一畸写、屏蔽系統(tǒng)短信功能
1肤频、屏蔽所有短信
android 4.2 短信發(fā)送流程分析可參考這篇 戳這
源碼位置 vendor\mediatek\proprietary\packages\apps\Mms\src\com\android\mms\transaction\SmsReceiverService.java
private void handleSmsReceived(Intent intent, int error) {
//2018-10-09 cczheng add for intercept mms notifications start
if (true) {
Log.i("SmsReceived", "handleSmsReceived");
return;
}
//2018-10-09 cczheng add for intercept mms notifications end
SmsMessage[] msgs = Intents.getMessagesFromIntent(intent);
/// M:Code analyze 022, check null @{
if (msgs == null) {
MmsLog.e(MmsApp.TXN_TAG, "getMessagesFromIntent return null.");
return;
}
MmsLog.d(MmsApp.TXN_TAG, "handleSmsReceived SmsReceiverService");
///
......
}
在handleSmsReceived()方法中直接return即可,不去解析和分發(fā)短信消息瀑晒,同時這樣操作 短信將不會記錄到短信數(shù)據(jù)庫中,插入短信消息到數(shù)據(jù)庫的方法見下文insertMessage()方法绍坝。
2、屏蔽特定的短信(特定的短信號碼或者短信內(nèi)容)
源碼位置同上
- SmsMessage.getOriginatingAddress() 獲取短信號碼
- SmsMessage.getMessageBody() 獲取短信內(nèi)容
private void handleSmsReceived(Intent intent, int error) {
SmsMessage[] msgs = Intents.getMessagesFromIntent(intent);
.....
/// M:Code analyze 024, print log @{
SmsMessage tmpsms = msgs[0];
MmsLog.d(MmsApp.TXN_TAG, "handleSmsReceived" + (tmpsms.isReplace() ? "(replace)" : "")
+ " messageUri: " + messageUri
+ ", address: " + tmpsms.getOriginatingAddress()
+ ", body: " + tmpsms.getMessageBody());
/// @
//2018-10-09 cczheng add for intercept mms notifications start
if ("10010".equals(tmpsms.getOriginatingAddress()) || "話費(fèi)".contains(tmpsms.getMessageBody())) {
Log.i("SmsReceived", "handleSmsReceived");
return;
}
//2018-10-09 cczheng add for intercept mms notifications end
....
}
是否插入短信消息到數(shù)據(jù)庫,insertMessage()方法在handleSmsReceived()中調(diào)用
private Uri insertMessage(Context context, SmsMessage[] msgs, int error, String format) {
// Build the helper classes to parse the messages.
if (msgs == null) {
MmsLog.e(MmsApp.TXN_TAG, "insertMessage:getMessagesFromIntent return null.");
return null;
}
/// @}
SmsMessage sms = msgs[0];
if (sms.getMessageClass() == SmsMessage.MessageClass.CLASS_0) {
MmsLog.d(MmsApp.TXN_TAG, "insertMessage: display class 0 message!");
displayClassZeroMessage(context, msgs, format);
return null;
} else if (sms.isReplace()) {
MmsLog.d(MmsApp.TXN_TAG, "insertMessage: is replace message!");
return replaceMessage(context, msgs, error);
} else {
MmsLog.d(MmsApp.TXN_TAG, "insertMessage: stored directly!");
return storeMessage(context, msgs, error);
}
}
3苔悦、應(yīng)用層攔截短信(不用修改android源碼轩褐,原理就是用你的app去替代系統(tǒng)默認(rèn)的短信app,過程略繁瑣)
需要添加SmsReceiver玖详,MmsReceiver把介,ComposeSmsActivity勤讽,HeadlessSmsSendService這幾個類,并在AndroidManifest中進(jìn)行相應(yīng)配置拗踢,具體流程可參考這篇 戳這
二脚牍、屏蔽系統(tǒng)來電響鈴和通知提示
屏蔽系統(tǒng)來電可分為三個步驟
1.來電靜音,不響鈴
2.來電掛斷秒拔,不出現(xiàn)IncallActivity
3莫矗、攔截未接來電通知,不顯示在狀態(tài)欄StatusBar中
ps:此種修改方式的弊端在于來電時網(wǎng)絡(luò)數(shù)據(jù)會離線2s左右
好砂缩,現(xiàn)在我們開始按這三個步驟來修改源碼
1.來電靜音作谚,不響鈴
源碼位置 packages/services/Telecomm/src/com/android/server/telecom/Ringer.java
private void updateRinging(Call call) {
if (mRingingCalls.isEmpty()) {
stopRinging(call, "No more ringing calls found");
stopCallWaiting(call);
} else {
//2018-10-10 cczheng add anotation function startRingingOrCallWaiting() for silent call start
Log.d("callRinging", "silent call, will not play ringtone");
// startRingingOrCallWaiting(call);
//2018-10-10 cczheng add anotation function startRingingOrCallWaiting() for silent call end
}
}
是的,注釋掉startRingingOrCallWaiting(call);方法就ok啦
2.來電掛斷庵芭,不出現(xiàn)IncallActivity
思路:監(jiān)聽PhoneState妹懒,當(dāng)監(jiān)聽到響鈴時,直接通過反射調(diào)用endcall方法掛斷電話双吆。監(jiān)聽PhoneStateListener可以寫到廣播中眨唬,當(dāng)收到開機(jī)廣播時,開始監(jiān)聽phoneState好乐,這樣和系統(tǒng)保持同步匾竿。以下是參考代碼
public class PhoneStartReceiver extends BroadcastReceiver {
private static final String TAG = "PhoneStartReceiver";
private PhoneCallListener mPhoneCallListener;
private TelephonyManager mTelephonyManager;
@Override
public void onReceive(final Context context, final Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
// endCall when CALL_STATE_RINGING
initPhoneCallListener(context);
}
}
private void initPhoneCallListener(Context context){
mPhoneCallListener = new PhoneCallListener();
mTelephonyManager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
mTelephonyManager.listen(mPhoneCallListener, PhoneCallListener.LISTEN_CALL_STATE);
}
public class PhoneCallListener extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
Log.v(TAG, "onCallStateChanged-state: " + state);
Log.v(TAG, "onCallStateChanged-incomingNumber: " + incomingNumber);
switch (state) {
case TelephonyManager.CALL_STATE_RINGING:
endCall();
break;
default:
break;
}
super.onCallStateChanged(state, incomingNumber);
}
}
private void endCall() {
try {
Method m1 = mTelephonyManager.getClass().getDeclaredMethod("getITelephony");
if (m1 != null) {
m1.setAccessible(true);
Object iTelephony = m1.invoke(mTelephonyManager);
if (iTelephony != null) {
Method m2 = iTelephony.getClass().getDeclaredMethod("silenceRinger");
if (m2 != null) {
m2.invoke(iTelephony);
Log.v(TAG, "silenceRinger......");
}
Method m3 = iTelephony.getClass().getDeclaredMethod("endCall");
if (m3 != null) {
m3.invoke(iTelephony);
Log.v(TAG, "endCall......");
}
}
}
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, "endCallError", e);
}
}
}
3.攔截未接來電通知,不顯示在狀態(tài)欄StatusBarr中
源碼位置 packages/apps/InCallUI/src/com/android/incallui/StatusBarNotifier.java
private void updateInCallNotification(final InCallState state, CallList callList) {
...
final Call call = getCallToShow(callList);
//2018-10-10 cczheng add intercept incoming notification start
if (true) {
if (call != null) {
Log.v("InCallNotification", "phoneNumber = " + call.getNumber());
}
return;
}
//2018-10-10 cczheng add intercept incoming notification end
if (call != null) {
showNotification(call);
} else {
cancelNotification();
}
...
}
其實(shí)核心方法就是showNotification(call)蔚万,發(fā)送通知當(dāng)statusBar收到通知就處理并顯示在狀態(tài)欄岭妖。
當(dāng)你發(fā)現(xiàn)這樣處理完后,重新mm反璃,然后push替換Dialer.apk重啟后昵慌,你會坑爹的發(fā)現(xiàn)狀態(tài)欄那個未接來電圖標(biāo)依舊顯示,無fa可說淮蜈,繼續(xù)跟蹤日志揪出罪魁禍?zhǔn)渍剩罱K發(fā)現(xiàn)另一處奇葩的地方。
源碼位置 packages/services/Telecomm/src/com/android/server/telecom/ui/MissedCallNotifierImpl.java
諾梧田,就是這了淳蔼,看注釋就明白了吧 Create a system notification for the missed call
/**
* Create a system notification for the missed call.
*
* @param call The missed call.
*/
@Override
public void showMissedCallNotification(Call call) {
////2018-10-10 cczheng hide missed call notification [S]
if (true) {
android.util.Log.i("misscall", "showMissedCallNotification......");
return;
}
///2018-10-10 cczheng hide missed call notification [E]
mMissedCallCount++;
final int titleResId;
final String expandedText; // The text in the notification's line 1 and 2.
....
}
ok,這樣我們就搞定了來電功能柿扣。
三肖方、隱藏短信應(yīng)用和電話應(yīng)用在launcher中顯示(去除AndroidManifest中的category)
<category android:name="android.intent.category.LAUNCHER" />
四、總結(jié)
Android源碼修改沒有大家想象的那么難未状,畢竟Google工程師都已經(jīng)給我們標(biāo)注了詳細(xì)的注釋說明俯画,只是框架和封裝的思路難以理解,這就考驗(yàn)我們的耐心了司草,Log是個好東西艰垂,多加日志泡仗,多分析,這樣很容易上手猜憎。