本帖最后由 wushaominkk 于 2018-3-15 16:06 编辑
来电拒接这个应用的比较广泛,通讯录黑名单用的比较多,而来电自动接听由于安全性,4.1以上的系统已经被禁用了.但是android系统还是有漏洞,这里给大家分析下原理,请勿用于不法操作!
低版本实现来电接听和拒接:
新建ITelephony.aidl文件:
[Java] 纯文本查看 复制代码 // ITelephony.aidl
package com.android.internal.telephony;
// Declare any non-default types here with import statements
interface ITelephony {
/**
* Demonstrates some basic types that you can use as parameters
* and return values in AIDL.
*/
boolean
void answerRingingCall();
}
接听/挂断电话的方法在接口ITelephony.java里面,而这个接口时隐藏的,也就是sdk开发是看不到这个接口的。(注意包名不能改),系统会在gen目录下自动生成ITelephony.java这个接口文件。只要我们获得了ITelephony的实例对象就可以使用endCall()自动挂断和answerRingingCall();自动接听方法了!
因为 ITelephony对象是以一个系统服务我们只能通过反射来获取该对象,直接贴代码吧:
[Java] 纯文本查看 复制代码 Method method = Class.forName("android.os.ServiceManager")
.getMethod("getService", String.class);
IBinder binder = (IBinder) method.invoke(null, new Object[]{TELEPHONY_SERVICE});
ITelephony telephony = ITelephony.Stub.asInterface(binder);
通过Binder机制得到的IBinder对象binder转化成ITelephony对象!
最后,我们还需要在AndroidManifest.xml里面配置下权限:
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE"/>然后获取TelephonyManager对象对电话状态进行监听,直接上代码吧[Java] 纯文本查看 复制代码 //获取电话服务
mTelephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
mTelephonyManager.listen(new MyPhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE); [Java] 纯文本查看 复制代码 /***
* 继承PhoneStateListener类,我们可以重新其内部的各种监听方法
*然后通过手机状态改变时,系统自动触发这些方法来实现我们想要的功能
*/
private class MyPhoneStateListener extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:
result = "手机空闲起来了";
break;
case TelephonyManager.CALL_STATE_RINGING:
result = "手机铃声响了,来电号码:" + incomingNumber;
break;
case TelephonyManager.CALL_STATE_OFFHOOK:
result = "电话被挂起了";
default:
break;
}
//Toast.makeText(MyBroadCast.this, ""+result, Toast.LENGTH_SHORT).show();
//textView.setText(result);
super.onCallStateChanged(state, incomingNumber);
}
高版本实现思路:4.1以上系统对answerRingingCall()方法,增加权限检查。只有系统进程才有权限执行这个方法,按照以上的操作编译会报错!有以上2个思路,既然是系统进程才能实现,那么我们伪装成系统APK,在该版本的源码下编译用系统签名打包,植入到sysytem就可以了,这种方法难度比较大,而且有局限性,本人没有试过,按照理论应该是可以实现的!第二种方法android会提供这个MediaButtonBroadcastReceiver广播接收器,这个广播接收器是为了监听耳机上接听电话那个按钮的,来电时只要按一下,就可以接听电话,接着就会调用MediaButtonBroadcastReceiver广播接收器。我们的思路是模拟耳机按键然后发出一条广播,让MediaButtonBroadcastReceiver广播接收器接收,从而达到自动接听的目的!
代码跟之前的一样监听TelephonyManager.CALL_STATE_RINGING来电事件,直接上代码:
[Java] 纯文本查看 复制代码 //注册模拟耳机接听电话广播
IntentFilter mediaButtonIntentFilter = new IntentFilter(Intent.ACTION_MEDIA_BUTTON);
registerReceiver(mMediaButtonReceiver, mediaButtonIntentFilter);
//TelephonyManager.CALL_STATE_RINGING中发送广播
[Java] 纯文本查看 复制代码 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);
sendOrderedBroadcast(meidaButtonIntent, null);
KeyEvent keyEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_HEADSETHOOK);就是模拟耳机按键动作
然后接收广播,判断耳机按键动作开启自动接听电话
[Java] 纯文本查看 复制代码 protected class MediaButtonBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
KeyEvent event = (KeyEvent) intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if ((event != null) && (event.getKeyCode() == KeyEvent.KEYCODE_HEADSETHOOK)) {
//boolean consumed = PhoneUtils.handleHeadsetHook(phone, event);
//answerCall(phone.getRingingCall());
Method method = null;
try {
method = Class.forName("android.os.ServiceManager")
.getMethod("getService", String.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
IBinder binder = null;
try {
binder = (IBinder) method.invoke(null, new Object[]{TELEPHONY_SERVICE});
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
ITelephony telephony = ITelephony.Stub.asInterface(binder);
try {
telephony.answerRingingCall();
} catch (RemoteException e) {
e.printStackTrace();
}
} else {
}
}
}
|