本文分享了一个电话黑名单的小项目,下面是具体的实现:
1.添加黑名单。
2.判断如果是黑名单,就对其拦截。
添加黑名单:
往数据库里面添加黑名单,手机号码,用的是ContentProvider进行添加的(当然,这里是完全没有必要用这个的)
第一步:
新建一个MyContentProvider继承自ContentProvider,并重写其中的方法:
package com.wind.safecall.contentprovider; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.Context; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.net.Uri; import android.support.annotation.NonNull; import android.support.annotation.Nullable; /** * Created by zhangcong on 2017/4/8. */ public class MyContentProvider extends ContentProvider { private MyOpenHelper myOpenHelper; private String DB_name="blackname";//数据库名 private String Table_name="blacknametable";//数据表名 private SQLiteDatabase sqLiteDatabase; private static UriMatcher uriMatcher; public static final String AUTHORITY="blacknum"; public static final Uri uri =Uri.parse("content://blacknum/path_simon"); // 注册该内容提供者匹配的uri static { uriMatcher=new UriMatcher(UriMatcher.NO_MATCH);//Creates the root node of the URI tree. uriMatcher.addURI(AUTHORITY,"path_simon",1);// 代表当前表中的所有的记录,第三个参数必须为正数 uriMatcher.addURI(AUTHORITY,"path_simon/1",2);// 代表当前表中的某条特定的记录,记录id便是#处得数字 } //数据表列名映射 private static final String blacknum="blacknum"; private static final String _id = "id"; @Override public boolean onCreate() { try { myOpenHelper=new MyOpenHelper(getContext(),DB_name,null,1); } catch (Exception e) { return false; } return true; } @Nullable @Override public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { Cursor cursor = null; sqLiteDatabase = myOpenHelper.getReadableDatabase(); int code = uriMatcher.match(uri);//addURI()传的第三个参数 switch (code) { case 1: cursor = sqLiteDatabase.query(Table_name, projection, selection, selectionArgs, null, null, sortOrder); break; case 2: // 从uri中解析出ID long id = ContentUris.parseId(uri); selection = (selection == null || "".equals(selection.trim())) ? _id + "=" + id : selection + " and " + _id + "=" + id; cursor = sqLiteDatabase.query(Table_name, projection, selection, selectionArgs, null, null, sortOrder); break; default: throw new IllegalArgumentException("参数错误"); } return cursor; } @Nullable @Override public String getType(@NonNull Uri uri) { return null; } @Nullable @Override public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) { sqLiteDatabase=myOpenHelper.getWritableDatabase(); sqLiteDatabase = myOpenHelper.getWritableDatabase(); int code = uriMatcher.match(uri);//前面addURI传的第三个参数 switch (code) { case 1: sqLiteDatabase.insert(Table_name, blacknum, values); break; case 2: long id = sqLiteDatabase.insert(Table_name, blacknum, values); // withAppendId将id添加到uri的最后 ContentUris.withAppendedId(uri, id); break; default: throw new IllegalArgumentException("异常参数"); } return uri; } @Override public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; } @Override public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; } private class MyOpenHelper extends SQLiteOpenHelper { public MyOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { super(context, name, factory, version); } @Override public void onCreate(SQLiteDatabase db) { /** * 官方解释 * Called when the database is created for the first time. This is where the * creation of tables and the initial population of the tables should happen. * * @param db The database. */ String sql = " create table if not exists " + Table_name + "(blacknum varchar(20),id INTEGER)"; db.execSQL(sql); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
第二步:在你的监听事件下执行这个方法:
private void insertData(String blacknum) { ContentValues contentValues=new ContentValues(); contentValues.put("blacknum",blacknum);//与数据库字段对应,第二个参数是你添加的给名单 Uri uri=getContentResolver().insert(MyContentProvider.uri,contentValues); Utils.showToast(uri.toString(),MainActivity.this); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
第三步:查询你所添加的黑名单:
这里分了两个步骤:
查询黑名单和显示黑名单:
查询黑名单
private void queryBlackNum() { String array[]={"blacknum"}; Cursor cursor=getContentResolver().query(MyContentProvider.uri,array,null,null,null); int blacknumindex=cursor.getColumnIndex("blacknum"); Log.i(">>>",blacknumindex+""); cursor.moveToFirst(); ArrayList<String> list=new ArrayList<>(); while (!cursor.isAfterLast()) { String blacknum=cursor.getString(blacknumindex); list.add(blacknum); cursor.moveToNext(); Log.i(">>>",">>>>"); Log.i("Simon",list.toString()); } Intent intent=new Intent(MainActivity.this,BlackNumActivity.class); intent.putStringArrayListExtra("list", list); // Bundle bundle=new Bundle(); // bundle.putSerializable("list", (Serializable) list); // intent.putExtras(bundle); startActivity(intent); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
在另一个Activity显示黑名单:
package com.wind.safecall.activity; import android.app.Activity; import android.os.Bundle; import android.support.annotation.Nullable; import android.util.Log; import android.view.View; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; import com.wind.safecall.R; import java.util.ArrayList; import java.util.List; /** * Created by zhangcong on 2017/4/10. */ public class BlackNumActivity extends Activity{ private TextView activitytitle; private TextView back; private StringBuffer sb; private ListView listview; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_black_num); activitytitle= (TextView) findViewById(R.id.tv_activity_toolbar_center); activitytitle.setText("黑名单"); listview= (ListView) findViewById(R.id.lv_black_num); back= (TextView) findViewById(R.id.tv_back); back.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { finish(); } }); showBlackNum(); } private void showBlackNum() { ArrayList<String> list = this.getIntent().getStringArrayListExtra("list"); Log.i(">>>>>", list.toString()); if (list != null) { listview.setAdapter(new ArrayAdapter<>(BlackNumActivity.this, R.layout.item_black_num, R.id.tv_black_num, list)); } } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
到这里,黑名单就添加完成。
接下来就是对其进行拦截了:
拦截黑名单来电:
第一步:新建一个BlackNumService继承自Service,在这里面判断是不是黑名单,是的话对其拦截:
这里需要补充一点的是:由于我们是直接拦截的来电,相当于是跨进程间的通信,这个时候aidl就登场了,好在Android有这些接口:
因为下面的代码会调用这些接口,所以我们提交准备好:
1.在根目录新建一个android.telephony的包,在里面新建一个aidl文件,命名为NeighboringCellInfo;
里面的内容为:
// NeighboringCellInfo.aidl package android.telephony; // Declare any non-default types here with import statements parcelable NeighboringCellInfo;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
2.在根目录下新建一个com.android.internal.telephony的包,在里面新建一个aidl文件,命名为ITelephony;里面的内容为:
package com.android.internal.telephony; interface ITelephony{ boolean endCall(); void answerRingingCall(); }
- 1
- 2
- 3
- 4
- 5
这里的包名和文件名一定要一致,通过包名识别来电的,再进行通信的
package com.wind.safecall.service; import android.app.Notification; import android.app.NotificationManager; import android.app.Service; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.IBinder; import android.support.annotation.Nullable; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.util.Log; import com.android.internal.telephony.ITelephony; import com.wind.safecall.contentprovider.MyContentProvider; import org.w3c.dom.ls.LSInput; import java.lang.reflect.Method; import java.util.ArrayList; /** * Created by zhangcong on 2017/4/10. */ public class BlackNumService extends Service { private TelephonyManager tm; private MyPhoneStateListener listener; private NotificationManager nm; @Override public void onCreate() { super.onCreate(); tm= (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE); listener=new MyPhoneStateListener(); tm.listen(listener,PhoneStateListener.LISTEN_CALL_STATE); // nm= (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); } private final class MyPhoneStateListener extends PhoneStateListener{ //private long startTime = 0; @Override public void onCallStateChanged(int state, String incomingNumber) { // TODO Auto-generated method stub super.onCallStateChanged(state, incomingNumber); switch (state) { case TelephonyManager.CALL_STATE_RINGING: String array[]={"blacknum"}; Cursor cursor=getContentResolver().query(MyContentProvider.uri,array,null,null,null); int blacknumindex=cursor.getColumnIndex("blacknum"); Log.i(">>>",blacknumindex+""); cursor.moveToFirst(); ArrayList<String> list=new ArrayList<>(); while (!cursor.isAfterLast()) { String blacknum=cursor.getString(blacknumindex); list.add(blacknum); cursor.moveToNext(); Log.i(">>>",">>>>"); Log.i("Simon",list.toString()); } if (list!=null&&list.contains(incomingNumber)) { endCall(); return; } //判断来电黑名单是否开启 // boolean isblackstart = sp.getBoolean("isblacknumber", false); // if(isblackstart){ // boolean isBlackNumber = blackNumberDao.isBlackNumber(incomingNumber); // if(isBlackNumber){ // // } //startTime = System.currentTimeMillis(); break; case TelephonyManager.CALL_STATE_OFFHOOK: break; case TelephonyManager.CALL_STATE_IDLE: break; default: break; } } } //挂断电话 private void endCall(){ try { Class<?> clazz = Class.forName("android.os.ServiceManager"); Method method = clazz.getMethod("getService", String.class); IBinder ibinder = (IBinder) method.invoke(null, Context.TELEPHONY_SERVICE); ITelephony iTelephony = ITelephony.Stub.asInterface(ibinder); iTelephony.endCall(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Nullable @Override public IBinder onBind(Intent intent) { return null; } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
第二步:在广播中或者应用中开启服务:
1.在应用中开启服务:
/* 启动服务 */ private void stService() { Intent intent=new Intent(MainActivity.this, BlackNumService.class); startService(intent); }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
你可以在mainactivity中的oncreate方法中调用这个方法,只要这个进程不被杀死,这个服务也就一致存在,这是startService的性质。
2.在开机广播中开启服务:有些手机是接收不到广播的:
需要新建一个BootCompletedReceiver继承自BroadcastReceiver:
package com.wind.safecall.broadcastreceiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.util.Log; import com.wind.safecall.service.BlackNumService; /** * Created by zhangcong on 2017/4/10. */ public class BootCompletedReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent){ Log.i(">>>>>>>>","已经开机"); Intent intent1=new Intent(context, BlackNumService.class); context.startService(intent1); } }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
这样,整个流程就结束了,最后贴出所有的权限和注册:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.wind.safecall"> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.RECEIVE_SMS"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <!--添加可以向外拨打电话的权限 --> <uses-permission android:name="android.permission.CALL_PHONE"></uses-permission> <permission android:name="blacknum.permission" android:protectionLevel="normal"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <!-- 开机广播 --> <receiver android:name=".broadcastreceiver.BootCompletedReceiver"> <intent-filter > <action android:name="android.intent.action.BOOT_COMPLETED"/> <category android:name="android.intent.category.HOME" /> </intent-filter> </receiver> <service android:name=".service.BlackNumService"/> <provider android:authorities="blacknum" android:name=".contentprovider.MyContentProvider" android:permission="blacknum.permission" /> <activity android:name=".activity.MainActivity" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".activity.PhoneCallActivity" android:screenOrientation="portrait"/> <activity android:name=".activity.BlackNumActivity" android:screenOrientation="portrait"/> </application> </manifest>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46