Android挂断电话流程

  • 近期在友盟上看到许多关于挂断电话导致崩溃的问题,如下异常
    java.lang.NoSuchMethodError: No interface method endCall()Z in class Lcom/android/internal/telephony/ITelephony; or its super classes (declaration of 'com.android.internal.telephony.ITelephony' appears in /system/framework/framework.jar!classes3.dex)
	at com.lifesense.ble.tools.PhoneCall.stopCall(PhoneCall.java:45)
	at com.lifesense.ble.protocol.ProtocolCommand.receivePhoneCommand(ProtocolCommand.java:384)
	at com.lifesense.ble.protocol.worker.sync.PedometerWorker$2.onCharacteristicChange(PedometerWorker.java:467)
	at com.lifesense.ble.protocol.worker.BaseDeviceWorker.postCharacteristicChange(BaseDeviceWorker.java:1288)
	at com.lifesense.ble.system.gatt.BluetoothGattHandler$2.onCharacteristicChanged(BluetoothGattHandler.java:368)
	at android.bluetooth.BluetoothGatt$1$8.run(BluetoothGatt.java:478)
	at android.bluetooth.BluetoothGatt.runOrQueueCallback(BluetoothGatt.java:780)
	at android.bluetooth.BluetoothGatt.access$200(BluetoothGatt.java:41)
	at android.bluetooth.BluetoothGatt$1.onNotify(BluetoothGatt.java:472)
	at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:306)
	at android.os.Binder.execTransactInternal(Binder.java:1021)
	at android.os.Binder.execTransact(Binder.java:994)
  • 此问题是报此方法不存在,查看手机版本信息发现都发生Android10的设备上,网上很少有关于此问题的描述,在现在的实现中,是根据反射系统API来实现挂断电话,但在API29后Google增加了对反射的限制,在高版本继续使用反射会导致更新未知问题。
  • 通过查看资料在高版本上可以TelecomManager来实现挂断电话的需求,此版本在API28及以上才能有效,且需要ANSWER_PHONE_CALLS的权限,在没有权限的情况下会提示SecurityException。
  • 可以根据下面代码进行兼容高版本的问题,在API28及以上使用TelecomManager使用endCall方法来挂断电话,API28及以下使用反射来挂断电话
//在项目中建com.android.internal.telephony包,创建ITelephony.aidl文件,以用反射实现挂断电话功能
package com.android.internal.telephony;

interface ITelephony{

    boolean endCall();

    void answerRingingCall();

}
	/**
	 * 挂断电话	android 9 及以上  可以使用系统api来挂断电话 android 9 及以下 使用反射来挂断电话
	 * @param context
	 * @return
	 */
	public static boolean stopCall(Context context) {
		if(context == null) {
			return false;
		}
		if (Build.VERSION.SDK_INT >= 28) { //android 9及以上商用此方式挂断电话
			try {
				if(context.checkSelfPermission(Manifest.permission.ANSWER_PHONE_CALLS) == PackageManager.PERMISSION_GRANTED) {
					TelecomManager manager = (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
					return manager.endCall();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			if(Build.VERSION.SDK_INT > 28) {	//android 10 挂断电话使用反射存在NoSuchMethodError问题
				return false;
			}
		}
		boolean result = false;
		String msg=null;
		try 
		{
			ITelephony iTelephony = getITelephony(context); 
			if(iTelephony==null)
			{
				msg="failed to hang up,is null";
				logMessage(msg,false);
				return false;
			}
			// 结束电话
			result = iTelephony.endCall();
			if (!result) {
				boolean isPermiss = PermissionUtils.checkPermission(context, Manifest.permission.CALL_PHONE);
				logMessage("result false isPermiss:" + isPermiss, false);
			}
			msg="telephony end call results="+result;
			logMessage(msg,result);
		} catch (Exception e)
		{
			e.printStackTrace();
			String className=null;
			if(e.getClass()!=null)
			{
				className=e.getClass().getName()+e.getMessage();

			}
			result=PermissionUtils.checkPermission(context, Manifest.permission.CALL_PHONE);
			msg="failed to hang up,has exception >>"+className+"("+result+")";
			logMessage(msg,false);
			return false;
		}
		return result;
	}
	
	
private static ITelephony getITelephony(Context context) {
		IBinder binder = null;
		Method method = null;
		ITelephony telephony=null;
		try 
		{
			Class classObj = Class.forName("android.os.ServiceManager");
			method = classObj.getMethod("getService", String.class);
			binder = (IBinder) method.invoke(null, new Object[] { "phone" });
			telephony = ITelephony.Stub.asInterface(binder);
		} catch (Exception e1) 
		{
			e1.printStackTrace();
			String className=null;
			if(e1.getClass()!=null)
			{
				className=e1.getClass().getName();
			}
			return null;
		}
		return telephony;
	}

你可能感兴趣的:(Android)