Android 实现手机接通电话后振动提示的功能

有些手机在电话接通后会有振动提示,这有个好处就是可以等到接通后再放到耳边接听,减少辐射。本文就讲讲如何在Android手机中实现这种接通电话后的振动提示功能,这里主要针对拨出的电话。

     Android SDK提供的通话状态

很明显,要在电话接通的时候产生振动提示,首先需要知道电话在何时被接通。而Android SDK并没有给出直接读取这种状态的方法。下面是Android SDK的电话服务类TelephonyManager提供的三种电话状态:

CALL_STATE_IDLE         空闲状态

CALL_STATE_OFFHOOK 摘机状态

CALL_STATE_RINGING   响铃状态

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

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

       Android运行log分析

还好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 = new InputStreamReader(
     inputstream);
   bufferedreader = new BufferedReader(inputstreamreader);
 String str = "";
while ((str = bufferedreader.readLine()) != null) {
  log.i("mLogcat",str);
}
} catch (Exception e) { 

  } 

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

XML/HTML代码

<uses-permission android:name="android.permission.READ_LOGS"></uses-permission>

通过上面这段代码我们就可以将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 这样的信息来判断了。

我们只能通过一些逻辑上的判断来实现了。

  实例代码讲解

下面看我的代码:

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 开发的朋友,谢谢大家对本站的支持!

(0)

相关推荐

  • Android 实现电话来去自动录音的功能

    我们在使用Android手机打电话时,有时可能会需要对来去电通话自动录音,本文就详细讲解实现Android来去电通话自动录音的方法,大家按照文中的方法编写程序就可以完成此功能. 来去电自动录音的关键在于如何监听手机电话状态的转变: 1)来电的状态的转换如下(红色标记是我们要用到的状态) 空闲(IDEL)--> 响铃(RINGING)--> 接听(ACTIVE)--> 挂断(经历DISCONNECTING--DISCONNECTED)--> 空闲(IDEL) 或者  空闲(IDEL)

  • Android监听手机电话状态与发送邮件通知来电号码的方法(基于PhoneStateListene实现)

    本文实例讲述了Android监听手机电话状态与发送邮件通知来电号码的方法.分享给大家供大家参考,具体如下: 在android中可以用PhoneStateListener来聆听手机电话状态(比如待机.通话中.响铃等).本例是通过它来监听手机电话状态,当手机来电时,通过邮件将来电号码发送到用户邮箱的例子.具体程序如下: import android.app.Activity; import android.content.Intent; import android.os.Bundle; impor

  • Android 实现电话拦截及拦截提示音功能的开发

    本文所讲的内容是在Android系统中如何写程序进行电话拦截,并发出拦截提示音提醒用户,可以说此功能还是比较实用的.        1.电话拦截 这个功能大家可能都知道了,就是利用反射原理调用ITelephony的隐藏方法来实现.        2.拦截后提示忙音/空号/已关机/已停机 这个功能其实是要用到MMI指令,具体如何设置呼叫转移的指定可以参考这里 http://baike.baidu.com/view/206402.html?fromTaglist. 在本文中我们会用到"遇忙转移&qu

  • Android广播接实现监听电话状态(电话的状态,拦截)

    首先我们来理解下监听器的机制. Android的事件处理机制有两种:监听和回调. A基于监听的事件处理 主要涉及三类对象:EventSource(事件源),Event(事件),EventListener(事件监听器) 监听机制处理事件的流程图如下(委派式:Delegation): 1:需要在AndroidManifest.xml清单中添加权限 <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS&q

  • Android拨打电话功能实例详解

    本文实例分析了Android拨打电话功能.分享给大家供大家参考,具体如下: 打电话是手机的一个最基本的功能,现在android智能手机非常流行,里面有多种多样的精彩的手机功能,但是android手机如何实现打电话这个基本功能呢?现以实例说明如下.首先呈上程序: import java.util.regex.Matcher; import java.util.regex.Pattern; import android.app.Activity; import android.content.Int

  • Android 实现手机拨打电话的功能

    一部手机最常用的功能就是打电话和发短信了,在Android开发中我们如何通过程序拨打电话呢?本文就给出一个用Android手机拨打电话的简单的实例. 下面是开发此实例的具体步骤: 一.新建一个Android工程,命名为phoneCallDemo. 二.设计程序的界面,打开main.xml把内容修改如下: XML/HTML代码 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:and

  • Android6.0来电号码与电话薄联系人进行匹配

    本文将介绍系统接收到来电之后,如何在电话薄中进行匹配联系人的流程.分析将从另外一篇文章(基于Android6.0的RIL框架层模块分析)中提到的与本文内容相关的代码开始. //packages/service/***/Call.java public void handleCreateConnectionSuccess( CallIdMapper idMapper, ParcelableConnection connection) { setHandle(connection.getHandle

  • Android编程实现从字符串中查找电话号码的方法

    本文实例讲述了Android编程实现从字符串中查找电话号码的方法.分享给大家供大家参考,具体如下: /** * 从字符串中查找数字字符串 */ private List<String> getNumbers(String content) { List<String> digitList = new ArrayList<String>(); Pattern p = Pattern.compile("(\\d+)"); Matcher m = p.ma

  • Android中简单的电话管理与短信管理App编写实例

    android电话管理器(TelephonyManger)实例: TelephonyManger是管理电话状态.网络信息的服务类. 添加权限: <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 逻辑功能:

  • Android 实现手机接通电话后振动提示的功能

    有些手机在电话接通后会有振动提示,这有个好处就是可以等到接通后再放到耳边接听,减少辐射.本文就讲讲如何在Android手机中实现这种接通电话后的振动提示功能,这里主要针对拨出的电话.      Android SDK提供的通话状态 很明显,要在电话接通的时候产生振动提示,首先需要知道电话在何时被接通.而Android SDK并没有给出直接读取这种状态的方法.下面是Android SDK的电话服务类TelephonyManager提供的三种电话状态: CALL_STATE_IDLE        

  • Android判断手机是否联网及自动跳转功能(收藏版)

    android欢迎页自动跳转及手机网络检测,具体实现代码如下所示: 在1.2s后从欢迎页(welcome)跳转到登陆页(Login_Activity),并进行手机网络检测 package com.example.amusic.welcome; import android.content.Intent; import android.content.IntentFilter; import android.support.v7.app.AppCompatActivity; import andr

  • Android 实现银联刷卡机消费后手动签名的功能(示例代码)

    几天前去物管交物业费,物管工作人员说小区引进高新产品,使用银行卡消费后,不需要拿笔在银联机上签名,直接用手指触摸实现消费签名,当时心想,果然是高科技,机子外形如下左图,签名如下右图. 仔细一看,其实就是一个触摸屏,用户在上面直接手动签名,实现这个功能其实并不复杂,我们自定义一个控件,继承view,使用 Canvas的drawLine,drawPoint这两个方法来实现这个功能. 首先自定义控件 MDrawLineView package com.view; import android.cont

  • Android实现手机振动设置的方法

    本文实例讲述了Android实现手机振动设置的方法.分享给大家供大家参考.具体如下: main.xml布局文件: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" androi

  • 解决android有的手机拍照后上传图片被旋转的问题

    需求:做仿新浪发微博的项目,能够上传图片还有两外一个项目用到手机拍摄图片,这两个都需要把图片上传到服务器 遇到问题:有的手机拍摄的图片旋转90度,有的图片旋转了180度,有的手机是正常的,服务器要求的是正的,这样问题就来了,不能用户发个照片在微博上看到的是被旋转了的啊,另外一个项目里旋转了的图片直接匹配出现问题,这个更严重. 解决:开始的时候在网上没有找到很好的解决办法,谷歌百度的搜了一通,想到第一种解决方式,当手机拍照结束,在返回结果处理里面立即跳转到一个新的页面,在新的页面里让用户自己手动去

  • Android 录制手机屏幕视频生成GIF图片实例详解

    Android 录制手机屏幕视频生成GIF图片实例详解 无图无真相,在我们日常的网络交流中往往需要给交流对象提供直观的显示,而视频是一个很好的方式,但是视频需要播放器,还需要当做文件进行对点传输,并不是很方便.想CSDN这样的博客网站也并不支持在博客里放视频这种方式,除非你贴外链,太烦了不是么.最好是如下图这种gif方式,直观 今天来教大家一个易操作的录制方式.当然,一般只适合Android开发者.因为你需要有AndroidStudio 工具 AndroidStudio(完成手机屏幕的视频录制,

  • Android应用开发:电话监听和录音代码示例

    在oncreate 中执行: 复制代码 代码如下: public void onCreate() {  super.onCreate();  Log.i("TAG", "服务启动了"); // 对电话的来电状态进行监听  TelephonyManager telManager = (TelephonyManager) this    .getSystemService(Context.TELEPHONY_SERVICE);  // 注册一个监听器对电话状态进行监听 

  • Android开发实现的电话窃听和拦截应用

    本文实例讲述了Android开发实现的电话窃听和拦截应用.分享给大家供大家参考,具体如下: 今天学习了进程间Service的通信-->AIDL,基于前几天学习的广播机制,我做了一个简单的电话窃听和录音应用.现将具体实现方法附在下面,供大家参考,希望大家提供一些宝贵的意见. 业务需求分析: 1.当手机处于开机状态,监听服务就要启动,对来电进行监听录音. 2.设置电话黑名单,当来电是黑名单电话,则直接挂断. 实现步骤: 首先我们要定义一个电话监听的服务,对来电进行监听录音和拦截.具体代码如下: Ph

随机推荐