在之前的这篇博客中,https://blog.csdn.net/huangbaokang/article/details/112334420
一、手工调用Service来拦截黑名单号码
我们讲解了手工挂断电话,使用的是AIDL,通过点击按钮来触发挂断电话的功能。接下来我们实现自动挂断电话,到达拦截黑名单电话的功能。
具体原理是通过广播接收器,通过注册开机的广播,启动一个挂断电话的服务即可,我们分两步,手工启动挂断电话的服务,此处不使用广播,后面将讲解。
布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >
<Button
android:id="@+id/btn_main_start"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="启动来电监听"
android:onClick="startListenCall" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="停止来电监听"
android:onClick="stopListenCall"
android:layout_below="@id/btn_main_start"
/>
</RelativeLayout>
处理Activity类,很简单,直接启动服务,和中断服务
package com.hbk.service;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void startListenCall(View v) {
startService(new Intent(this, ListenCallService.class));
}
public void stopListenCall(View v) {
stopService(new Intent(this, ListenCallService.class));
}
}
我定义ListenCallService类,并使用PhoneStateListener来监听不同打电话的状态,重点在处理响铃状态。
package com.hbk.service;
import java.lang.reflect.Method;
import com.android.internal.telephony.ITelephony;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
public class ListenCallService extends Service {
private TelephonyManager tm;
private PhoneStateListener listener = new PhoneStateListener() {
// 当通话状态发生改变时调用
/**
* Callback invoked when device call state changes.
*
* @see TelephonyManager#CALL_STATE_IDLE
* @see TelephonyManager#CALL_STATE_RINGING
* @see TelephonyManager#CALL_STATE_OFFHOOK
*/
public void onCallStateChanged(int state, String incomingNumber) {
switch (state) {
case TelephonyManager.CALL_STATE_IDLE:// 空闲 (挂断电话/未来电之前)
Log.e("TAG", "空闲 (挂断电话/未来电之前)");
break;
case TelephonyManager.CALL_STATE_RINGING:// 响铃
Log.e("TAG", "响铃");
// 如果来电电话是黑名单号(110), 就挂断电话
if ("110".equals(incomingNumber)) {
try {
endCall();
} catch (Exception e) {
e.printStackTrace();
}
}
break;
case TelephonyManager.CALL_STATE_OFFHOOK:// 接通
Log.e("TAG", "接通");
break;
default:
break;
}
}
};
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return null;
}
/**
* 挂断电话
* @throws Exception
*/
private void endCall() throws Exception {
// 通过反射调用隐藏的API
// 得到隐藏类的Class对象
Class c = Class.forName("android.os.ServiceManager");
// 得到方法所对应的Method对象
Method method = c.getMethod("getService", String.class);
// 调用方法
IBinder iBinder = (IBinder) method.invoke(null,
Context.TELEPHONY_SERVICE);
// 得到接口对象
ITelephony telephony = ITelephony.Stub.asInterface(iBinder);
// 结束通话
telephony.endCall();
}
@Override
public void onCreate() {
super.onCreate();
Log.e("TAG", "Service onCreate()");
// 得到电话管理器
tm = (TelephonyManager) this
.getSystemService(Context.TELEPHONY_SERVICE);
// 监听电话状态
tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e("TAG", "Service onDestroy()");
// 停止电话监听
tm.listen(listener, PhoneStateListener.LISTEN_NONE);
}
}
如上文件需要根据AIDL文件生成代码,才能在ListenCallService 中进行引用。
清单文件中增加如下两个权限
<!-- 挂断电话 -->
<uses-permission android:name="android.permission.CALL_PHONE"/>
<!-- 读取电话状态 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
并注册服务
<service android:name="com.hbk.service.ListenCallService"></service>
测试点击启动监听,然后在模拟器中对110进行打电话,发现没有电话呼入,但在通话记录里却可以看到记录。
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程
二、使用广播进行黑名单号码短信拦截
解析来我们介绍使用广播来实现黑名单号码的电话及短信拦截。
新建一个BootReceiver来接收开机完成广播的receiver
package com.hbk.service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
/**
* 接收开机完成广播的receiver
*
*/
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//启动电话监听的service
context.startService(new Intent(context, ListenCallService.class));
}
}
并在清单文件中增加如下权限
<!-- 接收开机完成广播的权限 -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
注册广播,action name是固定写法,记住即可
<receiver android:name="com.hbk.service.BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
工作中常用的广播
同理,我们定义一个拦截黑名单短信的receiver
package com.hbk.service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.telephony.SmsMessage;
import android.util.Log;
/**
* 接收来了短信的广播的receiver
*
*/
public class SmsReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//1. 得到intent短信数据, 并封装为短信对象smsMessage
Bundle extras = intent.getExtras();
Object[] pdus = (Object[])extras.get("pdus");
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[])pdus[0]);
//2. 取号码
String number = smsMessage.getOriginatingAddress();
String content = smsMessage.getMessageBody();
Log.e("TAG", number +" : "+content);
//3. 判断是否是黑名单号
if("110".equals(number)) {
//4. 如果是, 中断广播(拦截短信)
abortBroadcast();
Log.e("TAG", "拦截到一个黑名单短信");
}
}
}
在清单文件中进行配置
<receiver android:name="com.hbk.service.SmsReceiver">
<intent-filter android:priority="2147483647">
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
通过SmsMessage 对象去取出电话号码及短信内容。测试的话,先部署应用,然后关掉虚拟机,重新开机进行测试,开机的时候可以看到黑名单号码的广播接收器生效了。