您的位置:首页 > 移动开发 > Android开发

Android中自动接听电话的功能

2017-01-22 22:08 288 查看
最近,需要完成一个自动化测试工具,来测试一些模块的功能,其中有些功能需要接通电话后才可以使用,因为这个工具是完全自动化的,所以需要处理自动接听电话

在4.1以前Android是提供了接口可以直接调用接听电话的,而4.1以后google增加了访问控制,普通应用通过正常手段是无法实现该功能,因此,我们通过以下方法实现,比较简单。但注意,此方法编译的apk需要系统签名。

自动接听电话的接口answerRingingCall()定义在ITelephony.aidl之中,ITelephony.aidl为隐藏接口。本来TelephonyManager类中有方法getITelephony()可以或得到ITelephony的实例,但getITelephony()同样是隐藏方法,由于我们想直接在Eclipse编译apk,而不是在源码中编译,所以,我们将ITelephony.aidl拷贝到我们工程,进行改造后使用反射机制来调用answerRingingCall()方法。

首先,在工程中创建package,注意,目录必须和ITelephony.aidl所在源码路径一致,即com.android.internal.telephony,将ITelephony.aidl放在该目录下,去掉隐藏标签,提取需要使用的方法,类似如下代码:

package com.android.internal.telephony;

import android.os.Bundle;
interface ITelephony {
boolean endCall();
void dial(String number);
void answerRingingCall();
}


接着在AndroidManifest.xml中添加权限:

<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />


以上权限的意思,一目了然,因为“android.permission.MODIFY_PHONE_STATE"  权限是系统权限,所以apk才需要系统签名。

准备工作完成后,就可以编写代码了:

public class MainActivity extends Activity {

private static final String LOG_TAG = MainActivity.class.getName();
private ITelephony mTelephonyService;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

try {
TelephonyManager telephony = (TelephonyManager) getApplication()
.getSystemService(Context.TELEPHONY_SERVICE);
telephony.listen(new MyPhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE);
Class<?> c = Class.forName(telephony.getClass().getName());

Method m = c.getDeclaredMethod("getITelephony");
m.setAccessible(true);

mTelephonyService = (ITelephony) m.invoke(telephony);
} catch (Exception e) {
e.printStackTrace();
}
}

class MyPhoneStateListener extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
Log.i(LOG_TAG, "[Listener] Ringing State:" + incomingNumber);
if (mTelephonyService != null) {
try {
mTelephonyService.answerRingingCall();
} catch (RemoteException e) {
e.printStackTrace();
}
}
break;
case TelephonyManager.CALL_STATE_IDLE:
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
break;
}
super.onCallStateChanged(state, incomingNumber);
}
}


代码比较简单,首先获取TelephonyManager对象,向该对象中注册监听电话状态的listener,然后就用反射获取ITelephony对象。接下来实现listener的onCallStateChanged() 回调方法处理不同电话状态,在响铃状态调用answerRingingCall()方法就可以了。

对于电话的各种状态,android对普通应用提供的比较粗略,需要查看更详细的状态的话需要查看PreciseCallState类,但很不幸,这个类也是隐藏的。

另外,也可以通过receiver代替注册listener进行以上处理,整个实现代码的地址为:http://download.csdn.net/detail/u010538765/9743406
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Android