一、屏蔽系統簡訊功能 1、屏蔽所有簡訊 android 4.2 簡訊發送流程分析可參考這篇 [戳這][1] 源碼位置 vendor\mediatek\proprietary\packages\apps\Mms\src\com\android\mms\transaction\SmsReceiverSe ...
一、屏蔽系統簡訊功能
1、屏蔽所有簡訊
android 4.2 簡訊發送流程分析可參考這篇 戳這
源碼位置 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即可,不去解析和分發簡訊消息,同時這樣操作 簡訊將不會記錄到簡訊資料庫中,插入簡訊消息到資料庫的方法見下文insertMessage()方法。
2、屏蔽特定的簡訊(特定的簡訊號碼或者簡訊內容)
源碼位置同上
- SmsMessage.getOriginatingAddress() 獲取簡訊號碼
SmsMessage.getMessageBody() 獲取簡訊內容
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()) || "話費".contains(tmpsms.getMessageBody())) { Log.i("SmsReceived", "handleSmsReceived"); return; } //2018-10-09 cczheng add for intercept mms notifications end .... }
是否插入簡訊消息到資料庫,insertMessage()方法在handleSmsReceived()中調用
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、應用層攔截簡訊(不用修改android源碼,原理就是用你的app去替代系統預設的簡訊app,過程略繁瑣)
需要添加SmsReceiver,MmsReceiver,ComposeSmsActivity,HeadlessSmsSendService這幾個類,併在AndroidManifest中進行相應配置,具體流程可參考這篇 戳這
二、屏蔽系統來電響鈴和通知提示
屏蔽系統來電可分為三個步驟
1.來電靜音,不響鈴
2.來電掛斷,不出現IncallActivity
3、攔截未接來電通知,不顯示在狀態欄StatusBar中
ps:此種修改方式的弊端在於來電時網路數據會離線2s左右
好,現在我們開始按這三個步驟來修改源碼
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.來電掛斷,不出現IncallActivity
思路:監聽PhoneState,當監聽到響鈴時,直接通過反射調用endcall方法掛斷電話。監聽PhoneStateListener可以寫到廣播中,當收到開機廣播時,開始監聽phoneState,這樣和系統保持同步。以下是參考代碼
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.攔截未接來電通知,不顯示在狀態欄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();
}
...
}
其實核心方法就是showNotification(call),發送通知當statusBar收到通知就處理並顯示在狀態欄。
當你發現這樣處理完後,重新mm,然後push替換Dialer.apk重啟後,你會坑爹的發現狀態欄那個未接來電圖標依舊顯示,無fa可說,繼續跟蹤日誌揪出罪魁禍首,最終發現另一處奇葩的地方。
源碼位置 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,這樣我們就搞定了來電功能。
三、隱藏簡訊應用和電話應用在launcher中顯示(去除AndroidManifest中的category)
<category android:name="android.intent.category.LAUNCHER" />
四、總結
Android源碼修改沒有大家想象的那麼難,畢竟Google工程師都已經給我們標註了詳細的註釋說明,只是框架和封裝的思路難以理解,這就考驗我們的耐心了,Log是個好東西,多加日誌,多分析,這樣很容易上手。