android 接聽和掛斷實現方式


轉載
標簽:?

android

?

接聽

?

掛斷

?

it

分類:?android應用技巧

參考:android?來電接聽和掛斷?支持目前所有版本

?

注意:android2.3版本及以上不支持下面的自動接聽方法。

(會拋異常:java.lang.SecurityException: Neither user xxxxx nor current process hasandroid.permission.MODIFY_PHONE_STATE.)

原因:android2.3版本及以上android.permission.MODIFY_PHONE_STATE權限限制已經改為系統權限。

?普通應用程序已經無法調用,所以網上找到的那些如何使用android.permission.MODIFY_PHONE_STATE的文章均已失效,但仍有引用的辦法就是讓你的程序程序系統程序。一種就是預制到ROM中,另一種就是使用系統簽名。第一種我已經試驗通過,第二種還有待驗證。

http://kongweile.iteye.com/blog/1428033


言歸正傳,先說下如何使用映射機制實現自動接聽和掛斷

第一步:準備應用環境需要的系統包和aidl文件。



(1)在應用中創建包:android.telephony

android系統框架下的\framework\telephony\java\android\telephony目錄中的NeighboringCellInfo.aidl文件復制到上面創建的包(android.telephony )中;

(2)在應用中創建包:com.android.internal.telephony

android系統框架下的\framework\telephony\java\com\android\internal\telephony目錄中的ITelephony.aidl文件復制到上面創建的包(com.android.internal.telephony )中;





第二步:創建一個獲取ITelephony的方法

PhoneUtils.java
Java代碼
package com.zhouzijing.android.demo;

import java.lang.reflect.Method;
import com.android.internal.telephony.ITelephony;
import?android.telephony.TelephonyManager;

public class PhoneUtils {

public static ITelephony getITelephony(TelephonyManager telephony) throws Exception {
Method getITelephonyMethod = telephony.getClass().getDeclaredMethod("getITelephony");
getITelephonyMethod.setAccessible(true);//私有化函數也能使用
return (ITelephony)getITelephonyMethod.invoke(telephony);
}
}


第三步:創建電話廣播攔截器

MyPhoneBroadcastReceiver.java
Java代碼
package com.zhouzijing.android.demo;

import com.android.internal.telephony.ITelephony;
import?android.content.BroadcastReceiver;
import?android.content.Context;
import?android.content.Intent;
import?android.telephony.TelephonyManager;
import?android.util.Log;

public class MyPhoneBroadcastReceiver?extends BroadcastReceiver {

private final static String TAG = MyPhone.TAG;

@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.i(TAG, "[Broadcast]"+action);

//呼入電話
if(action.equals(MyPhone.B_PHONE_STATE)){
Log.i(TAG, "[Broadcast]PHONE_STATE");
doReceivePhone(context,intent);
}
}


public void doReceivePhone(Context context, Intent intent) {
String phoneNumber = intent.getStringExtra(
TelephonyManager.EXTRA_INCOMING_NUMBER);
TelephonyManager telephony = (TelephonyManager)context.getSystemService(
Context.TELEPHONY_SERVICE);
int state = telephony.getCallState();

switch(state){
case TelephonyManager.CALL_STATE_RINGING:
Log.i(TAG, "[Broadcast]等待接電話="+phoneNumber);
try {
ITelephony iTelephony = PhoneUtils.getITelephony(telephony);
iTelephony.answerRingingCall();//自動接通電話
//iTelephony.endCall();//自動掛斷電話
} catch (Exception e) {
Log.e(TAG, "[Broadcast]Exception="+e.getMessage(), e);
}
break;
case TelephonyManager.CALL_STATE_IDLE:
Log.i(TAG, "[Broadcast]電話掛斷="+phoneNumber);
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
Log.i(TAG, "[Broadcast]通話中="+phoneNumber);
break;
}
}

}




第四部:注冊電話廣播攔截器

MyPhone.java
Java代碼
package com.zhouzijing.android.demo;

import?android.app.Activity;
import?android.content.IntentFilter;
import?android.os.Bundle;
import?android.telephony.TelephonyManager;
import?android.util.Log;
import?android.view.View;

public class MyPhone extends Activity {
public final static String TAG = "MyPhone";

public final static String B_PHONE_STATE = TelephonyManager.ACTION_PHONE_STATE_CHANGED;

private MyPhoneBroadcastReceiver?mBroadcastReceiver;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_phone);
}

//按鈕1-注冊廣播
public void registerThis(View v) {
Log.i(TAG, "registerThis");
mBroadcastReceiver = new MyPhoneBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(B_PHONE_STATE);
intentFilter.setPriority(Integer.MAX_VALUE);
registerReceiver(mBroadcastReceiver, intentFilter);
}

//按鈕2-撤銷廣播
public void unregisterThis(View v) {
Log.i(TAG, "unregisterThis");
unregisterReceiver(mBroadcastReceiver);
?}
?}

第5步:在AndroidManifest.xml配置權限
Xml代碼
<uses-permission?android:name="android.permission.READ_PHONE_STATE" />
<uses-permission?android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission?android:name="android.permission.CALL_PHONE"/>
其中:
Java代碼
iTelephony.answerRingingCall();//自動接通電話

必須有權限?android.permission.MODIFY_PHONE_STATE


Java代碼
iTelephony.endCall();//自動掛斷電話

必須有權限?android.permission.CALL_PHONE


因為Android2.3以上增加了對permission?android.permission.MODIFY_PHONE_STATE 的限制,2.3之前的通過反射機制調用ITelephone的能力的做法已經不適用。
2.3上實現方式:
public synchronized void answerRingingCall() {

查詢系統PhoneAPP應用(PhoneGlobals.java)實現了對耳機插入、多媒體按鍵等通知的接受和處理。其中未發現有特殊的地方,個人認為,如果系統接收到此廣播應該可以進行接聽或掛斷操作。


???
????private void answerRingingCallWithBroadcast(Context context,TelephonyManager telmanager){ ?
????????AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); ?
????????//判斷是否插上了耳機 ?
????????if (! audioManager.isWiredHeadsetOn()) {?

???????//4.1以上系統限制了部分權限,?使用三星4.1版本測試提示警告:Permission Denial: not allowed to send broadcast?android.intent.action.HEADSET_PLUG from pid=1324, uid=10017

//這里需要注意一點,發送廣播時加了權限“android.permission.CALL_PRIVLEGED”,則接受該廣播時也需要增加該權限。但是4.1以上版本貌似這個權限只能系統應用才可以得到。測試的時候,自定義的接收器無法接受到此廣播,后來去掉了這個權限,設為NULL便可以監聽到了。


????????if(android.os.Build.VERSION.SDK_INT >=15 ){
????????????????Intent meidaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); ?
????????????????KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK); ?
????????????????meidaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT,keyEvent); ?
????????????????context.sendOrderedBroadcast(meidaButtonIntent, null); ?
????????}else{

// 以下適用于Android2.3及2.3以上的版本上 ,但測試發現4.1系統上不管用。
????????Intent localIntent1 = new Intent(Intent.ACTION_HEADSET_PLUG); ?
????????????????localIntent1.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); ?
????????????????localIntent1.putExtra("state", 1); ?
????????????????localIntent1.putExtra("microphone", 1); ?
????????????????localIntent1.putExtra("name", "Headset"); ?
????????????????context.sendOrderedBroadcast(localIntent1, ?"android.permission.CALL_PRIVILEGED"); ?
????????????????
????????????????Intent localIntent2 = new Intent(Intent.ACTION_MEDIA_BUTTON); ?
????????????????KeyEvent localKeyEvent1 = new KeyEvent(KeyEvent.ACTION_DOWN, ?KeyEvent.KEYCODE_HEADSETHOOK); ?
????????????????localIntent2.putExtra(Intent.EXTRA_KEY_EVENT, ??localKeyEvent1); ?
????????????????context. sendOrderedBroadcast(localIntent2, ?"android.permission.CALL_PRIVILEGED");?
????????????????
????????????????Intent localIntent3 = new Intent(Intent.ACTION_MEDIA_BUTTON); ?
????????????????KeyEvent localKeyEvent2 = new KeyEvent(KeyEvent.ACTION_UP, ?KeyEvent.KEYCODE_HEADSETHOOK); ?
????????????????localIntent3.putExtra(Intent.EXTRA_KEY_EVENT, ?localKeyEvent2); ?
????????????????context.sendOrderedBroadcast(localIntent3, ?"android.permission.CALL_PRIVILEGED"); ?
????????????????
????????????????Intent localIntent4 = new Intent(Intent.ACTION_HEADSET_PLUG); ?
????????????????localIntent4.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); ?
????????????????localIntent4.putExtra("state", 0); ?
????????????????localIntent4.putExtra("microphone", 1); ?
????????????????localIntent4.putExtra("name", "Headset"); ?
????????????????context.sendOrderedBroadcast(localIntent4, "android.permission.CALL_PRIVILEGED");
????????}
??????????????
????????} else { ?
????????????Intent meidaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON); ?
????????????KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK); ?
????????????meidaButtonIntent.putExtra(Intent.EXTRA_KEY_EVENT,keyEvent); ?
????????????context.sendOrderedBroadcast(meidaButtonIntent, null); ?
????????} ?
????}?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/387949.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/387949.shtml
英文地址,請注明出處:http://en.pswp.cn/news/387949.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Eclipse External Tool Configration Notepad++

Location&#xff1a; C:\Program Files\Notepad\notepad.exe Arguments&#xff1a;  ${resource_loc} 轉載于:https://www.cnblogs.com/rgqancy/p/9987610.html

利用延遲關聯或者子查詢優化超多分頁場景

2019獨角獸企業重金招聘Python工程師標準>>> MySQL并不是跳過offset行&#xff0c;而是取offsetN行&#xff0c;然后返回放棄前offset行&#xff0c;返回N行&#xff0c;那當offset 特別大的時候&#xff0c;效率就非常的低下&#xff0c;要么控制返回的總頁數&…

客戶流失_了解客戶流失

客戶流失Big Data Analytics within a real-life example of digital music service數字音樂服務真實示例中的大數據分析 Customer churn is a key predictor of the long term success or failure of a business. It is the rate at which customers are leaving your busine…

Java 動態加載class 并反射調用方法

反射方法&#xff1a; public static void main(String[] args) throws Exception { File filenew File("D:/classtest");//類路徑(包文件上一層) URL urlfile.toURI().toURL(); ClassLoader loadernew URLClassLoader(new URL[]{url});//創…

Nginx:Nginx limit_req limit_conn限速

簡介 Nginx是一個異步框架的Web服務器&#xff0c;也可以用作反向代理&#xff0c;負載均衡器和HTTP緩存&#xff0c;最常用的便是Web服務器。nginx對于預防一些攻擊也是很有效的&#xff0c;例如CC攻擊&#xff0c;爬蟲&#xff0c;本文將介紹限制這些攻擊的方法&#xff0c;可…

快速數據庫框架_快速學習新的數據科學概念的框架

快速數據庫框架重點 (Top highlight)數據科學 (Data Science) Success in data science and software engineering depends on our ability to continuously learn new models and concepts.數據科學和軟件工程的成功取決于我們不斷學習新模型和概念的能力。 Both domains are…

Linux實戰教學筆記12:linux三劍客之sed命令精講

第十二節 linux三劍客之sed命令精講 標簽&#xff08;空格分隔&#xff09;&#xff1a; Linux實戰教學筆記-陳思齊 ---更多資料點我查看 1&#xff0c;前言 我們都知道&#xff0c;在Linux中一切皆文件&#xff0c;比如配置文件&#xff0c;日志文件&#xff0c;啟動文件等等。…

activiti 為什么需要采用樂觀鎖?

樂觀鎖 為什么需要采用樂觀鎖&#xff1f; 由于activiti一個周期的transaction時間可能比較長&#xff0c;且同一流程實例中存在任務并發執行等場景。設計者將update、insert、delete事務性的操作推遲至command結束時完成&#xff0c;這樣盡量降低鎖沖突的概率&#xff0c;由…

Python實現三級菜單(字典和列表的使用)

menu { 北京: { 海淀: { 五道口: { soho: {}, 網易: {}, google: {} }, 中關村: { 愛奇藝: {}, 汽車之家: {}, 優酷: {} …

停止使用p = 0.05

How many of you use p0.05 as an absolute cut off? p ≥ 0.05 means not significant. No evidence. Nada. And then p < 0.05 great it’s significant. This is a crude way of using p-values, and hopefully I will convince you of this.你們中有多少人使用p 0.05作…

centos7系統根目錄擴容

比如 點擊了后 點擊創建虛擬磁盤 選擇一個 20G 然后啟動虛擬機使用fdisk查看所有的磁盤 看是否新增了一個20G的硬盤 [rootlocalhost ~]# fdisk -l磁盤 /dev/sda&#xff1a;8589 MB, 8589934592 字節&#xff0c;16777216 個扇區 Units 扇區 of 1 * 512 512 bytes 扇區大小(…

instrumentation模擬很多activity的操作

android.app.Instrumentation好像原來是用來做測試的, 可以用來模擬很多activity的操作 主要代碼如下 如果在文本框中輸入24,或者25 點擊按鈕就能模擬音量加減鍵 鍵值可以查看android.view.KeyEvent [java] view plaincopy package com.qefee.testinstrumentation; import…

成像數據更好的展示_為什么更多的數據并不總是更好

成像數據更好的展示Over the past few years, there has been a growing consensus that the more data one has, the better the eventual analysis will be.在過去的幾年中&#xff0c;越來越多的共識是&#xff0c;數據越多&#xff0c;最終的分析就越好。 However, just a…

支付寶架構

支付寶系統架構圖如下&#xff1a; 支付寶架構文檔有兩個搞支付平臺設計的人必須仔細揣摩的要點。 一個是賬務處理。在記賬方面&#xff0c;涉及到內外兩個子系統&#xff0c;外部子系統是單邊賬&#xff0c;滿足線上性能需求&#xff1b;內部子系統走復式記賬&#xff0c;滿足…

怎樣可以跨進程測試

在Android系統下模擬鼠標鍵盤等輸入設備&#xff0c;網絡上資料非常多。但不少是人云亦云&#xff0c;甚至測試都不愿測試一下就抄上來了。這次寫一點體會&#xff0c;當作拋磚引玉。0. 背景知識&#xff1a;眾所周知&#xff0c;Android是將Framework架在Linux之上的系統。Lin…

Android Studio 導入新工程項目

1 導入之前先修改工程下相關文件 1.1 只需修改如下三個地方1.2 修改build.gradle文件 1.3 修改gradle/wrapper/gradle-wrapper.properties 1.4 修改app/build.gradle 2 導入修改后的工程 2.1 選擇File|New|Import Project 2.2 選擇修改后的工程 如果工程沒有變成AS符號&#xf…

馬蜂窩張矗:績效考核是為了激發工作潛力,而不是逃避問題

3 月 23 日&#xff0c;由高端技術領導者社交平臺 TGO 鯤鵬會主辦的 GTLC 全球技術領導峰會分站首站在北京舉行。會上馬蜂窩技術副總裁 \u0026amp; TGO 鯤鵬會會員張矗發表了主題為“我在馬蜂窩的技術管理實踐”的演講。本文根據其演講整理而成。大家好&#xff0c;我是來自馬蜂…

vue domo網站_DOMO與Tableau-逐輪

vue domo網站Let me be your BI consultant. Best yet, let me be your free consultant on the following question:讓我成為您的BI顧問。 最好的是&#xff0c;讓我成為您的免費顧問 &#xff0c;解決以下問題&#xff1a; DOMO vs. Tableau — What should I use?DOMO vs.…

fiddler抓包1-抓小程序https包

抓小程序包和抓app包是一樣的操作方法&#xff1b;安卓用fiddler&#xff0c;ios用charles&#xff1b; 一、環境準備 1.電腦已裝最新版fiddler 2.手機和電腦在同一局域網 二、fiddler設置 1.fiddler>Tools>Options>HTTPS 勾選Capture HTTPS CONNECTs 及下邊的子項&am…

多態使用的前提

1&#xff1a;必須是繼承&#xff08;extends&#xff09;&#xff0c;實現&#xff08;implements&#xff09; 才行2&#xff1a;必須要重寫&#xff08;覆蓋&#xff09;父類的方法。轉載于:https://www.cnblogs.com/liyunchuan/p/10663788.html