http://blog.csdn.net/tyfjy/article/details/6452126

今天介绍一下在Android中实现通话接通后震动提示,这里通话主要是针对拨出的电话.想要在接通的时候给出震动提示那么我们就需要知道通话何时是被接通的.这样才能在进入该状态后给出提示.但SDK中并没有直接获得这种状态的方式.首先我们看一下SDK中电话服务类为我们提供了哪些通话状态.

SDK中的TelephonyManager类提供了3种电话的状态.

CALL_STATE_IDLE空闲状态

CALL_STATE_OFFHOOK摘机状态

CALL_STATE_RINGING响铃状态

这几个状态很容易理解,其中摘机状态即拿起话筒(对于座机电话而言的动作),但这个状态可能发生在拨入电话接通时,也可能是拨出电话时.但是却不能说明拨出电话接通时.通过以上3种状态我们仅能组合出:挂机,来电接通.这两个状态.而今天我们要实现的功能却无法做到.

看来我们需要寻找其他方法来实现了,SDK靠不住啊……

还好Android在运行时会有大量的log产生,看看我们能不能从这上面找到突波口呢.我们选择Android的Radio模块的日志来分析.首先我们需要写一段代码来读取Radio相关的log.读取log就不得不用到logcat了.

Process process;

InputStream inputstream;

BufferedReader bufferedreader;

try{

process = Runtime.getRuntime().exec("logcat -v time -b radio");

inputstream = process.getInputStream();

InputStreamReader inputstreamreader =newInputStreamReader(

inputstream);

bufferedreader =newBufferedReader(inputstreamreader);

String str ="";

while((str = bufferedreader.readLine()) !=null) {

log.i("mLogcat",str);

}

}catch(Exception e) {

}Process process;

InputStream inputstream;

BufferedReader bufferedreader;

try {

process = Runtime.getRuntime().exec("logcat -v time -b radio");

inputstream = process.getInputStream();

InputStreamReader inputstreamreader = new InputStreamReader(

inputstream);

bufferedreader = new BufferedReader(inputstreamreader);

String str = "";

while ((str = bufferedreader.readLine()) != null) {

log.i("mLogcat",str);

}

} catch (Exception e) {

}

另外,要让程序能够读取系统log需要指定权限,在AndroidManifest.xml文件中加入一下内容.

通过上面这段代码我们就可以将Radio的log输出到了,这样我们就可以通过在DDMS中查看这些log,分析其中的通话过程.具体抓到的log就不贴出来了.大家可以自己编写程序通过上面的代码来抓取和分析.我只说一下我的分析结果.

通过分析log发现了一些蛛丝马迹.其中有几条日志很有用.

GET_CURRENT_CALLS  id=1,DIALING

GET_CURRENT_CALLS  id=1,ALERTING

GET_CURRENT_CALLS  id=1,ACTIVE

由于log较长我只拿了每条log的开头部分,真实的会多很多内容.当我们拨出电话的时候,会输入这么几条log.

拨号->提醒->活动.

大致是这么个过程.经过几次测试发现,电话接通时会进入活动状态,并会输出:GET_CURRENT_CALLS  id=1,ACTIVE这条log,至此我们已经接近成功了.

不过之后我又发现在拨号开始到电话接通这段时间内会经过多次的

拨号->提醒->活动,这样的状态变化,仅当话筒中嘟声响起后GET_CURRENT_CALLS这条日志会锁定在ALERTING.在电话接通前便不再出现

GET_CURRENT_CALLS日志了.

可能上面的这段表述大家不是很清楚,换句话说在通话接通之前会出现多次的

GET_CURRENT_CALLS ACTIVE这样的日志,而仅有一次是电话接通产生的.这就给我们造成了麻烦.不能只是单纯的抓取GET_CURRENT_CALLS ACTIVE这样的信息来判断了.

我们只能通过一些逻辑上的判断来实现了.下面看我的代码.

classTestThreadimplementsRunnable {

//振动器

Vibrator mVibrator;

//电话服务

TelephonyManager telManager;

publicTestThread(Vibrator mVibrator, TelephonyManager telManager) {

this.mVibrator = mVibrator;

this.telManager = telManager;

}

@Override

publicvoidrun() {

//获取当前话机状态

intcallState = telManager.getCallState();

Log.i("TestService","开始.........."+ Thread.currentThread().getName());

//记录拨号开始时间

longthreadStart = System.currentTimeMillis();

Process process;

InputStream inputstream;

BufferedReader bufferedreader;

try{

process = Runtime.getRuntime().exec("logcat -v time -b radio");

inputstream = process.getInputStream();

InputStreamReader inputstreamreader =newInputStreamReader(

inputstream);

bufferedreader =newBufferedReader(inputstreamreader);

String str ="";

longdialingStart =0;

booleanenableVibrator =false;

booleanisAlert =false;

while((str = bufferedreader.readLine()) !=null) {

//如果话机状态从摘机变为空闲,销毁线程

if(callState == TelephonyManager.CALL_STATE_OFFHOOK

&& telManager.getCallState() == TelephonyManager.CALL_STATE_IDLE) {

break;

}

// 线程运行5分钟自动销毁

if(System.currentTimeMillis() - threadStart >300000) {

break;

}

Log.i("TestService", Thread.currentThread().getName() +":"

+ str);

// 记录GSM状态DIALING

if(str.contains("GET_CURRENT_CALLS")

&& str.contains("DIALING")) {

// 当DIALING开始并且已经经过ALERTING或者首次DIALING

if(!isAlert || dialingStart ==0) {

//记录DIALING状态产生时间

dialingStart = System.currentTimeMillis();

isAlert =false;

}

continue;

}

if(str.contains("GET_CURRENT_CALLS")

&& str.contains("ALERTING")&&!enableVibrator) {

longtemp = System.currentTimeMillis() - dialingStart;

isAlert =true;

//这个是关键,当第一次DIALING状态的时间,与当前的ALERTING间隔时间在1.5秒以上并且在20秒以内的话

//那么认为下次的ACTIVE状态为通话接通.

if(temp >1500&& temp <20000) {

enableVibrator =true;

Log.i("TestService","间隔时间....."+ temp +"....."

+ Thread.currentThread().getName());

}

continue;

}

if(str.contains("GET_CURRENT_CALLS") && str.contains("ACTIVE")

&& enableVibrator) {

mVibrator.vibrate(100);

enableVibrator =false;

break;

}

}

Log.i("TestService","结束.........."

+ Thread.currentThread().getName());

}catch(Exception e) {

// TODO: handle exception

}

}

}class TestThread implements Runnable {

//振动器

Vibrator mVibrator;

//电话服务

TelephonyManager telManager;

public TestThread(Vibrator mVibrator, TelephonyManager telManager) {

this.mVibrator = mVibrator;

this.telManager = telManager;

}

@Override

public void run() {

//获取当前话机状态

int callState = telManager.getCallState();

Log.i("TestService", "开始.........." + Thread.currentThread().getName());

//记录拨号开始时间

long threadStart = System.currentTimeMillis();

Process process;

InputStream inputstream;

BufferedReader bufferedreader;

try {

process = Runtime.getRuntime().exec("logcat -v time -b radio");

inputstream = process.getInputStream();

InputStreamReader inputstreamreader = new InputStreamReader(

inputstream);

bufferedreader = new BufferedReader(inputstreamreader);

String str = "";

long dialingStart = 0;

boolean enableVibrator = false;

boolean isAlert = false;

while ((str = bufferedreader.readLine()) != null) {

//如果话机状态从摘机变为空闲,销毁线程

if (callState == TelephonyManager.CALL_STATE_OFFHOOK

&& telManager.getCallState() == TelephonyManager.CALL_STATE_IDLE) {

break;

}

// 线程运行5分钟自动销毁

if (System.currentTimeMillis() - threadStart > 300000) {

break;

}

Log.i("TestService", Thread.currentThread().getName() + ":"

+ str);

// 记录GSM状态DIALING

if (str.contains("GET_CURRENT_CALLS")

&& str.contains("DIALING")) {

// 当DIALING开始并且已经经过ALERTING或者首次DIALING

if (!isAlert || dialingStart == 0) {

//记录DIALING状态产生时间

dialingStart = System.currentTimeMillis();

isAlert = false;

}

continue;

}

if (str.contains("GET_CURRENT_CALLS")

&& str.contains("ALERTING")&&!enableVibrator) {

long temp = System.currentTimeMillis() - dialingStart;

isAlert = true;

//这个是关键,当第一次DIALING状态的时间,与当前的ALERTING间隔时间在1.5秒以上并且在20秒以内的话

//那么认为下次的ACTIVE状态为通话接通.

if (temp > 1500 && temp < 20000) {

enableVibrator = true;

Log.i("TestService", "间隔时间....." + temp + "....."

+ Thread.currentThread().getName());

}

continue;

}

if (str.contains("GET_CURRENT_CALLS") && str.contains("ACTIVE")

&& enableVibrator) {

mVibrator.vibrate(100);

enableVibrator = false;

break;

}

}

Log.i("TestService", "结束.........."

+ Thread.currentThread().getName());

} catch (Exception e) {

// TODO: handle exception

}

}

}

我的这个方法比较牵强,是通过判断第一次DIALING与每一次ALERTING之间的间隔,当间隔大于1.5秒.那么认为已经进入了"嘟"声提示的时候了,那么下一个ACTIVE将是电话接通.这个1.5秒是通过分析日志得出的.但是这种方法我始终觉得不太靠谱.如果大家有好的方法可以交流交流.

剩下的就是让这个线程在电话拨出时触发,并且常驻在电话中时候准备这就可以了.可以采用Service配合Receiver来实现.Service来实现常驻,Receiver来实现监听拨出电话.基本就可以完成,我们想要的功能了.

以上代码我都测试过99%有效,哈哈.这里面提到了一些Android的基础内容像logcat,Service,Receiver.这些如果大家不了解的话可以到网上搜一下.有很多写的很不错的文章介绍Android的基础内容.我这里就不一一介绍了.

希望我写的东西对大家有所帮助.OK,就到这里吧.

android 通话的log分析,Android实例]通话接通后震动提示 (转载)相关推荐

  1. android 通话的log分析,Android Telephony 接电话流程分析

    写在前面的话 本文主要分析Android 接电话的流程,研究的代码是Android 4.4的,现在我们只关注framework层,以CDMA为例,GSM同理. 如果图片看不清的话,可以右键选择在新标签 ...

  2. Android开机阶段log分析

    Android开机阶段log分析 标签(空格分隔): 开关机流程 Android开机阶段log分析 bootchart工具查看开机过程 打印开机过程各阶段的时间 kernel Init进程 Zygot ...

  3. Android ANR bugreport log分析

    最近工作中频繁遇到设备ANR问题,而且是概率性的那种,于是决定花点时间找找规律复现分析下 说道这里,抓日志是问题解决的最有效途径,这里不得不说一下 bugreport log,其实网上关于它的分析方法 ...

  4. android布局时长分析,Android性能优化:布局优化 详细解析(含、、讲解 )

    前言 在 Android开发中,性能优化策略十分重要 本文主要讲解性能优化中的布局优化,希望你们会喜欢. 目录 1. 影响的性能 布局性能的好坏 主要影响 :Android应用中的页面显示速度 2. ...

  5. android asynctask源码分析,Android通过Handler与AsyncTask两种方式动态更新ListView(附源码)...

    本文实例讲述了Android通过Handler与AsyncTask两种方式动态更新ListView的方法.分享给大家供大家参考,具体如下: 有时候我们需要修改已经生成的列表,添加或者修改数据,noti ...

  6. android 浏览器源码分析,android webview 简单浏览器实现代码

    文件main.java package com.HHBrowser.android; import android.app.Activity; import android.os.Bundle; im ...

  7. android launcher3源码分析,Android Launcher3源码分析与修改

    Launcher和Setting是客户需求经常改动的地方,不过其代码量也不容小觑.今天就初略来看一下,以下内容都是本人查阅资料加上自己的理解得出,由于自己水平有限,如果误导还请指出: 先从Androi ...

  8. android书籍推荐!分析Android未来几年的发展前景,灵魂拷问

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xFWphp75-1615366380707)(//upload-images.jianshu.io/upload_ima ...

  9. android tcpdump log分析,android 系统启动过程中加入tcpdump和logcat

    一.android 系统启动过程中加入tcpdump ,分析开机启动后,系统与服务器端的消息交互. 1. init.rc 中的修改 1)在init.rc 中加上tcpdump service. ser ...

最新文章

  1. rar 文件头crc版本_php实现rar文件的读取和解压
  2. P2197 【模板】nim游戏
  3. mysql binlog日志查看及解码
  4. JSK-10926 各位数字之和的和【入门】
  5. JS中的事件委托/事件代理详解
  6. Oracle中文乱码(中文变问号?)解决方法---简单粗暴高效
  7. QT图形显示和处理6
  8. colorbox iframe小记
  9. Windows设置程序开机自启动
  10. 计算机word文档无法工作,win10所有word文档都打不开如何解决_win10电脑所有word文档无法打开解决教程...
  11. C语言 运算符优先级表
  12. Federated Graph Neural Networks
  13. Mysql如何添加环境变量(详细教程)
  14. 记录一次H3C交换机的配置
  15. 2018-12-16【训练日记】
  16. 树莓派4B使用VNC连接之大无语事件
  17. 海川QK1209 低压按键台灯充电 LED 驱动 IC- 昱灿电子
  18. SpringBoot微信公众号服务器配置案例
  19. Android Camera 架构
  20. rfid资产管理系统的优势

热门文章

  1. 北斗GPS天线使用中注意的问题
  2. 数据库MySQL-多表查询
  3. 分数混合运算简便方法_分数混合运算和简便计算
  4. 西北乱跑娃 --- python图像基本操作
  5. python爬虫基础学习
  6. 7-1 古埃及探秘-金字塔 (10分)
  7. 主控开发(一)Jetson nano环境搭建
  8. oracle bulk select,批量查询 Oracle的bulk collect用法
  9. dialogue怎么读_dialogue是什么意思_dialogue怎么读_dialogue翻译_用法_发音_词组_同反义词_对话-新东方在线英语词典...
  10. 成都睿铂|超详细三维模型单体化技术流程与标准