欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android项目实现黑名单拦截效果

程序员文章站 2024-03-03 19:47:16
本文实例讲述了android编程中黑名单的实现方法。分享给大家供大家参考,具体如下: 1,黑名单数据库创建 三个字段(_id 自增长字段 phone 黑名单号码...

本文实例讲述了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,加载更多的触发条件

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

加载下一页数据完成后,需要添加到上一页数据的最后面

//监听其滚动状态
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 = mdao.find(mblacknumberlist.size());
              //3,添加下一页数据的过程
              mblacknumberlist.addall(moredata);
              //4,通知数据适配器刷新
              mhandler.sendemptymessage(0);
            }
          }.start();
        }
      }
    }
     
  }
   
  //滚动过程中调用方法
  @override
  public 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;
  @override
  public 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,手动重写,电话状态发生改变会触发的方法
    @override
    public 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{
    @override
    public 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();
        }
      }
    }
  }
  
  @override
  public 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();
      }
    }
  }
  @override
  public void ondestroy() {
    if(minnersmsreceiver!=null){
      unregisterreceiver(minnersmsreceiver);
    }
    super.ondestroy();
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。