HardBirch

Android提高第十四篇之探秘TelephonyManager

时间:10-12-09 栏目:安卓入门与提高 作者:张飞不张,文采横飞 评论:53 点击: 16,903 次

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


main.xml源码如下:























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

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种电话控制功能,源码如下:

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提高第十四篇之探秘TelephonyManager

Android提高第十四篇之探秘TelephonyManager:目前有53 条留言

  1. [e01]最近咋一直在android

    2010-12-09 16:49 [回复]
  2. 0楼
    kf156:

    [e01]自动接听挂断来电啊,这个必须顶

    2010-12-09 16:49 [回复]
  3. 0楼
    hmc1985:

    [e01]啥也不说了!

    2010-12-09 16:50 [回复]
  4. 不错,虽被逼着来,但不错

    2010-12-09 16:51 [回复]
  5. 0楼
    hellogv:

    回复 qwe285735942:
    terry…..去51CTO投你对手票[e02]

    2010-12-09 16:55 [回复]
  6. 0楼
    s278777851:

    顶上。。。必须的。。

    2010-12-09 16:56 [回复]
  7. 又有大作了,欣赏。。。能转载么?嘿嘿。。。

    2010-12-10 09:49 [回复]
  8. 0楼
    hellogv:

    回复 fanwander0711:
    这个可以有

    2010-12-10 10:09 [回复]
  9. 回复 hellogv:哈哈,谢谢啊。。。

    2010-12-10 11:51 [回复]
  10. 0楼
    huangbq:

    [e01][e03]楼主牛人,哈哈!目前android防火墙中实现自动挂接电话都是用这个方式实现的,楼主好多人都没有android源码,无法查看ITelephony.aidl怎么写,能否把ITelephony.aidl的代码也加上?

    2010-12-10 12:11 [回复]
  11. PhoneUtils.getITelephony(telMgr).isDataConnectivityPossible()模拟器测试ok,手机测试返回的为什么总是true呢?

    2010-12-10 12:17 [回复]
  12. 0楼
    hellogv:

    回复 shenhaihua002:
    用真机吧

    2010-12-10 17:29 [回复]
  13. [e01]

    2010-12-11 16:12 [回复]
  14. 回复 hellogv:g3,g9测试过了啊,就算我PhoneUtils.getITelephony(telMgr).disableDataConnectivity(); 获得的状态总是true,不知道楼主那怎么样[e06]

    2010-12-12 00:34 [回复]
  15. 0楼
    hellogv:

    回复 shenhaihua002:
    我用的是XT720,那么你的手机的数据连接标记是否消失了呢?

    2010-12-12 08:39 [回复]
  16. 回复 hellogv:数据连接标志确实是关闭了,但是我感觉内部是尝试在连接的,因为返回的还是true,如果直接飞行模式,它就确实返回false了

    2010-12-12 12:46 [回复]
  17. [e01] 顶。。。不解释~

    2010-12-12 17:51 [回复]
  18. 0楼
    kepoon:

    学习了。。。

    2010-12-13 10:28 [回复]
  19. 0楼
    zhy206517:

    怎么可以自动拨打电话,然后自动挂断??

    2010-12-13 22:13 [回复]
  20. 0楼
    hellogv:

    回复 zhy206517:
    响一声电话………..

    2010-12-13 22:15 [回复]
  21. 0楼
    leisc162:

    顶,最近看了一周了,才开始学的

    2010-12-14 13:21 [回复]
  22. 请问楼主大大 打电话的时候电话语音的入口在哪里?我找了好久一直找不到..难道是在C层?
    这个问题困扰了我很久..希望楼主不吝赐教..可以的话麻烦楼主大概说一下语音数据传输的流程..小弟拜谢..

    2010-12-19 23:43 [回复]
  23. 0楼
    hellogv:

    回复 shuiqiang998:
    我也曾经尝试用蓝牙的handset来捕获,后来发现真的是在C层,上层JAVA只能调用C封装好的功能,取不了音频流

    2010-12-20 09:19 [回复]
  24. 回复 hellogv:额..称呼楼主一声师兄可以吧?我是08届中大软院的..那请问有什么方法可以取音频流么?最近我们参加信安大赛..要做这个东西..希望指教..

    2010-12-20 11:25 [回复]
  25. 0楼
    hellogv:

    回复 shuiqiang998:
    信息安全竞赛….我也参加过…….

    2011-01-25 20:37 [回复]
  26. 0楼
    xiaoyaoACi:

    云雀君果然犀利。。[e03]

    2011-03-24 17:38 [回复]
  27. 0楼
    sd4399340:

    我遇到一个很奇怪的问题,我想拦截一个电话,拦截后写入数据库。可能有时响了几下才被挂断,根据时间长短会写入好几条记录,后来我debug了一下,发发现onCallStateChanged被调用了好几次,第一次来电时传入的state为1,然后endCall以后,这个函数又被调用,并且state还是1

    2011-04-05 18:19 [回复]
  28. 0楼
    qqsheji:

    太好了,刚用了下,顶呱呱啊,必须要顶啊

    2011-07-18 17:27 [回复]
  29. 0楼
    wang882588:

    我这有官方代码,吼吼,用ITelephony隐藏代码.吼吼
    你知道怎么在通话的时候获取音频流吗.纠结.
    知道怎么变音不,了解一些的话,可以交流下

    2011-07-26 16:59 [回复]
  30. 0楼
    hellogv:

    [reply]wang882588[/reply]
    这个么做过。。。

    2011-07-27 19:33 [回复]
  31. 总是提示:The method isRadioOn() is undefined for the type ITelephony

    2011-08-04 12:02 [回复]
  32. 0楼
    hellogv:

    [reply]jameslin_2011[/reply]
    真机还是模拟器?

    2011-08-05 07:57 [回复]
  33. 0楼
    jackDG624:

    顶起来!

    2011-08-05 08:37 [回复]
  34. 关闭数据连接的这个 只能在2.2以下的系统用吧?
    2.2以上的我用会抛异常啊

    2011-08-05 10:40 [回复]
  35. [reply]hellogv[/reply]
    多谢回复。原来是ITelephony.aidl接口缺少方法。

    2011-08-08 17:12 [回复]
  36. 能用service 或receiver来监听处理吗

    2011-08-08 17:13 [回复]
  37. 0楼
    stevensbsd:

    打开、关闭数据连接需要MODIFY_PHONE_STATE这个权限,在2.3中这个权限不对普通应用开放了,所以在2.3中用不了。

    在2.2和2.1中,我测试的情况是:必须要在数据连接打开的情况下,用这个方法关闭一次数据连接,然后才可以正常的用这个方法来打开、关闭连接。如果连接一开始是关闭的,这个方法就无效。请问博主,有办法解决这个问题吗?

    2011-08-09 09:00 [回复]
  38. 牛逼啊…

    2011-09-10 16:28 [回复]
  39. 0楼
    qinjuning:

    有启发。

    2011-10-11 13:44 [回复]
  40. 0楼
    nyistwjw:

    不能运行啊 按照程序运行 怎么提示 ActivityManager: Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.XXX/.TestTelephonyActivity } 请教怎么解决 谢谢

    2011-10-17 16:45 [回复]
  41. 0楼
    hellogv:

    [reply]nyistwjw[/reply]
    兄弟,你遇到这个问题之前,有没有搜索过“ ActivityManager: Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=”?我不是google也不是百度

    2011-10-17 23:14 [回复]
  42. 0楼
    nyistwjw:

    搜过的 但是还是那情况 那个Manifest配置没有错 但是不知道为什么出错 难道2.3版本的不行?

    2011-10-18 09:05 [回复]
  43. 0楼
    nyistwjw:

    大哥 好像实现不了自动接听电话 里面没有注册广播

    2011-10-18 16:13 [回复]
  44. 0楼
    hellogv:

    [reply]nyistwjw[/reply]
    在2.2试试,如果2.2OK,2.3 no way,那就是2.3不兼容了

    2011-10-18 16:42 [回复]
  45. 0楼
    hu_hu1221:

    那怎么设置3G与2G呢?

    2011-11-09 17:58 [回复]
  46. 0楼
    hellogv:

    [reply]hu_hu1221[/reply]
    3G是数据通道,2G只是电话,android可以关闭数据通道保留电话功能,看看android的源码,里面有

    2011-11-09 23:19 [回复]
  47. 0楼
    reone:

    问一个很弱的问题:这个ITelephony应该是从TelephonyManager的隐藏API中映射出来的,但是1)我打印出所有的TelephonyManager似乎没有发现有诸如isRadioOn、silenceRinger等等方法,是不是我这边的问题?2)这些调用的方法是需要写在aidl中的,但是我怎么知道底层的API能实现这些方法功能呢?
    这两个问题,望指导

    2011-11-15 11:06 [回复]
  48. 0楼
    hellogv:

    [reply]reone[/reply]
    看看对应版本的android源码就可以知道有木有了

    2011-11-15 19:53 [回复]
  49. 0楼
    anzhu_111:

    楼主,为什么import com.android.internal.telephony.ITelephony;会报错?

    2011-12-21 15:24 [回复]
  50. 谢谢分享。有一个问题想请教下,用了PhoneStateListener 后,只能监听三个状态。对于拨出去的电话,如何能区分现在是在响铃还是对方已接听,从PhoneStateListener 来看都是TelephonyManager.CALL_STATE_OFFHOOK。
    对方何时接起电话,我们监听不到吗?

    2011-12-30 16:40 [回复]
  51. 0楼
    zhuyz89:

    学习学习

    2012-03-19 13:26 [回复]
  52. 0楼
    gmangman:

    楼主 请问在我这 PhoneUtils.getITelephony(telMgr).silenceRinger(); 这个方法为什么不能静音呢?我是想屏蔽系统默认铃声,从而播放自定义铃声,可是用这个方法也无法静止系统的铃声。请赐教!

    2012-05-24 11:23 [回复]
  53. 楼主,您讲的都必须在真机上实验?在模拟器上完全不行。

    2012-07-03 11:17 [回复]

发表评论


QQ群互动

Linux系统与内核学习群:194051772

WP建站技术学习交流群:194062106

魔豆之路QR

魔豆的Linux内核之路

魔豆的Linux内核之路

优秀工程师当看优秀书籍

优秀程序员,要看优秀书!

赞助商广告

友荐云推荐