Android通过AIDL实现接听电话、挂断电话操作 | 拨打电话

开发中需求永远都是在不断的超越预期而且也越来越变态,但是呢你做为一个开发还是要想尽办法去实现的。

Android中拨打电话功能是很轻松的只需要几行代码即可,如下:

  • 首先还是得加上权限这个东西(或者动态申请)
<!--拨打电话-->
<uses-permission android:name="android.permission.CALL_PHONE" />
<!--接听、挂断电话-->
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
  • 使用Intent调用拨打电话意图
/**
 * 拨打电话
 *
 * @param number 联系人号码
 * @return
 */
public void callPhone(String number) {
    //Intent.ACTION_CALL是直接拨打
    //Intent.ACTION_DIAL是调起拨号界面
    Intent intent = new Intent(Intent.ACTION_CALL);
    intent.setData(Uri.parse("tel:" + number.trim()));
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
}

可以看到拨打一个电话还是很简单的、那要怎么样接听和挂掉电话呢,这里就要使用到AIDL了调用系统层来执行,这样就可以达到我们的功能了。

系统在frameworks层定义好了AIDL(ITelephony.aidl)接口然后提供给电话应用进行使用,这样就完成了电话应用里面的一些操作。
源码路径为:../frameworks/base/telephony/java/com/android/internal/telephony/ITelephony.aidl
综上所述,在我们应用中通过aidl去与它通信即可。

在项目中创建ITelephony.aidl文件 需要注意的是这里的包名和函数名称必须和frameworks层定义的一样,如下步骤:

  • 创建aidl文件目录
    这里写图片描述
  • 创建ITelephony.aidl文件,并声明 接听和挂断函数
    这里写图片描述

这个文件中,里面有很多函数这里只将用到的函数复写了源码中还定义了许多其它的函数,有需要的可以查看源码了解下。

package com.android.internal.telephony;

interface ITelephony{

    //挂断电话
    boolean endCall();

    //接听电话
    void answerRingingCall();
}

创建好后 你需要点击rebuild进行编译生成对应的java文件,接下来就只要调用函数就可以了。

  • 挂断电话操作:
/**
 * 挂断电话
 */
public void endCall() {
    try {
        Method method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
        IBinder binder = (IBinder) method.invoke(null, new Object[]{Context.TELEPHONY_SERVICE});
        ITelephony telephony = ITelephony.Stub.asInterface(binder);
        telephony.endCall();
    } catch (Exception e) {
        e.printStackTrace();
    }
}


  • 接听电话:

在4.1以上的版本中,谷歌给这个方法的调用设置了权限,如果不是系统应用,会收到permissDeny的异常 (在HUAWEI Che2-TL00,Android API 19)上测试并没有抛出异常,所以为了适配机型还是将其加上

/**
 * 接听电话
 */
public void answerRingingCall() {
    try {
        Method method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);
        IBinder binder = (IBinder) method.invoke(null, new Object[]{Context.TELEPHONY_SERVICE});
        ITelephony telephony = ITelephony.Stub.asInterface(binder);
        telephony.answerRingingCall();
    } catch (Exception e) {
        e.printStackTrace();
        //4.1系统以后的电话接听
        answerRingingCall_4_1(context);
    }
}

/**
 * 4.1版本以上接听电话
 */
private void answerRingingCall_4_1(Context context) {
    AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    //模拟无线耳机的按键来接听电话
    // for HTC devices we need to broadcast a connected headset
    boolean broadcastConnected = "HTC".equalsIgnoreCase(Build.MANUFACTURER) && !audioManager.isWiredHeadsetOn();
    if (broadcastConnected) {
        broadcastHeadsetConnected(context);
    }
    try {
        try {
            Runtime.getRuntime().exec("input keyevent " +
                    Integer.toString(KeyEvent.KEYCODE_HEADSETHOOK));
        } catch (IOException e) {
            // Runtime.exec(String) had an I/O problem, try to fall back
            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));
            context.sendOrderedBroadcast(btnDown, enforcedPerm);
            context.sendOrderedBroadcast(btnUp, enforcedPerm);
        }
    } finally {
        if (broadcastConnected) {
            broadcastHeadsetConnected(context);
        }
    }
}
/**
 * 对HTC的手机,需要进行一点特殊的处理,也就是通过广播的形式,让手机误以为连上了无线耳机。
 */
private void broadcastHeadsetConnected(Context context) {
    Intent i = new Intent(Intent.ACTION_HEADSET_PLUG);
    i.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
    i.putExtra("state", 0);
    i.putExtra("name", "mysms");
    try {
        context.sendOrderedBroadcast(i, null);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

总是被一些偏的功能搞得脑壳疼……

猜你喜欢

转载自blog.csdn.net/a_zhon/article/details/80640669