android 4.2 短信發送流程分析可參考這篇 戳這java
源碼位置 vendor\mediatek\proprietary\packages\apps\Mms\src\com\android\mms\transaction\SmsReceiverService.javaandroid
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()方法。數據庫
源碼位置同上網絡
SmsMessage.getMessageBody() 獲取短信內容app
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); } }
須要添加SmsReceiver,MmsReceiver,ComposeSmsActivity,HeadlessSmsSendService這幾個類,並在AndroidManifest中進行相應配置,具體流程可參考這篇 戳這less
屏蔽系統來電可分爲三個步驟ide
1.來電靜音,不響鈴ui
2.來電掛斷,不出現IncallActivity.net
三、攔截未接來電通知,不顯示在狀態欄StatusBar中
ps:此種修改方式的弊端在於來電時網絡數據會離線2s左右
好,如今咱們開始按這三個步驟來修改源碼
源碼位置 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啦
思路:監聽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); } } }
源碼位置 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,這樣咱們就搞定了來電功能。
<category android:name="android.intent.category.LAUNCHER" />
Android源碼修改沒有你們想象的那麼難,畢竟Google工程師都已經給咱們標註了詳細的註釋說明,只是框架和封裝的思路難以理解,這就考驗咱們的耐心了,Log是個好東西,多加日誌,多分析,這樣很容易上手。