Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android項目實現黑名單攔截效果

Android項目實現黑名單攔截效果

編輯:關於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();
  }
}

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved