首页 > 代码库 > Android 手机卫士7--黑名单拦截

Android 手机卫士7--黑名单拦截

技术分享

1,黑名单数据库创建

三个字段(_id 自增长字段 phone 黑名单号码 mode 拦截类型)
创建表的sql语句
create table blacknumber (_id integer primary key autoincrement , phone varchar(20), mode varchar(5));
结合项目,去创建数据库,以及相应的表

2.BlackNumberDao 

 BlackNumberDao单例模式

技术分享
  1 package com.itheima.mobilesafe74.db.dao;
  2 
  3 import java.util.ArrayList;
  4 import java.util.List;
  5 
  6 import android.content.ContentValues;
  7 import android.content.Context;
  8 import android.database.Cursor;
  9 import android.database.sqlite.SQLiteDatabase;
 10 
 11 import com.itheima.mobilesafe74.db.BlackNumberOpenHelper;
 12 import com.itheima.mobilesafe74.db.domain.BlackNumberInfo;
 13 
 14 public class BlackNumberDao {
 15     private BlackNumberOpenHelper blackNumberOpenHelper;
 16     //BlackNumberDao单例模式
 17     //1,私有化构造方法
 18     private BlackNumberDao(Context context){
 19         //创建数据库已经其表机构
 20         blackNumberOpenHelper = new BlackNumberOpenHelper(context);
 21     }
 22     //2,声明一个当前类的对象
 23     private static BlackNumberDao blackNumberDao = null;
 24     //3,提供一个静态方法,如果当前类的对象为空,创建一个新的
 25     public static BlackNumberDao getInstance(Context context){
 26         if(blackNumberDao == null){
 27             blackNumberDao = new BlackNumberDao(context);
 28         }
 29         return blackNumberDao;
 30     }
 31     
 32     /**增加一个条目
 33      * @param phone    拦截的电话号码
 34      * @param mode    拦截类型(1:短信    2:电话    3:拦截所有(短信+电话))
 35      */
 36     public void insert(String phone,String mode){
 37         //1,开启数据库,准备做写入操作
 38         SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();
 39 
 40         ContentValues values = new ContentValues();
 41         values.put("phone", phone);
 42         values.put("mode", mode);
 43         db.insert("blacknumber", null, values);
 44         
 45         db.close();
 46     }
 47     
 48     /**从数据库中删除一条电话号码
 49      * @param phone    删除电话号码
 50      */
 51     public void delete(String phone){
 52         SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();
 53 
 54         db.delete("blacknumber", "phone = ?", new String[]{phone});
 55         
 56         db.close();
 57     }
 58     
 59     /**
 60      * 根据电话号码去,更新拦截模式
 61      * @param phone    更新拦截模式的电话号码
 62      * @param mode    要更新为的模式(1:短信    2:电话    3:拦截所有(短信+电话)
 63      */
 64     public void update(String phone,String mode){
 65         SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();
 66 
 67         ContentValues contentValues = new ContentValues();
 68         contentValues.put("mode", mode);
 69         
 70         db.update("blacknumber", contentValues, "phone = ?", new String[]{phone});
 71         
 72         db.close();
 73     }
 74     
 75     /**
 76      * @return    查询到数据库中所有的号码以及拦截类型所在的集合
 77      */
 78     public List<BlackNumberInfo> findAll(){
 79         SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();
 80 
 81         Cursor cursor = db.query("blacknumber", new String[]{"phone","mode"}, null, null, null, null, "_id desc");
 82         List<BlackNumberInfo> blackNumberList = new ArrayList<BlackNumberInfo>();
 83         while(cursor.moveToNext()){
 84             BlackNumberInfo blackNumberInfo = new BlackNumberInfo();
 85             blackNumberInfo.phone = cursor.getString(0);
 86             blackNumberInfo.mode = cursor.getString(1);
 87             blackNumberList.add(blackNumberInfo);
 88         }
 89         cursor.close();
 90         db.close();
 91         
 92         return blackNumberList;
 93     }
 94     
 95     /**
 96      * 每次查询20条数据
 97      * @param index    查询的索引值
 98      */
 99     public List<BlackNumberInfo> find(int index){
100         SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();
101 
102         Cursor cursor = db.rawQuery("select phone,mode from blacknumber order by _id desc limit ?,20;", new String[]{index+""});
103         
104         List<BlackNumberInfo> blackNumberList = new ArrayList<BlackNumberInfo>();
105         while(cursor.moveToNext()){
106             BlackNumberInfo blackNumberInfo = new BlackNumberInfo();
107             blackNumberInfo.phone = cursor.getString(0);
108             blackNumberInfo.mode = cursor.getString(1);
109             blackNumberList.add(blackNumberInfo);
110         }
111         cursor.close();
112         db.close();
113         
114         return blackNumberList;
115     }
116     
117     /**
118      * @return    数据库中数据的总条目个数,返回0代表没有数据或异常
119      */
120     public int getCount(){
121         SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();
122         int count = 0;
123         Cursor cursor = db.rawQuery("select count(*) from blacknumber;", null);
124         if(cursor.moveToNext()){
125             count = cursor.getInt(0);
126         }
127         
128         cursor.close();
129         db.close();
130         return count;
131     }
132     
133     /**
134      * @param phone    作为查询条件的电话号码
135      * @return    传入电话号码的拦截模式    1:短信    2:电话    3:所有    0:没有此条数据
136      */
137     public int getMode(String phone){
138         SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();
139         int mode = 0;
140         Cursor cursor = db.query("blacknumber", new String[]{"mode"}, "phone = ?", new String[]{phone}, null, null,null);
141         if(cursor.moveToNext()){
142             mode = cursor.getInt(0);
143         }
144         
145         cursor.close();
146         db.close();
147         return mode;
148     }
149 }
BlackNumberDao

3,加载更多的触发条件
1.监听状态改变
2.滚动到最底部,最后一个listView的条目可见
3.滚动状态发生改变 滚动------>停止(空闲)

加载下一页数据完成后,需要添加到上一页数据的最后面 20 40 60 80 100

//监听其滚动状态
lv_blacknumber.setOnScrollListener(new OnScrollListener() {
	//滚动过程中,状态发生改变调用方法()
	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
//				OnScrollListener.SCROLL_STATE_FLING	飞速滚动
//				OnScrollListener.SCROLL_STATE_IDLE	 空闲状态
//				OnScrollListener.SCROLL_STATE_TOUCH_SCROLL	拿手触摸着去滚动状态
		
		if(mBlackNumberList!=null){
			//条件一:滚动到停止状态
			//条件二:最后一个条目可见(最后一个条目的索引值>=数据适配器中集合的总条目个数-1)
			if(scrollState == OnScrollListener.SCROLL_STATE_IDLE
					&& lv_blacknumber.getLastVisiblePosition()>=mBlackNumberList.size()-1
					&& !mIsLoad){
				/*mIsLoad防止重复加载的变量
				如果当前正在加载mIsLoad就会为true,本次加载完毕后,再将mIsLoad改为false
				如果下一次加载需要去做执行的时候,会判断上诉mIsLoad变量,是否为false,如果为true,就需要等待上一次加载完成,将其值
				改为false后再去加载*/
				
				//如果条目总数大于集合大小的时,才可以去继续加载更多
				if(mCount>mBlackNumberList.size()){
					//加载下一页数据
					new Thread(){
						public void run() {
							//1,获取操作黑名单数据库的对象
							mDao = BlackNumberDao.getInstance(getApplicationContext());
							//2,查询部分数据
							List<BlackNumberInfo> moreData = http://www.mamicode.com/mDao.find(mBlackNumberList.size());>

4.拦截短信 

短信在接受的时候,广播发送,监听广播接受者,拦截短信(有序)
将广播的优先级级别提高到最高 (1000)

5.拦截电话

有电话拨入,处于响铃状态,响铃状态通过代码去挂断电话(aidl,反射),拦截电话
挂断电话号码的方法,放置在了aidl文件中名称为endCall

在此处去查看TelePhoneManager源码,去查找获取ITelephony对象的方法

ServiceManager此类android对开发者隐藏,所以不能去直接调用其方法,所以需要反射调用
ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));

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

//1,获取ServiceManager字节码文件
Class<?> clazz = Class.forName("android.os.ServiceManager");
//2,获取方法
Method method = clazz.getMethod("getService", String.class);
//3,反射调用此方法
IBinder iBinder = (IBinder) method.invoke(null, Context.TELEPHONY_SERVICE);
//4,调用获取aidl文件对象方法
ITelephony iTelephony = ITelephony.Stub.asInterface(iBinder);
//5,调用在aidl中隐藏的endCall方法
iTelephony.endCall();

技术分享
  1 package com.itheima.mobilesafe74.service;
  2 
  3 import java.lang.reflect.InvocationTargetException;
  4 import java.lang.reflect.Method;
  5 
  6 import com.android.internal.telephony.ITelephony;
  7 import com.itheima.mobilesafe74.db.dao.BlackNumberDao;
  8 import com.itheima.mobilesafe74.service.AddressService.MyPhoneStateListener;
  9 import android.app.Service;
 10 import android.content.BroadcastReceiver;
 11 import android.content.Context;
 12 import android.content.Intent;
 13 import android.content.IntentFilter;
 14 import android.os.IBinder;
 15 import android.telephony.PhoneStateListener;
 16 import android.telephony.SmsMessage;
 17 import android.telephony.TelephonyManager;
 18 import android.util.Log;
 19 import android.view.WindowManager;
 20 
 21 public class BlackNumberService extends Service {
 22     private InnerSmsReceiver mInnerSmsReceiver;
 23     private BlackNumberDao mDao;
 24     private TelephonyManager mTM;
 25     private MyPhoneStateListener mPhoneStateListener;
 26     @Override
 27     public void onCreate() {
 28         mDao = BlackNumberDao.getInstance(getApplicationContext());
 29         
 30         //拦截短信
 31         IntentFilter intentFilter = new IntentFilter();
 32         intentFilter.addAction("android.provider.Telephony.SMS_RECEIVED");
 33         intentFilter.setPriority(1000);
 34         
 35         mInnerSmsReceiver = new InnerSmsReceiver();
 36         registerReceiver(mInnerSmsReceiver, intentFilter);
 37         
 38         //监听电话的状态
 39         //1,电话管理者对象
 40         mTM = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
 41         //2,监听电话状态
 42         mPhoneStateListener = new MyPhoneStateListener();
 43         mTM.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
 44         
 45         super.onCreate();
 46     }
 47     
 48     class MyPhoneStateListener extends PhoneStateListener{
 49         //3,手动重写,电话状态发生改变会触发的方法
 50         @Override
 51         public void onCallStateChanged(int state, String incomingNumber) {
 52             switch (state) {
 53             case TelephonyManager.CALL_STATE_IDLE:
 54                 break;
 55             case TelephonyManager.CALL_STATE_OFFHOOK:
 56                 break;
 57             case TelephonyManager.CALL_STATE_RINGING:
 58                 //挂断电话     aidl文件中去了
 59 //                mTM.endCall();
 60                 endCall(incomingNumber);
 61                 break;
 62             }
 63             super.onCallStateChanged(state, incomingNumber);
 64         }
 65     }
 66     class InnerSmsReceiver extends BroadcastReceiver{
 67         @Override
 68         public void onReceive(Context context, Intent intent) {
 69             //获取短信内容,获取发送短信电话号码,如果此电话号码在黑名单中,并且拦截模式也为1(短信)或者3(所有),拦截短信
 70             //1,获取短信内容
 71             Object[] objects = (Object[]) intent.getExtras().get("pdus");
 72             //2,循环遍历短信过程
 73             for (Object object : objects) {
 74                 //3,获取短信对象
 75                 SmsMessage sms = SmsMessage.createFromPdu((byte[])object);
 76                 //4,获取短信对象的基本信息
 77                 String originatingAddress = sms.getOriginatingAddress();
 78                 String messageBody = sms.getMessageBody();
 79                 
 80                 int mode = mDao.getMode(originatingAddress);
 81                 
 82                 if(mode == 1 || mode == 3){
 83                     //拦截短信(android 4.4版本失效    短信数据库,删除)
 84                     abortBroadcast();
 85                 }
 86             }
 87         }
 88     }
 89     
 90     @Override
 91     public IBinder onBind(Intent arg0) {
 92         return null;
 93     }
 94     public void endCall(String phone) {
 95         int mode = mDao.getMode(phone);
 96         
 97         if(mode == 2 || mode == 3){
 98 //            ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
 99             //ServiceManager此类android对开发者隐藏,所以不能去直接调用其方法,需要反射调用
100             try {
101                 //1,获取ServiceManager字节码文件
102                 Class<?> clazz = Class.forName("android.os.ServiceManager");
103                 //2,获取方法
104                 Method method = clazz.getMethod("getService", String.class);
105                 //3,反射调用此方法
106                 IBinder iBinder = (IBinder) method.invoke(null, Context.TELEPHONY_SERVICE);
107                 //4,调用获取aidl文件对象方法
108                 ITelephony iTelephony = ITelephony.Stub.asInterface(iBinder);
109                 //5,调用在aidl中隐藏的endCall方法
110                 iTelephony.endCall();
111             } catch (Exception e) {
112                 e.printStackTrace();
113             }
114         }
115     }
116     @Override
117     public void onDestroy() {
118         if(mInnerSmsReceiver!=null){
119             unregisterReceiver(mInnerSmsReceiver);
120         }
121         super.onDestroy();
122     }
123 }
BlackNumberService

 

  

Android 手机卫士7--黑名单拦截