本文來自[http://blog.csdn.net/hellogv/](http://blog.csdn.net/hellogv/) ,引用必須注明出處!
?????? 上次介紹了如何使用JAVA的反射機制來[調用藍牙的隱藏API](http://blog.csdn.net/hellogv/archive/2010/11/29/6042091.aspx),這次繼續練習JAVA的反射機制,探秘TelephonyManager在Framework里包含卻在SDK隱藏的幾項功能。先來看看本文程序運行的效果圖:

本文程序演示了以下功能:
1.所有來電自動接聽;
2.所有來電自動掛斷;
3.開啟/關閉Radio;
4.開啟/關閉數據連接(WAP or NET的連接)。
調用TelephonyManager的隱藏API是先參考Framework的/base/telephony/java/com/android/internal/telephony/ITelephony.aidl,然后自己實現一個ITelephony.aidl,最后在TelephonyManager中通過反射機制實例化自定義的ITelephony,實例化之后就可以調用ITelephony里面的函數了。
本文程序需要在AndroidManifest.xml添加以下兩行代碼,以獲得權限:
<uses-permission android:name="android.permission.CALL_PHONE" /><uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
main.xml源碼如下:
~~~
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <RadioGroup android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/rGrpSelect"> <RadioButton android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/rbtnAutoAccept" android:text="所有來電自動接聽"></RadioButton> <RadioButton android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/rbtnAutoReject" android:text="所有來電自動掛斷"></RadioButton> </RadioGroup> <ToggleButton android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/tbtnRadioSwitch" android:textOn="Radio已經啟動" android:textOff="Radio已經關閉" android:textSize="24dip" android:textStyle="normal"></ToggleButton> <ToggleButton android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="@+id/tbtnDataConn" android:textSize="24dip" android:textStyle="normal" android:textOn="允許數據連接" android:textOff="禁止數據連接"></ToggleButton></LinearLayout>
~~~
PhoneUtils.java是手機功能類,從TelephonyManager中實例化ITelephony并返回,源碼如下:
~~~
package com.testTelephony;import java.lang.reflect.Field;import java.lang.reflect.Method;import com.android.internal.telephony.ITelephony;import android.telephony.TelephonyManager;import android.util.Log;public class PhoneUtils { /** * 從TelephonyManager中實例化ITelephony,并返回 */ static public ITelephony getITelephony(TelephonyManager telMgr) throws Exception { Method getITelephonyMethod = telMgr.getClass().getDeclaredMethod("getITelephony"); getITelephonyMethod.setAccessible(true);//私有化函數也能使用 return (ITelephony)getITelephonyMethod.invoke(telMgr); } static public void printAllInform(Class clsShow) { try { // 取得所有方法 Method[] hideMethod = clsShow.getDeclaredMethods(); int i = 0; for (; i < hideMethod.length; i++) { Log.e("method name", hideMethod[i].getName()); } // 取得所有常量 Field[] allFields = clsShow.getFields(); for (i = 0; i < allFields.length; i++) { Log.e("Field name", allFields[i].getName()); } } catch (SecurityException e) { // throw new RuntimeException(e.getMessage()); e.printStackTrace(); } catch (IllegalArgumentException e) { // throw new RuntimeException(e.getMessage()); e.printStackTrace(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
~~~
testTelephony.java是主類,使用PhoneStateListener監聽通話狀態,以及實現上述4種電話控制功能,源碼如下:
~~~
package com.testTelephony;import android.app.Activity;import android.os.Bundle;import android.telephony.PhoneStateListener;import android.telephony.TelephonyManager;import android.util.Log;import android.view.View;import android.widget.RadioGroup;import android.widget.ToggleButton;public class testTelephony extends Activity { /** Called when the activity is first created. */ RadioGroup rg;//來電操作單選框 ToggleButton tbtnRadioSwitch;//Radio開關 ToggleButton tbtnDataConn;//數據連接的開關 TelephonyManager telMgr; CallStateListener stateListner; int checkedId=0; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); telMgr= (TelephonyManager)getSystemService(TELEPHONY_SERVICE); telMgr.listen(new CallStateListener(), CallStateListener.LISTEN_CALL_STATE); PhoneUtils.printAllInform(TelephonyManager.class); rg = (RadioGroup)findViewById(R.id.rGrpSelect); rg.setOnCheckedChangeListener(new CheckEvent()); tbtnRadioSwitch=(ToggleButton)this.findViewById(R.id.tbtnRadioSwitch); tbtnRadioSwitch.setOnClickListener(new ClickEvent()); try { tbtnRadioSwitch.setChecked(PhoneUtils.getITelephony(telMgr).isRadioOn()); } catch (Exception e) { Log.e("error",e.getMessage()); } tbtnDataConn=(ToggleButton)this.findViewById(R.id.tbtnDataConn); tbtnDataConn.setOnClickListener(new ClickEvent()); try { tbtnDataConn.setChecked(PhoneUtils.getITelephony(telMgr).isDataConnectivityPossible()); } catch (Exception e) { Log.e("error",e.getMessage()); } } /** * 來電時的操作 * @author GV * */ public class CheckEvent implements RadioGroup.OnCheckedChangeListener{ @Override public void onCheckedChanged(RadioGroup group, int checkedId) { testTelephony.this.checkedId=checkedId; } } /** * Radio和數據連接的開關 * @author GV * */ public class ClickEvent implements View.OnClickListener{ @Override public void onClick(View v) { if (v == tbtnRadioSwitch) { try { PhoneUtils.getITelephony(telMgr).setRadio(tbtnRadioSwitch.isChecked()); } catch (Exception e) { Log.e("error", e.getMessage()); } } else if(v==tbtnDataConn){ try { if(tbtnDataConn.isChecked()) PhoneUtils.getITelephony(telMgr).enableDataConnectivity(); else if(!tbtnDataConn.isChecked()) PhoneUtils.getITelephony(telMgr).disableDataConnectivity(); } catch (Exception e) { Log.e("error", e.getMessage()); } } } } /** * 監視電話狀態 * @author GV * */ public class CallStateListener extends PhoneStateListener { @Override public void onCallStateChanged(int state, String incomingNumber) { if(state==TelephonyManager.CALL_STATE_IDLE)//掛斷 { Log.e("IDLE",incomingNumber); } else if(state==TelephonyManager.CALL_STATE_OFFHOOK)//接聽 { Log.e("OFFHOOK",incomingNumber); } else if(state==TelephonyManager.CALL_STATE_RINGING)//來電 { if(testTelephony.this.checkedId==R.id.rbtnAutoAccept) { try { //需要<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" /> PhoneUtils.getITelephony(telMgr).silenceRinger();//靜鈴 PhoneUtils.getITelephony(telMgr).answerRingingCall();//自動接聽 } catch (Exception e) { Log.e("error",e.getMessage()); } } else if(testTelephony.this.checkedId==R.id.rbtnAutoReject) { try { PhoneUtils.getITelephony(telMgr).endCall();//掛斷 PhoneUtils.getITelephony(telMgr).cancelMissedCallsNotification();//取消未接顯示 } catch (Exception e) { Log.e("error",e.getMessage()); } } } super.onCallStateChanged(state, incomingNumber); } }}
~~~
- 前言
- Android提高第一篇之MediaPlayer
- Android提高第二篇之SurfaceView的基本使用
- Android提高第三篇之SurfaceView與多線程的混搭
- Android提高第四篇之Activity+Intent
- Android提高第五篇之Service
- Android提高第六篇之BroadcastReceiver
- Android提高第七篇之XML解析與生成
- Android提高第八篇之SQLite分頁讀取
- Android提高第九篇之SQLite分頁表格
- Android提高第十篇之AudioRecord實現&quot;助聽器&quot;
- Android提高第十一篇之模擬信號示波器
- Android提高第十二篇之藍牙傳感應用
- Android提高第十三篇之探秘藍牙隱藏API
- Android提高第十四篇之探秘TelephonyManager
- Android提高第十五篇之ListView自適應實現表格
- Android提高十六篇之使用NDK把彩圖轉換灰度圖
- Android上使用ASIFT實現對視角變化更魯棒的特征匹配
- 在Android上使用ZXing識別條形碼/二維碼
- Android提高十七篇之多級樹形菜單的實現
- Android-opencv之CVCamera
- Android提高十八篇之自定義Menu(TabMenu)
- Android提高第十九篇之&quot;多方向&quot;抽屜
- Android提高第二十篇之MediaPlayer播放網絡音頻
- Android提高第二十一篇之MediaPlayer播放網絡視頻
- android平板上的GridView視圖緩存優化
- 精確監聽AbsListView滾動至底部
- 可動態布局的Android抽屜之基礎
- 可動態布局的Android抽屜之完整篇
- Android MediaPlayer與Http Proxy結合之基礎篇