上次介绍了如何使用JAVA的反射机制来调用蓝牙的隐藏API,这次继续练习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添加以下两行代码,以获得权限:
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"
?>
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);
}
}
}
|