內容觀察者 ContentObserver 監聽簡訊、通話記錄資料庫 結束通話來電
阿新 • • 發佈:2019-02-01
Activity
publicclass MainActivity extends ListActivity { private TextView tv_info; private SMSContentObserver smsContentObserver; private CallLogObserver callLogObserver; private PhoneStateReceiver myReceiver; @SuppressLint("HandlerLeak") private Handler mHandler = new Handler() {public void handleMessage(Message msg) { String msgBody = (String) msg.obj; tv_info.setText(msg.obj + ":" + msgBody); } }; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String[] array = { "註冊簡訊資料庫變化的觀察者", "收件箱資料庫……", "刪除新來電的通話記錄", "監聽新來電通話記錄的詳細資訊", "取消註冊Observer",// "註冊電話狀態改變的廣播,當有來電時立即結束通話電話", "取消註冊廣播", }; for (int i = 0; i < array.length; i++) { array[i] = i + "、" + array[i]; } ListAdapter mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, new ArrayList<String>(Arrays.asList(array))); tv_info = new TextView(this);// 將內容顯示在TextView中 tv_info.setTextColor(Color.BLUE); tv_info.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); tv_info.setPadding(20, 10, 20, 10); getListView().addFooterView(tv_info); setListAdapter(mAdapter); myReceiver = new PhoneStateReceiver(); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { switch (position) { case 0: smsContentObserver = new SMSContentObserver(mHandler, this, SMSContentObserver.MSG_SMS_WHAT); getContentResolver().registerContentObserver(Uri.parse("content://sms"), true, smsContentObserver); // boolean notifyForDescendents(後裔):若為true,則監視所有以指定的Uri開頭的Uri;若為false,則只精確的監視指定的URI break; case 1: smsContentObserver = new SMSContentObserver(mHandler, this, SMSContentObserver.MSG_SMS_INBOX_WHAT); getContentResolver().registerContentObserver(Uri.parse("content://sms/inbox"), true, smsContentObserver); break; case 2: callLogObserver = new CallLogObserver(mHandler, this, CallLogObserver.MSG_CALLLOG_DELETE_WHAT); getContentResolver().registerContentObserver(Uri.parse("content://call_log/calls"), true, callLogObserver); break; case 3: callLogObserver = new CallLogObserver(mHandler, this, CallLogObserver.MSG_CALLLOG_QUERY_WHAT); getContentResolver().registerContentObserver(CallLog.Calls.CONTENT_URI, true, callLogObserver);//等價於【Uri.parse("content://call_log/calls")】 break; case 4: if (smsContentObserver != null) getContentResolver().unregisterContentObserver(smsContentObserver); if (callLogObserver != null) getContentResolver().unregisterContentObserver(callLogObserver); break; case 5: registerReceiver(myReceiver, new IntentFilter(TelephonyManager.ACTION_PHONE_STATE_CHANGED)); break; case 6: try { unregisterReceiver(myReceiver); } catch (Exception e) { } break; } } /** * 利用aidl及反射自動結束通話來電。注意,不能通過ContentResolver監聽通話記錄資料庫來結束通話電話,估計是因為電話已接通,不能再掛掉了 */ public void endCall() { // IBinder iBinder = ServiceManager.getService(TELEPHONY_SERVICE);//希望呼叫的方法,但此方法被系統隱藏了 try { Class<?> clazz = Class.forName("android.os.ServiceManager");//利用反射拿到其位元組碼檔案 Method method = clazz.getDeclaredMethod("getService", String.class);//獲取ServiceManager類的getService(String s)方法 IBinder ibinder = (IBinder) method.invoke(null, Context.TELEPHONY_SERVICE);//引數為:呼叫此方法的物件,此方法的引數 ITelephony telephony = ITelephony.Stub.asInterface(ibinder);//把上面getService(String s)得到的IBinder物件轉化成【ITelephony】物件 boolean isSuccess = telephony.endCall();//呼叫ITelephony結束通話電話的方法 mHandler.sendMessage(Message.obtain(mHandler, 5, "是否成功結束通話電話:" + isSuccess)); } catch (Exception e) { mHandler.sendMessage(Message.obtain(mHandler, 5, "異常啦" + e.getMessage())); e.printStackTrace(); } } /**監聽來電狀態的廣播*/ class PhoneStateReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (intent != null) { if (TelephonyManager.EXTRA_STATE_RINGING.equalsIgnoreCase(intent.getStringExtra(TelephonyManager.EXTRA_STATE))) {//來電狀態 endCall(); } } } }}
簡訊資料庫的ContentObserver
/**監聽或獲取手機簡訊內容的兩種方式 * 方式一:通過註冊廣播監聽簡訊 * 這種方式只對新收到的短訊息有效,並且系統的這個廣播是有序廣播,現在在一些定製的系統或是有安全軟體的情況下,往往短訊息都被擷取到,並被幹掉。 * 方法二:通過監聽簡訊資料庫的變化獲取簡訊 * 這種方式可以獲取手機上所有的簡訊,包括已讀未讀的簡訊,並且不受其它程式干擾 * ContentObserver的使用類似與設計模式中的觀察者模式,ContentObserver是觀察者,被觀察的ContentProvider是被觀察者。 * 當被觀察者ContentProvider的資料發生了增刪改的變化,就會及時的通知給ContentProvider,ContentObsserver做出相應的處理。*/publicclass SMSContentObserver extends ContentObserver { private Handler mHandler; private Context mContext; /**觀察型別:所有內容或僅收件箱*/ private int observerType; /**觀察所有內容*/ public static final int MSG_SMS_WHAT = 1; /**僅觀察收件箱*/ public static final int MSG_SMS_INBOX_WHAT = 2; public SMSContentObserver(Handler handler, Context context, int observerType) { super(handler); this.mHandler = handler; this.mContext = context; this.observerType = observerType; } @Override public void onChange(