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

本文实例讲述了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();
  }
}

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

(0)

相关推荐

  • Android基于AudioManager、PhoneStateListener实现设置黑名单功能

    本文实例讲述了Android基于AudioManager.PhoneStateListener实现设置黑名单功能.分享给大家供大家参考,具体如下: 手机中一般有设置黑名单的功能.此例通过设置电话黑名单,当黑名单中的电话打来时,手机铃声为变成静音. 程序代码如下: import android.app.Activity; import android.content.Context; import android.media.AudioManager; import android.os.Bund

  • Android编程中黑名单的实现方法

    本文实例讲述了Android编程中黑名单的实现方法.分享给大家供大家参考,具体如下: 说明:由于挂断电话android   api不是对外开放的,所以需要使用反射的方法得到拨打电话的服务. 1.将android源代码中的"aidl"文件拷贝到项目中 这样项目中会生成两个包:android.telephony:此包中文件为:NeighboringCellInfo.aidl com.android.internal.telephony;此包中文件为:ITelephony.aidl 2.通过

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

    本文实例讲述了Android编程中黑名单的实现方法.分享给大家供大家参考,具体如下: 1,黑名单数据库创建 三个字段(_id 自增长字段 phone 黑名单号码 mode 拦截类型) 创建表的sql语句 create table blacknumber (_id integer primary key autoincrement , phone varchar(20), mode varchar(5)); 结合项目,去创建数据库,以及相应的表 2.BlackNumberDao BlackNumb

  • Android项目实战之ListView悬浮头部展现效果实现

    目录 实现效果: 我们先分析要解决的问题: 解决: 代码实现: 总结 实现效果: 先看下效果:需求是 滑动列表 ,其中一部分视图(粉丝数,关注数这一部分)在滑动到顶端的时候不消失,而是停留在整个界面头部. 我们先分析要解决的问题: 1.如何实现列表ListView顶部视图跟随ListView一起滑动 2.如何实现滑动过程中需要停留在顶部的视图 解决: 第一个问题,实现ListView与顶部视图一起滑动,ListView提供一个方法,addHeadView(View); 意思就是在ListView

  • 在Android项目中使用AspectJ的详细攻詻

    AOP 全称"Aspect Oriented Programming",面向切面编程,由于面向对象的思想要求高内聚,低耦合的风格,使模块代码间的可见性变差,对于埋点,日志输出等需求,就会变的十分复杂,如果手动编写代码,入侵性很大,不利于扩展,AOP应运而生. AspectJ AspectJ实际上是对AOP编程的实践,目前还有很多的AOP实现,如ASMDex,但笔者选用的是AspectJ. 使用场景 当我们需要在某个方法运行前和运行后做一些处理时,便可使用AOP技术.具体有: 统计埋点

  • Android仿微信底部菜单栏效果

    前言 在市面上,大多数的APP都需要通过底部菜单栏来将程序的功能进行分类整理,通常都是分为3-5个大模块,从而正确有效地引导用户去使用我们的APP.实现底部菜单栏的方法也有很多种. 1.仿微信底部菜单栏(ViewPager+ImagerView+TextView) ......(其他方式后续会补充) 效果预览 首先来个开胃菜,看看实现效果: 先贴出项目所需的资源文件,这些可随个人自由更改颜色和文字 colors.xml <color name="bg_line_light_gray&quo

  • 用Eclipse搭建Android开发环境并创建第一个Android项目(eclipse+android sdk)

    一.搭建Android开发环境 准备工作:下载Eclipse.JDK.Android SDK.ADT插件 1.安装和配置JAVA开发环境:  ①把准备好的Eclipse和JDK安装到本机上(最好安装在全英文路径下),并给JDK配置环境变量,其中JDK的变量值为JDK安装路径的根目录,如我的为:D:\Program Files\Java\jdk1.7.0_02: ②打开命令提示符(cmd),输入java -version命令,显示如下图则说明JAVA环境变量已经配置好了. 2.安装ADT插件: ①

  • Android 实现控件悬浮效果实例代码

    随着移动互联网的快速发展,它已经和我们的生活息息相关了,在公交地铁里面都能看到很多人的人低头看着自己的手机屏幕,从此"低头族"一词就产生了,作为一名移动行业的开发人员,我自己也是一名"低头族",上下班时间在公交地铁上看看新闻来打发下时间,有时候也会看看那些受欢迎的App的一些界面效果,为什么人家的app那么受欢迎?跟用户体验跟UI设计也有直接的关系,最近在美团和大众点评的App看到如下效果,我感觉用户好,很人性化,所以自己也尝试着实现了下,接下来就讲解下实现思路!

  • android项目从Eclipse迁移到Android studio中常见问题解决方法

    (1)将Eclipse项目导入到Android studio 中出现9-patch image问题解决方法: 在build.gradle里添加以下两句: aaptOptions.cruncherEnabled = false aaptOptions.useNewCruncher = false 用来关闭Android Studio的PNG合法性检查的,直接不让它检查. (2)Android Studio 错误: 非法字符: '\ufeff' 解决方案|错误: 需要class, interface

  • 在Android项目中使用AspectJ的方法

    什么是AOP AOP是 Aspect Oriented Programming 的缩写,即面向切面编程,和平常遇到的面向对象OOP编程不一样的是,OOP是将功能模块化对象化,AOP是针对同一类的问题统一化处理.例如做日志埋点,性能监控,动态权限控制等. AspectJ AspectJ实际上是对AOP编程的实践,目前还有很多的AOP实现,如ASMDex,但笔者选用的是AspectJ. 在Android项目中使用AspectJ 如果使用原生AspectJ在项目中配置会非常麻烦,在GitHub上有个开

  • Android实现水波纹扩散效果的实例代码

    本文讲述了Android实现水波纹扩散效果的实例代码.分享给大家供大家参考,具体如下: 项目地址下载 1.效果图: 2.使用方法: 在xml里使用RippleImageView自定义控件: xmlns:app="http://schemas.android.com/apk/res-auto" <com.army.rippleimage.RippleImageView android:id="@+id/rippleImageView" android:layou

随机推荐