Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發實例 >> Android手機接通電話後振動提示的實例

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了。

Java代碼
  1.     Process process;   
  2.         InputStream inputstream;   
  3.         BufferedReader bufferedreader;   
  4.         try {   
  5.             process = Runtime.getRuntime().exec("logcat -v time -b radio");   
  6.             inputstream = process.getInputStream();   
  7.             InputStreamReader inputstreamreader = new InputStreamReader(   
  8.                     inputstream);   
  9.             bufferedreader = new BufferedReader(inputstreamreader);   
  10.     String str = "";   
  11. while ((str = bufferedreader.readLine()) != null) {   
  12.        log.i("mLogcat",str);   
  13. }   
  14. } catch (Exception e) {   
  15.                
  16.         }  

       另外,要讓程序能夠讀取系統log需要指定權限,在AndroidManifest.xml文件中加入一下內容。

XML/HTML代碼
  1. <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 這樣的信息來判斷了。

       我們只能通過一些邏輯上的判斷來實現了。

       實例代碼講解

       下面看我的代碼:

Java代碼
  1. class TestThread implements Runnable {   
  2.     //振動器   
  3.     Vibrator mVibrator;   
  4.     //電話服務   
  5.     TelephonyManager telManager;   
  6.     public TestThread(Vibrator mVibrator, TelephonyManager telManager) {   
  7.         this.mVibrator = mVibrator;   
  8.         this.telManager = telManager;   
  9.     }   
  10.     @Override  
  11.     public void run() {   
  12.         //獲取當前話機狀態   
  13.         int callState = telManager.getCallState();   
  14.         Log.i("TestService", "開始.........." + Thread.currentThread().getName());   
  15.         //記錄撥號開始時間   
  16.         long threadStart = System.currentTimeMillis();   
  17.         Process process;   
  18.         InputStream inputstream;   
  19.         BufferedReader bufferedreader;   
  20.         try {   
  21.             process = Runtime.getRuntime().exec("logcat -v time -b radio");   
  22.             inputstream = process.getInputStream();   
  23.             InputStreamReader inputstreamreader = new InputStreamReader(   
  24.                     inputstream);   
  25.             bufferedreader = new BufferedReader(inputstreamreader);   
  26.             String str = "";   
  27.             long dialingStart = 0;   
  28.             boolean enableVibrator = false;   
  29.             boolean isAlert = false;   
  30.             while ((str = bufferedreader.readLine()) != null) {   
  31.                 //如果話機狀態從摘機變為空閒,銷毀線程   
  32.                 if (callState == TelephonyManager.CALL_STATE_OFFHOOK   
  33.                         && telManager.getCallState() == TelephonyManager.CALL_STATE_IDLE) {   
  34.                     break;   
  35.                 }   
  36.                 // 線程運行5分鐘自動銷毀   
  37.                 if (System.currentTimeMillis() - threadStart > 300000) {   
  38.                     break;   
  39.                 }   
  40.                 Log.i("TestService", Thread.currentThread().getName() + ":"  
  41.                         + str);   
  42.                 // 記錄GSM狀態DIALING   
  43.                 if (str.contains("GET_CURRENT_CALLS")   
  44.                         && str.contains("DIALING")) {   
  45.                     // 當DIALING開始並且已經經過ALERTING或者首次DIALING   
  46.                     if (!isAlert || dialingStart == 0) {   
  47.                         //記錄DIALING狀態產生時間   
  48.                         dialingStart = System.currentTimeMillis();   
  49.                         isAlert = false;   
  50.                     }   
  51.                     continue;   
  52.                 }   
  53.                 if (str.contains("GET_CURRENT_CALLS")   
  54.                         && str.contains("ALERTING")&&!enableVibrator) {   
  55.                        
  56.                     long temp = System.currentTimeMillis() - dialingStart;   
  57.                     isAlert = true;   
  58.                     //這個是關鍵,當第一次DIALING狀態的時間,與當前的ALERTING間隔時間在1.5秒以上並且在20秒以內的話   
  59.                     //那麼認為下次的ACTIVE狀態為通話接通.   
  60.                     if (temp > 1500 && temp < 20000) {   
  61.                         enableVibrator = true;   
  62.                         Log.i("TestService", "間隔時間....." + temp + "....."  
  63.                                 + Thread.currentThread().getName());   
  64.                     }   
  65.                     continue;   
  66.                 }   
  67.                 if (str.contains("GET_CURRENT_CALLS") && str.contains("ACTIVE")   
  68.                         && enableVibrator) {   
  69.                     mVibrator.vibrate(100);   
  70.                     enableVibrator = false;   
  71.                     break;   
  72.                 }   
  73.             }   
  74.             Log.i("TestService", "結束.........."  
  75.                     + Thread.currentThread().getName());   
  76.         } catch (Exception e) {   
  77.             // TODO: handle exception   
  78.         }   
  79.     }   
  80. }  

       我的這個方法比較牽強,是通過判斷第一次DIALING與每一次ALERTING之間的間隔,如果間隔大於1.5秒,那麼認為已經進入了“嘟”聲提示的時候了,那麼下一個ACTIVE將是電話接通。這個1.5秒是通過分析日志得出的。但是這種方法我始終覺得不太靠譜。如果大家有好的方法可以交流交流。

       剩下的就是讓這個線程在電話撥出時觸發,並且常駐在電話中時候准備這就可以了。可以采用Service配合Receiver來實現。Service來實現常駐,Receiver來實現監聽撥出電話。基本就可以完成我們想要的功能了。

        以上代碼我都測試過,99%有效,哈哈。這裡面提到了一些Android的基礎內容,像logcat、Service、Receiver,這些如果大家不了解的話可以找相關文章資料學習下。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved