Android項目實現(xiàn)黑名單攔截效果
本文實例講述了Android編程中黑名單的實現(xiàn)方法。分享給大家供大家參考,具體如下:
1,黑名單數(shù)據(jù)庫創(chuàng)建
三個字段(_id 自增長字段 phone 黑名單號碼 mode 攔截類型)
創(chuàng)建表的sql語句
create table blacknumber (_id integer primary key autoincrement , phone varchar(20), mode varchar(5));
結(jié)合項目,去創(chuàng)建數(shù)據(jù)庫,以及相應(yīng)的表
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,私有化構(gòu)造方法
private BlackNumberDao(Context context){
//創(chuàng)建數(shù)據(jù)庫已經(jīng)其表機構(gòu)
blackNumberOpenHelper = new BlackNumberOpenHelper(context);
}
//2,聲明一個當(dāng)前類的對象
private static BlackNumberDao blackNumberDao = null;
//3,提供一個靜態(tài)方法,如果當(dāng)前類的對象為空,創(chuàng)建一個新的
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,開啟數(shù)據(jù)庫,準(zhǔn)備做寫入操作
SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("phone", phone);
values.put("mode", mode);
db.insert("blacknumber", null, values);
db.close();
}
/**從數(shù)據(jù)庫中刪除一條電話號碼
* @param phone 刪除電話號碼
*/
public void delete(String phone){
SQLiteDatabase db = blackNumberOpenHelper.getWritableDatabase();
db.delete("blacknumber", "phone = ?", new String[]{phone});
db.close();
}
/**
* 根據(jù)電話號碼去,更新攔截模式
* @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 查詢到數(shù)據(jù)庫中所有的號碼以及攔截類型所在的集合
*/
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條數(shù)據(jù)
* @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 數(shù)據(jù)庫中數(shù)據(jù)的總條目個數(shù),返回0代表沒有數(shù)據(jù)或異常
*/
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:沒有此條數(shù)據(jù)
*/
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,加載更多的觸發(fā)條件
- 監(jiān)聽狀態(tài)改變
- 滾動到最底部,最后一個listView的條目可見
- 滾動狀態(tài)發(fā)生改變 滾動------>停止(空閑)
加載下一頁數(shù)據(jù)完成后,需要添加到上一頁數(shù)據(jù)的最后面
//監(jiān)聽其滾動狀態(tài)
lv_blacknumber.setOnScrollListener(new OnScrollListener() {
//滾動過程中,狀態(tài)發(fā)生改變調(diào)用方法()
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// OnScrollListener.SCROLL_STATE_FLING 飛速滾動
// OnScrollListener.SCROLL_STATE_IDLE 空閑狀態(tài)
// OnScrollListener.SCROLL_STATE_TOUCH_SCROLL 拿手觸摸著去滾動狀態(tài)
if(mBlackNumberList!=null){
//條件一:滾動到停止?fàn)顟B(tài)
//條件二:最后一個條目可見(最后一個條目的索引值>=數(shù)據(jù)適配器中集合的總條目個數(shù)-1)
if(scrollState == OnScrollListener.SCROLL_STATE_IDLE
&& lv_blacknumber.getLastVisiblePosition()>=mBlackNumberList.size()-1
&& !mIsLoad){
/*mIsLoad防止重復(fù)加載的變量
如果當(dāng)前正在加載mIsLoad就會為true,本次加載完畢后,再將mIsLoad改為false
如果下一次加載需要去做執(zhí)行的時候,會判斷上訴mIsLoad變量,是否為false,如果為true,就需要等待上一次加載完成,將其值
改為false后再去加載*/
//如果條目總數(shù)大于集合大小的時,才可以去繼續(xù)加載更多
if(mCount>mBlackNumberList.size()){
//加載下一頁數(shù)據(jù)
new Thread(){
public void run() {
//1,獲取操作黑名單數(shù)據(jù)庫的對象
mDao = BlackNumberDao.getInstance(getApplicationContext());
//2,查詢部分?jǐn)?shù)據(jù)
List<BlackNumberInfo> moreData = mDao.find(mBlackNumberList.size());
//3,添加下一頁數(shù)據(jù)的過程
mBlackNumberList.addAll(moreData);
//4,通知數(shù)據(jù)適配器刷新
mHandler.sendEmptyMessage(0);
}
}.start();
}
}
}
}
//滾動過程中調(diào)用方法
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
}
});
4.攔截短信
短信在接受的時候,廣播發(fā)送,監(jiān)聽廣播接受者,攔截短信(有序)
將廣播的優(yōu)先級級別提高到最高 (1000)
5.攔截電話
有電話撥入,處于響鈴狀態(tài),響鈴狀態(tài)通過代碼去掛斷電話(aidl,反射),攔截電話
掛斷電話號碼的方法,放置在了aidl文件中名稱為endCall
在此處去查看TelePhoneManager源碼,去查找獲取ITelephony對象的方法
ServiceManager此類android對開發(fā)者隱藏,所以不能去直接調(diào)用其方法,所以需要反射調(diào)用
ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
<uses-permission android:name="android.permission.CALL_PHONE"/>
//1,獲取ServiceManager字節(jié)碼文件
Class<?> clazz = Class.forName("android.os.ServiceManager");
//2,獲取方法
Method method = clazz.getMethod("getService", String.class);
//3,反射調(diào)用此方法
IBinder iBinder = (IBinder) method.invoke(null, Context.TELEPHONY_SERVICE);
//4,調(diào)用獲取aidl文件對象方法
ITelephony iTelephony = ITelephony.Stub.asInterface(iBinder);
//5,調(diào)用在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);
//監(jiān)聽電話的狀態(tài)
//1,電話管理者對象
mTM = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
//2,監(jiān)聽電話狀態(tài)
mPhoneStateListener = new MyPhoneStateListener();
mTM.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
super.onCreate();
}
class MyPhoneStateListener extends PhoneStateListener{
//3,手動重寫,電話狀態(tài)發(fā)生改變會觸發(fā)的方法
@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) {
//獲取短信內(nèi)容,獲取發(fā)送短信電話號碼,如果此電話號碼在黑名單中,并且攔截模式也為1(短信)或者3(所有),攔截短信
//1,獲取短信內(nèi)容
Object[] objects = (Object[]) intent.getExtras().get("pdus");
//2,循環(huán)遍歷短信過程
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版本失效 短信數(shù)據(jù)庫,刪除)
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對開發(fā)者隱藏,所以不能去直接調(diào)用其方法,需要反射調(diào)用
try {
//1,獲取ServiceManager字節(jié)碼文件
Class<?> clazz = Class.forName("android.os.ServiceManager");
//2,獲取方法
Method method = clazz.getMethod("getService", String.class);
//3,反射調(diào)用此方法
IBinder iBinder = (IBinder) method.invoke(null, Context.TELEPHONY_SERVICE);
//4,調(diào)用獲取aidl文件對象方法
ITelephony iTelephony = ITelephony.Stub.asInterface(iBinder);
//5,調(diào)用在aidl中隱藏的endCall方法
iTelephony.endCall();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onDestroy() {
if(mInnerSmsReceiver!=null){
unregisterReceiver(mInnerSmsReceiver);
}
super.onDestroy();
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android中oncreate中獲得控件高度或?qū)挾鹊膶崿F(xiàn)方法
這篇文章主要介紹了Android中oncreate中獲得控件高度或?qū)挾鹊膶崿F(xiàn)方法的相關(guān)資料,希望通過本文大家能實現(xiàn)這樣的功能,需要的朋友可以參考下2017-09-09
Android圖像切換器imageSwitcher的實例應(yīng)用
這篇文章主要為大家詳細(xì)介紹了Android圖像切換器imageSwitcher的實例應(yīng)用,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-10-10
Android用PopupWindow實現(xiàn)新浪微博的分組信息實例
PopupWindow可以實現(xiàn)浮層效果,而且可以自定義顯示位置,本篇文章主要介紹Android用PopupWindow實現(xiàn)新浪微博的分組信息,有需要的可以了解一下。2016-11-11
Android RecyclerView打造懸浮效果的實現(xiàn)代碼
本篇文章主要介紹了Android RecyclerView打造懸浮效果的實現(xiàn)代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-10-10
Android實現(xiàn)中國象棋游戲(局域網(wǎng)版)
這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)局域網(wǎng)版的中國象棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-05-05

