Android拦截电话与短信(电话拒接/短信拒收)
16lz
2021-01-25
前段时间领导说了这样一个需求:对特定的号码电话进行拦截、短信拒收,在百度了查阅了很多的资料,结果有点不尽人意。特别是AIDL通信接口废了老大劲。直接上过程
- 创建aidl通信接口直接在main目录新建aldl类型文件ITelephony即可,自动生成包名等等如图所示此处有坑:网上基本上都是让这样写
interface ITelephony { boolean endCall(); void answerRingingCall();}
这里导致有可能会导致项目编译错误,这里最好还是不要去网上粘贴aidl包名和ITelephony,尽量自己创建不要懒
// ITelephony.aidlpackage com.android.internal.telephony;// Declare any non-default types here with import statementsinterface ITelephony { /** * Demonstrates some basic types that you can use as parameters * and return values in AIDL. */ void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,double aDouble, String aString); boolean endCall(); void answerRingingCall();}
如果编译不通过重新编译一下就好。
根据需求需要配置权限如下:
我这里直接贴代码,注释我会写清楚的
import androidx.annotation.NonNull;import androidx.annotation.RequiresApi;import androidx.appcompat.app.AppCompatActivity;import androidx.core.app.ActivityCompat;import android.Manifest;import android.annotation.SuppressLint;import android.app.Service;import android.content.BroadcastReceiver;import android.content.ContentResolver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.content.pm.PackageManager;import android.database.Cursor;import android.media.AudioManager;import android.net.Uri;import android.os.Build;import android.os.Bundle;import android.provider.CallLog;import android.provider.ContactsContract;import android.telephony.SmsMessage;import android.telephony.TelephonyManager;import android.util.Log;import java.lang.reflect.Method;import java.util.ArrayList;import java.util.List;public class MainActivity extends AppCompatActivity { private static String[] PERMISSIONS_STORAGE = { android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.CALL_PHONE , Manifest.permission.RECEIVE_SMS, Manifest.permission.READ_CONTACTS, Manifest.permission.WRITE_SETTINGS,Manifest.permission.READ_CALL_LOG, Manifest.permission.WRITE_CALL_LOG}; private static final int REQUEST_PERMISSION_CODE = 666; private TelephonyManager telMgr; private IncomingCallReceiver mIncomingCallReceiver; @RequiresApi(api = Build.VERSION_CODES.N) @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //动态获取权限 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(MainActivity.this, PERMISSIONS_STORAGE, REQUEST_PERMISSION_CODE); } } //注册广播 mIncomingCallReceiver = new IncomingCallReceiver(); IntentFilter mIntentFilter = new IntentFilter(); //拦截电话 mIntentFilter.addAction("android.intent.action.PHONE_STATE"); //拦截短信 mIntentFilter.addAction("android.provider.Telephony.SMS_RECEIVED"); //注册BroadcastReceiver registerReceiver(mIncomingCallReceiver, mIntentFilter); } //广播接收器 public class IncomingCallReceiver extends BroadcastReceiver { @SuppressLint("MissingPermission") @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); ContentResolver resolver = getContentResolver(); if ("android.intent.action.PHONE_STATE".equals(action)) { //拦截电话 telMgr = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE); switch (telMgr.getCallState()) { // 当电话呼入时 case TelephonyManager.CALL_STATE_RINGING: String number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER); Log.e("111111111111-----------", "拦截电话2:" + number); //我这里是获取手机通讯录的联系人,如果是呼入电话是手机联系人就不拦截,反之你懂的,如果嫌麻烦当然也可以只设置一个号码 ArrayList list = getPhoneNum(); Log.e("111111111111-----------", "list:" + list.toString()); if (!list.contains(number)) { AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); //先静音 mAudioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT); //这里就是aldl通讯接口 挂断电话 endCall(); // 删除该呼入电话系统通话记录 if (null != resolver) resolver.delete(CallLog.Calls.CONTENT_URI, "number=?", new String[]{number}); //恢复正常铃声 mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL); } break; //电话被挂起 case TelephonyManager.CALL_STATE_OFFHOOK: break; //手机空闲了 case TelephonyManager.CALL_STATE_IDLE: break; } } //拦截短信else if ("android.provider.Telephony.SMS_RECEIVED".equals(action)) { //获取短信信息 SmsMessage sms = getMessagesFromIntent(intent)[0]; //取得电话号码 String number = sms.getOriginatingAddress(); Log.e("111111111111-----------", "拦截短信2:" + number); //把国家代码去除掉 number = trimSmsNumber("+86", number); if (!getPhoneNum().contains(number)) { //中断短信推送 this.abortBroadcast(); // 删除系统短信 if (null != resolver) resolver.delete(Uri.parse("content://sms/"), "address=? or address = ?", new String[] {number, "+86" + number}); } } } } //获取短信内容 public final static SmsMessage[] getMessagesFromIntent(Intent intent) { Object[] messages = (Object[]) intent.getSerializableExtra("pdus"); byte[][] pduObjs = new byte[messages.length][]; for (int i = 0; i < messages.length; i++) { pduObjs[i] = (byte[]) messages[i]; } byte[][] pdus = new byte[pduObjs.length][]; int pduCount = pdus.length; SmsMessage[] msgs = new SmsMessage[pduCount]; for (int i = 0; i < pduCount; i++) { pdus[i] = pduObjs[i]; msgs[i] = SmsMessage.createFromPdu(pdus[i]); } return msgs; } //去除国家代码 public final static String trimSmsNumber(String prefix, String number) { String s = number; if (prefix.length() > 0 && number.startsWith(prefix)) { s = number.substring(prefix.length()); } return s; } /** * 挂断电话 */ private void endCall() { Class c = TelephonyManager.class; try { Method getITelephonyMethod = c.getDeclaredMethod("getITelephony", (Class[]) null); getITelephonyMethod.setAccessible(true); ITelephony iTelephony = null; iTelephony = (ITelephony) getITelephonyMethod.invoke(telMgr, (Object[]) null); //挂断电话 iTelephony.endCall(); } catch (Exception e) { //如果有异常查看动态权限有没有遗漏 Log.e("111111111111-----------", "Exception:" + e); } } //权限请求回调,如果返回无权限,卸载重装即可 @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { switch (requestCode) { case REQUEST_PERMISSION_CODE: if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { Log.e("111111111111-----------", "有权限"); } else { Log.e("111111111111-----------", "无权限"); } } } //获取所有联系人 private ArrayList getPhoneNum() { ArrayList numList = new ArrayList(); //得到ContentResolver对象 ContentResolver cr = getContentResolver(); //取得电话本中开始一项的光标 Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, null, null, null, null); while (cursor.moveToNext()) { // 取得联系人ID String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); Cursor phone = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, null, null); // 取得电话号码(可能存在多个号码) while (phone.moveToNext()) { String strPhoneNumber = phone.getString(phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); String str1 = strPhoneNumber.replaceAll(" ", ""); String str2 = str1.replaceAll("-", ""); numList.add(str2); } phone.close(); } cursor.close(); return numList; } @Override protected void onDestroy() { super.onDestroy(); //注销广播 if (null != mIncomingCallReceiver) unregisterReceiver(mIncomingCallReceiver); }}
好嘞这样就可以了,可以根据自己的需求改吧改吧就可以用了。目前在我的真机上的测试效果如下:
手机通讯录外的号码呼入拒接,短信拒收(在信息里面也找不到痕迹)
更多相关文章
- 浅入浅出 Android(安卓)安全:第四章 Android(安卓)框架层安全
- Android(安卓)Zxing集成
- 关于Android(安卓)5.0 安装部分应用失败解决方案
- Android权限管理详解
- Android(安卓)限制textview Edittext 只能输入电话号码和特定字
- Android(安卓)运行时权限申请之电话权限(兼容6.0以上)
- Android动态权限申请
- Android(安卓)系统 root 破解原理分析
- Eclipse如何快速调试系统App(具有系统权限的Android(安卓)App)即Ec