android 上層電話狀態的監聽
阿新 • • 發佈:2019-02-17
1,概述
做開發時,有時完全不利用Dialer.apk來開發撥號等功能,如何撥打/接聽/結束通話電話呢?電話來了又怎麼知道呢?現在分為2個部分一一到來。首先是撥打/接聽/結束通話等電話操作,然後監聽電話的狀態,並進行相應的處理,本文基於Android 5.1.
2, 電話操作
2.1 撥號
撥號最簡單了,直接發個廣播就可以了
private String callnumber = “10086”; // 比如 給移動客服打電話 Uri uri = getCallUri(callnumber); // 將所撥號碼進行格式化 Intent intentd = new Intent(); intentd.setAction(Intent.ACTION_CALL); intentd.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intentd.addFlags(Intent.FLAG_ACTIVITY_NO_USER_ACTION); intentd.setData(uri); startActivity(intentd); public static Uri getCallUri(String number) { if (number != null && (number.contains("@") || number.contains("%40"))) { return Uri.fromParts("sip", number, null); } return Uri.fromParts("tel", number, null); }
2.2 結束通話
利用反射機制呼叫telephonyManager的endCall方法進行結束通話。
private Object telephonyObject = null; TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); Class telManager = telephonyManager.getClass(); Method getITelephony = null; try { try { getITelephony = telManager .getDeclaredMethod("getITelephony"); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } getITelephony.setAccessible(true); telephonyObject = getITelephony.invoke(telephonyManager); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } try { if (null != telephonyObject) { Class telephonyClass = telephonyObject.getClass(); Method endCallMethod = telephonyClass.getMethod("endCall"); endCallMethod.setAccessible(true); endCallMethod.invoke(telephonyObject); } } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); }
2.3 接聽
實現接聽有多種方法,和上小節的結束通話操作一樣,可以直接利用反射機制來進行接聽;還有一種方法利用按鍵事件這個介面,通過傳送廣播的形式,實現接聽。
try { Runtime.getRuntime().exec("input keyevent " + Integer .toString(KeyEvent.KEYCODE_HEADSETHOOK)); } catch (IOException e) { String enforcedPerm = "android.permission.CALL_PRIVILEGED"; Intent btnDown = new Intent(Intent.ACTION_MEDIA_BUTTON) .putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent( KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_HEADSETHOOK)); Intent btnUp = new Intent(Intent.ACTION_MEDIA_BUTTON) .putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent( KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK)); sendOrderedBroadcast(btnDown, enforcedPerm); sendOrderedBroadcast(btnUp, enforcedPerm); }
3, 電話狀態的監聽
import java.lang.reflect.Method;
import android.app.Activity;
import android.app.Dialog;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.SystemClock;
import android.telephony.TelephonyManager;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Chronometer;
import android.widget.ImageView;
import android.widget.TextView;
public class PhoneBroadcastReceiver extends BroadcastReceiver {
private static final String TAG = "message";
private static boolean mIncomingFlag = false;
private static String mIncomingNumber = null;
private static boolean callover = false;
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {// 如果是撥打電話
mIncomingFlag = false;
String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
} else {
TelephonyManager tManager = (TelephonyManager)
context.getSystemService(Service.TELEPHONY_SERVICE);
switch (tManager.getCallState()) {
case TelephonyManager.CALL_STATE_RINGING: //來電狀態
mIncomingNumber = intent.getStringExtra("incoming_number");
••• }
break;
case TelephonyManager.CALL_STATE_OFFHOOK: //摘機狀態(接聽)
mIncomingNumber = intent.getStringExtra("incoming_number");
callover = true;
•••
break;
case TelephonyManager.CALL_STATE_IDLE:// 空閒狀態,沒有任何活動。(結束通話)
android.util.Log.d("fangc", " mIncomingNumber " + "guaduan");
if (mIncomingFlag||callover) {
mIncomingFlag = false;
callover = false;
•••
}
break;
}
}
}
}
在這四個狀態中,可以分別新增一些boolean值來確定是撥號/來電還是結束通話,接聽等狀態,然後在裡面分別進行不同的處理。
4, 結尾
最後不要忘記了在AdnroidManifest.xml 檔案中新增相關許可權
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
PhoneBroadcastReceiver類一定要註冊靜態廣播,而不是動態廣播。
<receiver android:name=".PhoneBroadcastReceiver">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.NEW_OUTGOING_CALL"/>
<action android:name="android.intent.action.PHONE_STATE"/>
</intent-filter>
</receiver>