Android 代碼實現來電攔截


為了更好地理解這個Demo,我先向大家介紹一下需求與功能。

需求:

每天都會有很多無聊的電話,比如推銷商品等,占用我們大量時間不說,有時候還會打亂我們的思路,擾亂我們的正常生活。所以實現一個對某些號碼(比如陌生號碼,指定號碼/黑名單等)進行攔截以避免受到騷擾,是很有現實用途的。

為了避免程序過分復雜,造成不易學習的麻煩我在這里只實現“如果來電號碼沒在聯系人中,則進行掛斷,並存入xml文件(SharedPreferences)中,並在首頁顯示”,以期達到拋磚引玉的效果。

 

其實在android在1.1版本后就已經把Phone類的相關API給隱藏起來了,想要用代碼實現掛斷電話的功能,就必須通過AIDL才行,然后利用反射來使用其方法。

第一步:在程序中新建一個包,包名必須為:com.android.internal.telephony,因為要使用aidl。

第二步:在這個包里面新建一個名為ITelephony.aidl的文件,然后在文件里面寫入代碼:

 

[java]  view plain copy
 
  1. package com.android.internal.telephony;  
  2.     interface ITelephony{  
  3.         boolean endCall();  
  4.         void answerRingingCall();  
  5.     }  

 

 

然后是要監聽電話狀態,當來電時,檢測來電號碼是否符合攔截標准(這個攔截標准是我們自己定的,你可以攔截指定號碼如實現一個黑名單的功能,我們在這里攔截所有不在聯系人里的號碼,並把此號碼存入文件,以方便在首頁顯示),代碼如下:

 

[java]  view plain copy
 
  1. import java.lang.reflect.Method;  
  2. import java.util.ArrayList;  
  3.   
  4. import com.android.internal.telephony.ITelephony;  
  5.   
  6. import android.app.Service;  
  7. import android.content.BroadcastReceiver;  
  8. import android.content.ContentResolver;  
  9. import android.content.Context;  
  10. import android.content.Intent;  
  11. import android.content.SharedPreferences;  
  12. import android.content.SharedPreferences.Editor;  
  13. import android.database.Cursor;  
  14. import android.provider.ContactsContract;  
  15. import android.telephony.TelephonyManager;  
  16. import android.util.Log;  
  17.   
  18. public class PhoneStatReceiver extends BroadcastReceiver{  
  19.   
  20.     String TAG = "tag";  
  21.     TelephonyManager telMgr;  
  22.     @Override  
  23.     public void onReceive(Context context, Intent intent) {  
  24.         telMgr = (TelephonyManager) context.getSystemService(Service.TELEPHONY_SERVICE);  
  25.         switch (telMgr.getCallState()) {  
  26.             case TelephonyManager.CALL_STATE_RINGING:  
  27.                 String number = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);   
  28.                 Log.v(TAG,"number:"+number);  
  29.                 if (!getPhoneNum(context).contains(number)) {  
  30.                     SharedPreferences phonenumSP = context.getSharedPreferences("in_phone_num", Context.MODE_PRIVATE);  
  31.                     Editor editor = phonenumSP.edit();  
  32.                     editor.putString(number,number);  
  33.                     editor.commit();  
  34.                     endCall();  
  35.                 }  
  36.                 break;  
  37.             case TelephonyManager.CALL_STATE_OFFHOOK:                                 
  38.                 break;  
  39.             case TelephonyManager.CALL_STATE_IDLE:                                 
  40.                 break;  
  41.         }  
  42.           
  43.     }  
  44.     /** 
  45.      * 掛斷電話 
  46.      */  
  47.     private void endCall()  
  48.     {  
  49.         Class<TelephonyManager> c = TelephonyManager.class;           
  50.         try  
  51.         {  
  52.             Method getITelephonyMethod = c.getDeclaredMethod("getITelephony", (Class[]) null);  
  53.             getITelephonyMethod.setAccessible(true);  
  54.             ITelephony iTelephony = null;  
  55.             Log.e(TAG, "End call.");  
  56.             iTelephony = (ITelephony) getITelephonyMethod.invoke(telMgr, (Object[]) null);  
  57.             iTelephony.endCall();  
  58.         }  
  59.         catch (Exception e)  
  60.         {  
  61.             Log.e(TAG, "Fail to answer ring call.", e);  
  62.         }          
  63.     }  
  64.     private ArrayList<String>  getPhoneNum(Context context) {  
  65.         ArrayList<String> numList = new ArrayList<String>();  
  66.         //得到ContentResolver對象     
  67.         ContentResolver cr = context.getContentResolver();       
  68.         //取得電話本中開始一項的光標     
  69.         Cursor cursor = cr.query(ContactsContract.Contacts.CONTENT_URI, nullnullnullnull);     
  70.         while (cursor.moveToNext())     
  71.         {                 
  72.             // 取得聯系人ID     
  73.             String contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));     
  74.             Cursor phone = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,  
  75.                     ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactId, nullnull);     
  76.             // 取得電話號碼(可能存在多個號碼)     
  77.             while (phone.moveToNext())     
  78.             {     
  79.                 String strPhoneNumber = phone.getString(phone.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));     
  80.                 numList.add(strPhoneNumber);    
  81.                 Log.v("tag","strPhoneNumber:"+strPhoneNumber);  
  82.             }     
  83.               
  84.             phone.close();     
  85.         }     
  86.         cursor.close();  
  87.         return numList;  
  88.     }  
  89. }  

這里我們要注意以下幾點:

 

1.PhoneStatReceiver一定要在清單文件(AndroidManifest.xml)中注冊。

2.一定要添加權限

AndroidManifest文件如下:

 

[html]  view plain copy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     package="com.xxxx.xxxx"  
  4.     android:versionCode="1"  
  5.     android:versionName="1.0" >  
  6.   
  7.     <uses-sdk android:minSdkVersion="8" />  
  8.     <!-- 掛斷手機的權限 -->  
  9.     <uses-permission android:name="android.permission.CALL_PHONE"/>  
  10.     <!-- 讀取手機狀態的權限 -->  
  11.     <uses-permission android:name="android.permission.READ_PHONE_STATE" />  
  12.     <!-- 讀content的權限 -->  
  13.     <uses-permission android:name="android.permission.READ_CONTACTS" />  
  14.     <application  
  15.         android:icon="@drawable/ic_launcher"  
  16.         android:label="@string/app_name" >  
  17.         <activity  
  18.             android:name=".MainActivity"  
  19.             android:label="@string/app_name" >  
  20.             <intent-filter>  
  21.                 <action android:name="android.intent.action.MAIN" />  
  22.   
  23.                 <category android:name="android.intent.category.LAUNCHER" />  
  24.             </intent-filter>  
  25.         </activity>  
  26.         <!-- 注冊監聽手機狀態 -->  
  27.         <receiver android:name=".PhoneStatReceiver">  
  28.             <intent-filter android:priority="1000" >  
  29.                 <action android:name="android.intent.action.PHONE_STATE" />  
  30.             </intent-filter>  
  31.         </receiver>  
  32.           
  33.     </application>  
  34.   
  35. </manifest>  

其實最到這里,整個攔截功能就已經實現了,但是呢,我們的首頁也不能讓它光禿禿的顯示個Hello World!吧。所以,在MainActivity中,再給大家加點料,就是在listView中顯示所有已經被攔截的電話號碼,代碼如下:

 

 

[java]  view plain copy
 
  1. import java.util.Map;  
  2. import android.app.ListActivity;  
  3. import android.content.Context;  
  4. import android.content.SharedPreferences;  
  5. import android.os.Bundle;  
  6. import android.util.Log;  
  7. import android.widget.ArrayAdapter;  
  8.   
  9. public class MainActivity extends ListActivity {  
  10.     @Override  
  11.     public void onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.           
  14.         SharedPreferences phonenumSP = getSharedPreferences("in_phone_num", Context.MODE_PRIVATE);  
  15.         Map map = phonenumSP.getAll();  
  16.         Object[] array = map.keySet().toArray();  
  17.         Log.v("tag",map.toString()+map.size());  
  18.         ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1,array);  
  19.           
  20.         setListAdapter(adapter);  
  21.     }  
  22. }  

 

好了,整個項目就完成了,我們可以攔截騷擾電話了,這只是一個小例子,你可以添加一些控制功能以更加人性化,比如開啟和關閉攔截,可選的攔截時間段,給ListView添加點擊事件使用戶可以把攔截到的電話添加到通訊錄等功能。

不過,這里只是完成了對來電的攔截功能,未對外撥電話進行攔截,下篇博客再寫吧!

 

參考:http://blog.163.com/wu_zefeng/blog/static/1826291752011312114420975/

    http://www.cotrun.net/blog/1572.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM