Android 实现手机接通电话后振动提示的功能_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 开发的朋友,谢谢大家对本站的支持!

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索android
, 电话振动提示
电话振动
android搜索功能实现、android 登陆功能实现、android收藏功能实现、android签到功能实现、android定位功能实现,以便于您获取更多的相关知识。

时间: 2024-08-03 09:55:44

Android 实现手机接通电话后振动提示的功能_Android的相关文章

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

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

Android静默安装实现方案 仿360手机助手秒装和智能安装功能_Android

之前有很多朋友都问过我,在Android系统中怎样才能实现静默安装呢?所谓的静默安装,就是不用弹出系统的安装界面,在不影响用户任何操作的情况下不知不觉地将程序装好.虽说这种方式看上去不打搅用户,但是却存在着一个问题,因为Android系统会在安装界面当中把程序所声明的权限展示给用户看,用户来评估一下这些权限然后决定是否要安装该程序,但如果使用了静默安装的方式,也就没有地方让用户看权限了,相当于用户被动接受了这些权限.在Android官方看来,这显示是一种非常危险的行为,因此静默安装这一行为系统是

Android检查手机有没有安装某应用的方法_Android

本文实例讲述了Android检查手机有没有安装某应用的方法.分享给大家供大家参考,具体如下: 手机用户尤其厌烦手动输入大量信息,在一个程序中可以调用其他程序或功能往往可以给用户更好的用户体验,让用户倍感亲切,所以程序间这样的整合可以 促成多方软件协同工作的"共赢"局面. 那我们在我们自己的程序中调用其他程序时往往要检查手机有没有安装该软件后再做相应操作,如没有安装,用intent将用户引导至android market去下载该程序,如已安装则打开该程序,并传入参数和调用其功能. 下面介

android bluetooth-Android手机如何使用蓝牙来实现打印功能

问题描述 Android手机如何使用蓝牙来实现打印功能 请问目前android手机是怎样使用蓝牙来实现打印的,打印机厂家会提供sdk吗?还是要遵循什么标准?

Android获取手机SIM卡运营商信息的方法_Android

本文实例讲述了Android获取手机SIM卡运营商信息的方法,对于Android程序设计有非常实用的价值.分享给大家供大家参考之用.具体方法如下: 主要功能代码如下: /** * 获取SIM卡运营商 * * @param context * @return */ public static String getOperators(Context context) { TelephonyManager tm = (TelephonyManager) context .getSystemServic

Android判断手机是否是小米MIUI系统的方法_Android

废话不多说了,直接给大家贴代码了: 具体代码如下所示: public class MIUIUtils { // 检测MIUI private static final String KEY_MIUI_VERSION_CODE = "ro.miui.ui.version.code"; private static final String KEY_MIUI_VERSION_NAME = "ro.miui.ui.version.name"; private static

Android检查手机网络状态及网络类型的方法_Android

本文实例讲述了Android检查手机网络状态及网络类型的方法.分享给大家供大家参考.具体分析如下: //judge network status is connecting or not public static boolean checkNetworkConnected(Context context) { if (null!=context) { ConnectivityManager connectivityManager = (ConnectivityManager) context

Android基于AudioManager、PhoneStateListener实现设置黑名单功能_Android

本文实例讲述了Android基于AudioManager.PhoneStateListener实现设置黑名单功能.分享给大家供大家参考,具体如下: 手机中一般有设置黑名单的功能.此例通过设置电话黑名单,当黑名单中的电话打来时,手机铃声为变成静音. 程序代码如下: import android.app.Activity; import android.content.Context; import android.media.AudioManager; import android.os.Bund

Android自定义View 实现闹钟唤起播放闹钟铃声功能_Android

先上图看一下闹钟唤期页面的效果 实现的功能: 1:转动的图片根据天气情况更换 2:转动时间可以设置,转动结束,闹铃声音就结束 3:光圈颜色渐变效果 直接上代码啦: package com.yuekong.sirius.extension.customview; import android.animation.Animator; import android.animation.ValueAnimator; import android.content.Context; import andro