1. 程式人生 > >Android初級教程反射+AIDL+內容觀察者監控黑名單號碼程式碼模板

Android初級教程反射+AIDL+內容觀察者監控黑名單號碼程式碼模板

對於想要攔截一些莫名的陌生號碼,就需要電話攔截功能與刪除其電話記錄功能。攔截的主要業務邏輯,分別是在一個服務裡面進行:1、註冊電話監聽;2、取消註冊電話監聽(當然註冊於取消是在服務裡面建立一個廣播接收者)。刪除電話日誌的功能,是靠內容觀察者和內容提供者。

下面給出實現電話監聽,取消註冊監聽,內容觀察者監聽電話資料庫狀態的主要程式碼。對於以後開發此類產品,不需要去檢視系統原始碼,複製貼上這段程式碼就行了。下面給出程式碼:

一、註冊電話監聽與內容觀察者監控電話資料庫狀態:

  因為是在服務裡面,因此,註冊寫在onCreate方法裡面

	<span style="font-size:12px;">@Override
	public void onCreate() {

		// 註冊電話監聽
		// 通過電話管理類TelephoneManager
		tm = (TelephoneManager</span><span style="font-size:12px;">) getSystemService(TELEPHONY_SERVICE);
		
		// 監聽電話的狀態
		listener = new PhoneStateListener() {

			/*
			 * (non-Javadoc) 該方法用來監聽電話的狀態
			 * 
			 * @see android.telephony.PhoneStateListener#onCallStateChanged(int,
			 * java.lang.String)
			 */
			@Override
			public void onCallStateChanged(int state, final String incomingNumber) {
				// TODO Auto-generated method stub
				// state 電話的狀態 incomingNumber 打進來的號碼
				switch (state) {
				case TelephonyManager.CALL_STATE_IDLE:// 結束通話的狀態,空閒的狀態
					System.out.println("CALL_STATE_IDLE");
					break;
				case TelephonyManager.CALL_STATE_RINGING://響鈴狀態
					System.out.println("CALL_STATE_RINGING");
					//判斷是否是黑名單號碼
					//獲取電話的模式
					int mode = dao.getMode(incomingNumber);
					
					//如果是攔截號碼
					if ((mode & BlackTable.TEL) != 0) {
						//電話攔截
						System.out.println("結束通話電話");
						//結束通話電話之前先註冊內容觀察者,新生成的日誌之後(資料庫發生改變)
						getContentResolver().registerContentObserver(Uri.parse("content://call_log/calls"), true,
								new ContentObserver(new Handler()) {

									@Override
									public void onChange(boolean selfChange) {
										//電話日誌變化 觸發此方法呼叫
										deleteCalllog(incomingNumber);//刪除電話日誌
										
										super.onChange(selfChange);
									}
							
						});
						endCall();
						
					}
					break;
				case TelephonyManager.CALL_STATE_OFFHOOK:// 通話的狀態
					System.out.println("CALL_STATE_OFFHOOK");
					break;

				default:
					break;
				}
				super.onCallStateChanged(state, incomingNumber);
			}

		};

		// 註冊電話的監聽
		tm.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
		super.onCreate();
	}

	/**
	 * 刪除電話日誌
	 * @param incomingNumber
	 *     要刪除日誌的號碼
	 */
	protected void deleteCalllog(String incomingNumber) {
		//只能內容提供者來刪除電話日誌
		Uri uri = Uri.parse("content://call_log/calls");
		//刪除指定號碼(黑名單號碼)日誌
		getContentResolver().delete(uri, "number=?", new String[]{incomingNumber});
		
	}

	/**
	 * 結束通話電話:反射+AIDL
	 */
	protected void endCall() {
		//tm.endCall(); 1.5版本後,把該方法閹割掉了
		//想用該功能,實現方法
		//ServiceManager.getService();
		//反射呼叫
		//1.class  
		try {
			Class clazz = Class.forName("android.os.ServiceManager");
			//2. method
			Method method = clazz.getDeclaredMethod("getService", String.class);
			
			//3.obj 不需要 因為是靜態方法
			//4. 呼叫
			IBinder binder = (IBinder) method.invoke(null, Context.TELEPHONY_SERVICE);
			
			//5.aidl 
			ITelephony iTelephony = ITelephony.Stub.asInterface(binder);
			iTelephony.endCall();//結束通話電話
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (RemoteException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}</span>
因為用到AIDL因此,要把在相應應用中加入兩個檔案:截圖:


若用到了相應的功能,直接複製核心程式碼就行了