上次介绍了如何使用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添加以下两行代码,以获得权限:
<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: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并返回,源码如下:
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);
}
}