1. 程式人生 > >內容觀察者 ContentObserver 監聽簡訊、通話記錄資料庫 結束通話來電

內容觀察者 ContentObserver 監聽簡訊、通話記錄資料庫 結束通話來電

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(mHandlerthis, SMSContentObserver.MSG_SMS_WHAT);            getContentResolver().registerContentObserver(Uri.parse("content://sms"), truesmsContentObserver);            // boolean notifyForDescendents(後裔):若為true,則監視所有以指定的Uri開頭的Uri;若為false,則只精確的監視指定的URI            break;        case 1:            smsContentObserver = new SMSContentObserver(mHandlerthis, SMSContentObserver.MSG_SMS_INBOX_WHAT);            getContentResolver().registerContentObserver(Uri.parse("content://sms/inbox"), truesmsContentObserver);            break;        case 2:            callLogObserver = new CallLogObserver(mHandlerthis, CallLogObserver.MSG_CALLLOG_DELETE_WHAT);            getContentResolver().registerContentObserver(Uri.parse("content://call_log/calls"), truecallLogObserver);            break;        case 3:            callLogObserver = new CallLogObserver(mHandlerthis, CallLogObserver.MSG_CALLLOG_QUERY_WHAT);            getContentResolver().registerContentObserver(CallLog.Calls.CONTENT_URItruecallLogObserver);//等價於【Uri.parse("content://call_log/calls")】            break;        case 4:            if (smsContentObserver != nullgetContentResolver().unregisterContentObserver(smsContentObserver);            if (callLogObserver != null) getContentResolver().unregisterContentObserver(callLogObserver);            break;        case 5:            registerReceiver(myReceivernew 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(