14.探秘TelephonyManager

上次介绍了如何使用JAVA的反射机制来调用蓝牙的隐藏API,这次继续练习JAVA的反射机制,探秘TelephonyManager在Framework里包含却在SDK隐藏的几项功能。先来看看本文程序运行的效果图:

testTelephony

本文程序演示了以下功能:

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添加以下两行代码,以获得权限:

?
1
2
< uses-permission  android:name = "android.permission.CALL_PHONE"  />
< uses-permission  android:name = "android.permission.MODIFY_PHONE_STATE"  />

main.xml源码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<? xml  version = "1.0"  encoding = "utf-8" ?>
< LinearLayout  xmlns:android = "http://schemas.android.com/apk/res/android"
     android:layout_width = "fill_parent"
     android:layout_height = "fill_parent"
     android:orientation = "vertical"  >
 
     < RadioGroup
         android:id = "@+id/rGrpSelect"
         android:layout_width = "fill_parent"
         android:layout_height = "wrap_content"  >
 
         < RadioButton
             android:id = "@+id/rbtnAutoAccept"
             android:layout_width = "fill_parent"
             android:layout_height = "wrap_content"
             android:text = "所有来电自动接听"  >
         </ RadioButton >
 
         < RadioButton
             android:id = "@+id/rbtnAutoReject"
             android:layout_width = "fill_parent"
             android:layout_height = "wrap_content"
             android:text = "所有来电自动挂断"  >
         </ RadioButton >
     </ RadioGroup >
 
     < ToggleButton
         android:id = "@+id/tbtnRadioSwitch"
         android:layout_width = "fill_parent"
         android:layout_height = "wrap_content"
         android:textOff = "Radio已经关闭"
         android:textOn = "Radio已经启动"
         android:textSize = "24dip"
         android:textStyle = "normal"  >
     </ ToggleButton >
 
     < ToggleButton
         android:id = "@+id/tbtnDataConn"
         android:layout_width = "fill_parent"
         android:layout_height = "wrap_content"
         android:textOff = "禁止数据连接"
         android:textOn = "允许数据连接"
         android:textSize = "24dip"
         android:textStyle = "normal"  >
     </ ToggleButton >
 
</ LinearLayout >

PhoneUtils.java是手机功能类,从TelephonyManager中实例化ITelephony并返回,源码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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种电话控制功能,源码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
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);
         }
     }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值