本文实例讲述了Android编程中黑名单的实现方法。分享给大家供大家参考,具体如下:
1,黑名单数据库创建三个字段(_id 自增长字段 phone 黑名单号码 mode 拦截类型)
创建表的sql语句
create table blacknumber (_id integer primary key autoincrement , phone varchar(20), mode varchar(5));
结合项目,去创建数据库,以及相应的表
2.BlackNumberDao BlackNumberDao单例模式
package com.itheima.mobilesafe74.db.dao;import java.util.ArrayList;import java.util.List;import android.content.ContentValues;import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import com.itheima.mobilesafe74.db.BlackNumberOpenHelper;import com.itheima.mobilesafe74.db.domain.BlackNumberInfo;public class BlackNumberDao {private BlackNumberOpenHelper blackNumberOpenHelper;//BlackNumberDao单例模式//1,私有化构造方法private BlackNumberDao(Context context){//创建数据库已经其表机构blackNumberOpenHelper = new BlackNumberOpenHelper(context);}//2,声明一个当前类的对象private static BlackNumberDao blackNumberDao = null;//3,提供一个静态方法,如果当前类的对象为空,创建一个新的public static BlackNumberDao getInstance(Context context){if(blackNumberDao == null){blackNumberDao = new BlackNumberDao(context);}return blackNumberDao;}/**增加一个条目 * @param phone拦截的电话号码 * @param mode拦截类型(1:短信2:电话3:拦截所有(短信+电话)) */public void insert(String phone,String mode){//1,开启数据库,准备做写入操作SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();ContentValues values = new ContentValues();values.put("phone", phone);values.put("mode", mode);db.insert("blacknumber", null, values);db.close();}/**从数据库中删除一条电话号码 * @param phone删除电话号码 */public void delete(String phone){SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();db.delete("blacknumber", "phone = ?", new String[]{phone});db.close();}/** * 根据电话号码去,更新拦截模式 * @param phone更新拦截模式的电话号码 * @param mode要更新为的模式(1:短信2:电话3:拦截所有(短信+电话) */public void update(String phone,String mode){SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();ContentValues contentValues = new ContentValues();contentValues.put("mode", mode);db.update("blacknumber", contentValues, "phone = ?", new String[]{phone});db.close();}/** * @return查询到数据库中所有的号码以及拦截类型所在的集合 */public List<BlackNumberInfo> findAll(){SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();Cursor cursor = db.query("blacknumber", new String[]{"phone","mode"}, null, null, null, null, "_id desc");List<BlackNumberInfo> blackNumberList = new ArrayList<BlackNumberInfo>();while(cursor.moveToNext()){BlackNumberInfo blackNumberInfo = new BlackNumberInfo();blackNumberInfo.phone = cursor.getString(0);blackNumberInfo.mode = cursor.getString(1);blackNumberList.add(blackNumberInfo);}cursor.close();db.close();return blackNumberList;}/** * 每次查询20条数据 * @param index查询的索引值 */public List<BlackNumberInfo> find(int index){SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();Cursor cursor = db.rawQuery("select phone,mode from blacknumber order by _id desc limit ?,20;", new String[]{index+""});List<BlackNumberInfo> blackNumberList = new ArrayList<BlackNumberInfo>();while(cursor.moveToNext()){BlackNumberInfo blackNumberInfo = new BlackNumberInfo();blackNumberInfo.phone = cursor.getString(0);blackNumberInfo.mode = cursor.getString(1);blackNumberList.add(blackNumberInfo);}cursor.close();db.close();return blackNumberList;}/** * @return数据库中数据的总条目个数,返回0代表没有数据或异常 */public int getCount(){SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();int count = 0;Cursor cursor = db.rawQuery("select count(*) from blacknumber;", null);if(cursor.moveToNext()){count = cursor.getInt(0);}cursor.close();db.close();return count;}/** * @param phone作为查询条件的电话号码 * @return传入电话号码的拦截模式1:短信2:电话3:所有0:没有此条数据 */public int getMode(String phone){SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();int mode = 0;Cursor cursor = db.query("blacknumber", new String[]{"mode"}, "phone = ?", new String[]{phone}, null, null,null);if(cursor.moveToNext()){mode = cursor.getInt(0);}cursor.close();db.close();return mode;}}
3,加载更多的触发条件- 监听状态改变
- 滚动到最底部,最后一个listView的条目可见
- 滚动状态发生改变 滚动------>停止(空闲)
加载下一页数据完成后,需要添加到上一页数据的最后面
//监听其滚动状态lv_blacknumber.setOnScrollListener(new OnScrollListener() {//滚动过程中,状态发生改变调用方法()@Overridepublic 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 = mDao.find(mBlackNumberList.size());//3,添加下一页数据的过程mBlackNumberList.addAll(moreData);//4,通知数据适配器刷新mHandler.sendEmptyMessage(0);}}.start();}}} } //滚动过程中调用方法@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) { }});
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方法
BlackNumberService
iTelephony.endCall();package com.itheima.mobilesafe74.service;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import com.android.internal.telephony.ITelephony;import com.itheima.mobilesafe74.db.dao.BlackNumberDao;import com.itheima.mobilesafe74.service.AddressService.MyPhoneStateListener;import android.app.Service;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.os.IBinder;import android.telephony.PhoneStateListener;import android.telephony.SmsMessage;import android.telephony.TelephonyManager;import android.util.Log;import android.view.WindowManager;public class BlackNumberService extends Service {private InnerSmsReceiver mInnerSmsReceiver;private BlackNumberDao mDao;private TelephonyManager mTM;private MyPhoneStateListener mPhoneStateListener;@Overridepublic void onCreate() {mDao = BlackNumberDao.getInstance(getApplicationContext());//拦截短信IntentFilter intentFilter = new IntentFilter();intentFilter.addAction("android.provider.Telephony.SMS_RECEIVED");intentFilter.setPriority(1000);mInnerSmsReceiver = new InnerSmsReceiver();registerReceiver(mInnerSmsReceiver, intentFilter);//监听电话的状态//1,电话管理者对象mTM = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);//2,监听电话状态mPhoneStateListener = new MyPhoneStateListener();mTM.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);super.onCreate();}class MyPhoneStateListener extends PhoneStateListener{//3,手动重写,电话状态发生改变会触发的方法@Overridepublic void onCallStateChanged(int state, String incomingNumber) {switch (state) {case TelephonyManager.CALL_STATE_IDLE:break;case TelephonyManager.CALL_STATE_OFFHOOK:break;case TelephonyManager.CALL_STATE_RINGING://挂断电话 aidl文件中去了//mTM.endCall();endCall(incomingNumber);break;}super.onCallStateChanged(state, incomingNumber);}}class InnerSmsReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {//获取短信内容,获取发送短信电话号码,如果此电话号码在黑名单中,并且拦截模式也为1(短信)或者3(所有),拦截短信//1,获取短信内容Object[] objects = (Object[]) intent.getExtras().get("pdus");//2,循环遍历短信过程for (Object object : objects) {//3,获取短信对象SmsMessage sms = SmsMessage.createFromPdu((byte[])object);//4,获取短信对象的基本信息String originatingAddress = sms.getOriginatingAddress();String messageBody = sms.getMessageBody();int mode = mDao.getMode(originatingAddress);if(mode == 1 || mode == 3){//拦截短信(android 4.4版本失效短信数据库,删除)abortBroadcast();}}}}@Overridepublic IBinder onBind(Intent arg0) {return null;}public void endCall(String phone) {int mode = mDao.getMode(phone);if(mode == 2 || mode == 3){//ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));//ServiceManager此类android对开发者隐藏,所以不能去直接调用其方法,需要反射调用try {//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();} catch (Exception e) {e.printStackTrace();}}}@Overridepublic void onDestroy() {if(mInnerSmsReceiver!=null){unregisterReceiver(mInnerSmsReceiver);}super.onDestroy();}}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。