Android - 在线浏览源码,电话短信相关,文本变化监听器
//ServiceManager 获取不到,需要反射调用
Class clazz = getClassLoader().loadClass("android.os.ServiceManager");
Method method = clazz.getDeclaredMethod("getService", String.class);
IBinder iBinder = (IBinder) method.invoke(null, Context.TELEPHONY_SERVICE);
//挂断电话需要用到 AIDL,拷贝需要用到的 AIDL 文件,ITelephony.aidl 和 NeighboringCellInfo.aidl,包名要与原包名一致
ITelephony iTelephony = ITelephony.Stub.asInterface(iBinder);
iTelephony.endCall();
} catch (Exception e) {
e.printStackTrace();
}
}
3.删除呼叫记录
//加入权限
<uses-permission android:name="android.permission.READ_CALL_LOG" />
<uses-permission android:name="android.permission.WRITE_CALL_LOG" />
/**
删除黑名单号码的呼叫记录
@param incomingNumber 来电黑名单号码
*/
public void deleteCallLog(final String incomingNumber) {
final ContentResolver resolver = getContentResolver();
//CallLog.Calls.CONTENT_URI 等价于 Uri.parse("content://call_log/calls");
final Uri uri = Uri.parse("content://call_log/calls");
//利用内容观察者 观察呼叫记录的数据库,如果生成了呼叫记录就立刻删除呼叫记录
resolver.registerContentObserver(uri, true, new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
//当内容观察者观察到数据库的内容变化的时候调用的方法.
super.onChange(selfChange);
resolver.delete(uri, "number=?", new String[]{incomingNumber});
}
});
}
4.拦截短信
1.注册在清单文件中的广播接收者,无论应用是否启动都会接收到广播,想用开关控制拦截短信的功能,则在代码中注册短信广播接收者
receiver = new InnerSmsReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction("android.provider.Telephony.SMS_RECEIVED");
filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
registerReceiver(receiver, filter);
private class InnerSmsReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Log.i(Tag,"服务内部广播接受者接收到了短信");
Object[] objs = (Object[]) intent.getExtras().get("pdus");
for(Object obj: objs){
SmsMessage smsMessage = SmsMessage.createFromPdu((byte[]) obj);
String body = smsMessage.getMessageBody();
if(body.contains("fapiao")){
//你的头发票亮的很 分词技术
Log.i(Tag,"发现发票垃圾短信,拦截");
abortBroadcast();
return;
}
String sender = smsMessage.getOriginatingAddress();
String mode = dao.find(sender);
if("2".equals(mode)||"3".equals(mode)){
Log.i(Tag,"发现黑名单短信,拦截");
abortBroadcast();
}
}
}
}
2.onDestroy 中注销
unregisterReceiver(receiver);
receiver = null;
5.导入已存在的数据库
//assert 资产目录里面的文件会原封不动的打包到 apk 里,不生成 id
/**
拷贝归属地的数据库
*/
private void copyAddressDB() {
File file = new File(getFilesDir(), "address.db");
//判断数据库文件是否存在
if (file.exists() && file.length() > 0) {
Log.i(TAG, "数据库存在,无需拷贝");
} else {
new Thread() {
public void run() {
// 把 asset 资产目录里面的数据库文件(在 apk 里面的)拷贝到手机系统里面
try {
InputStream is = getAssets().open("address.db");
File file = new File(getFilesDir(), "address.db");
FileOutputStream fos = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int len = -1;
while ((len = is.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
fos.close();
is.close();
} catch (Exception e) {
e.printStackTrace();
}
};
}.start();
}
}
6.查询号码归属地
/**
查询手机号码的归属地信息
@param mobilenumber
@return
*/
public static String findLocation(String mobilenumber) {
String path = "/data/data/com.mythmayor.project/files/address.db";
//打开已存在的数据库
SQLiteDatabase db = SQLiteDatabase.openDatabase(path, null,
SQLiteDatabase.OPEN_READONLY);
Cursor cursor = db.rawQuery(
"select location from data2 where id = (select outkey from data1 where id = ?)",
new String[]{mobilenumber.substring(0, 7)});
String location ="";
if(cursor.moveToNext()){
location = cursor.getString(0);
}
cursor.close();
db.close();
return location;
}
7.判断一个号码是否是手机号码
// ^1[34578]\d{9}$
// ^ 匹配输入字符串的开始位置。
// [] 字符集合。匹配所包含的任意一个字符。
// \d 匹配一个数字字符。
// {} n 是一个非负整数。匹配确定的 n 次。
// $ 匹配输入字符串的结束位置。
boolean result = number.matches("^1[34578]\d{9}$");
8.给 EditText 添加文本变化监听器
// 给文本输入框注册一个内容变化的监听器.
et_number.addTextChangedListener(new TextWatcher() {
//当文本变化之前调用的方法,s 为改变前字符串,可获取被替换内容
//在 s 中从 start 开始的 count 个字符即将被 after 个字符替换
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
//当文本变化之后调用的方法,s 为改变后字符串,可获取替换内容
//在 s 中从 start 开始的 before 个字符刚刚被 count 个字符替换
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
if (s.length() >= 10) {
String location = AddressDBDao.findLocation(s.toString());
tv_location.setText("归属地为:" + location);
}
}
//当文本变化之后调用的方法,s 为改变后字符串,操作 s 可直接改变 EditText 内容,EditText 内容改变会继续调用 beforeTextChanged 和 onTextChanged 方法
//s 中有内容被改变
@Override
public void afterTextChanged(Editable s) {
}
});
每次输入都会调用 3 个方法,调用顺序为 beforeTextChanged-->onTextChanged-->afterTextChanged
9.CharSequence、String、Editable
1.CharSequence:接口,只有 length()、charAt(int index)、subSequence(int start, int end)、toString()四个方法
2.String:实现了 CharSequence 接口,具有很多操作字符串的方法,不可修改
3.Editable:实现了 CharSequence 接口,具有增删改等修改的方法,可修改
评论