国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 系統(tǒng) > Android > 正文

Android 實(shí)現(xiàn)手機(jī)接通電話后振動(dòng)提示的功能

2019-12-12 05:43:22
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

有些手機(jī)在電話接通后會(huì)有振動(dòng)提示,這有個(gè)好處就是可以等到接通后再放到耳邊接聽(tīng),減少輻射。本文就講講如何在Android手機(jī)中實(shí)現(xiàn)這種接通電話后的振動(dòng)提示功能,這里主要針對(duì)撥出的電話。

       Android SDK提供的通話狀態(tài)

       很明顯,要在電話接通的時(shí)候產(chǎn)生振動(dòng)提示,首先需要知道電話在何時(shí)被接通。而Android SDK并沒(méi)有給出直接讀取這種狀態(tài)的方法。下面是Android SDK的電話服務(wù)類TelephonyManager提供的三種電話狀態(tài):

       CALL_STATE_IDLE         空閑狀態(tài)

       CALL_STATE_OFFHOOK 摘機(jī)狀態(tài)

       CALL_STATE_RINGING   響鈴狀態(tài)

       這幾個(gè)狀態(tài)很容易理解:摘機(jī)狀態(tài)即拿起話筒(對(duì)于座機(jī)電話而言的動(dòng)作),但這個(gè)狀態(tài)可能發(fā)生在撥入電話接通時(shí),也可能是撥出電話時(shí),但是卻不能說(shuō)明撥出電話接通時(shí)。通過(guò)以上3種狀態(tài)我們僅能組合出掛機(jī)和來(lái)電接通這兩個(gè)狀態(tài)。而今天我們要實(shí)現(xiàn)的功能卻無(wú)法做到。

       看來(lái)我們需要尋找其他方法來(lái)實(shí)現(xiàn)了,SDK靠不住啊……

       Android運(yùn)行l(wèi)og分析

       還好Android在運(yùn)行時(shí)會(huì)有大量的log產(chǎn)生,看看我們能不能從這上面找到突波口呢?我們選擇Android的Radio模塊的日志來(lái)分析。首先我們需要寫(xiě)一段代碼來(lái)讀取Radio相關(guān)的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) {       } 

另外,要讓程序能夠讀取系統(tǒng)log需要指定權(quán)限,在AndroidManifest.xml文件中加入一下內(nèi)容。

XML/HTML代碼

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

       通過(guò)上面這段代碼我們就可以將Radio的log輸出到了,這樣我們就可以通過(guò)在DDMS中查看這些log,分析其中的通話過(guò)程。具體抓到的log就不貼出來(lái)了,大家可以自己編寫(xiě)程序通過(guò)上面的代碼來(lái)抓取和分析。我只說(shuō)一下我的分析結(jié)果。

       通過(guò)分析log發(fā)現(xiàn)了一些蛛絲馬跡。其中有幾條日志很有用:

       GET_CURRENT_CALLS  id=1,DIALING

       GET_CURRENT_CALLS  id=1,ALERTING

       GET_CURRENT_CALLS  id=1,ACTIVE

       由于log較長(zhǎng)我只拿了每條log的開(kāi)頭部分,真實(shí)的會(huì)多很多內(nèi)容。當(dāng)我們撥出電話的時(shí)候,會(huì)輸入這么幾條log。

       撥號(hào)->提醒->活動(dòng)

       大致是這么個(gè)過(guò)程。經(jīng)過(guò)幾次測(cè)試發(fā)現(xiàn),電話接通時(shí)會(huì)進(jìn)入活動(dòng)狀態(tài),并會(huì)輸出:GET_CURRENT_CALLS  id=1,ACTIVE  這條log,至此我們已經(jīng)接近成功了。

       不過(guò)之后我又發(fā)現(xiàn)在撥號(hào)開(kāi)始到電話接通這段時(shí)間內(nèi)會(huì)經(jīng)過(guò)多次的“撥號(hào)->提醒->活動(dòng)”這樣的狀態(tài)變化,僅當(dāng)話筒中嘟聲響起后GET_CURRENT_CALLS這條日志會(huì)鎖定在ALERTING。在電話接通前便不再出現(xiàn)GET_CURRENT_CALLS日志了。

       可能上面的這段表述大家不是很清楚,換句話說(shuō)在通話接通之前會(huì)出現(xiàn)多次的GET_CURRENT_CALLS ACTIVE 這樣的日志,而僅有一次是電話接通產(chǎn)生的。這就給我們?cè)斐闪寺闊2荒苤皇菃渭兊淖トET_CURRENT_CALLS ACTIVE 這樣的信息來(lái)判斷了。

       我們只能通過(guò)一些邏輯上的判斷來(lái)實(shí)現(xiàn)了。

       實(shí)例代碼講解

       下面看我的代碼:

class TestThread implements Runnable {  //振動(dòng)器  Vibrator mVibrator;  //電話服務(wù)  TelephonyManager telManager;  public TestThread(Vibrator mVibrator, TelephonyManager telManager) {   this.mVibrator = mVibrator;   this.telManager = telManager;  }  @Override  public void run() {   //獲取當(dāng)前話機(jī)狀態(tài)   int callState = telManager.getCallState();   Log.i("TestService", "開(kāi)始.........." + Thread.currentThread().getName());   //記錄撥號(hào)開(kāi)始時(shí)間   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) {     //如果話機(jī)狀態(tài)從摘機(jī)變?yōu)榭臻e,銷毀線程     if (callState == TelephonyManager.CALL_STATE_OFFHOOK       && telManager.getCallState() == TelephonyManager.CALL_STATE_IDLE) {      break;     }     // 線程運(yùn)行5分鐘自動(dòng)銷毀     if (System.currentTimeMillis() - threadStart > 300000) {      break;     }     Log.i("TestService", Thread.currentThread().getName() + ":"       + str);     // 記錄GSM狀態(tài)DIALING     if (str.contains("GET_CURRENT_CALLS")       && str.contains("DIALING")) {      // 當(dāng)DIALING開(kāi)始并且已經(jīng)經(jīng)過(guò)ALERTING或者首次DIALING      if (!isAlert || dialingStart == 0) {       //記錄DIALING狀態(tài)產(chǎn)生時(shí)間       dialingStart = System.currentTimeMillis();       isAlert = false;      }      continue;     }     if (str.contains("GET_CURRENT_CALLS")       && str.contains("ALERTING")&&!enableVibrator) {            long temp = System.currentTimeMillis() - dialingStart;      isAlert = true;      //這個(gè)是關(guān)鍵,當(dāng)?shù)谝淮蜠IALING狀態(tài)的時(shí)間,與當(dāng)前的ALERTING間隔時(shí)間在1.5秒以上并且在20秒以內(nèi)的話      //那么認(rèn)為下次的ACTIVE狀態(tài)為通話接通.      if (temp > 1500 && temp < 20000) {       enableVibrator = true;       Log.i("TestService", "間隔時(shí)間....." + temp + "....."         + Thread.currentThread().getName());      }      continue;     }     if (str.contains("GET_CURRENT_CALLS") && str.contains("ACTIVE")       && enableVibrator) {      mVibrator.vibrate(100);      enableVibrator = false;      break;     }    }    Log.i("TestService", "結(jié)束.........."      + Thread.currentThread().getName());   } catch (Exception e) {    // TODO: handle exception   }  } } 

      我的這個(gè)方法比較牽強(qiáng),是通過(guò)判斷第一次DIALING與每一次ALERTING之間的間隔,如果間隔大于1.5秒,那么認(rèn)為已經(jīng)進(jìn)入了“嘟”聲提示的時(shí)候了,那么下一個(gè)ACTIVE將是電話接通。這個(gè)1.5秒是通過(guò)分析日志得出的。但是這種方法我始終覺(jué)得不太靠譜。如果大家有好的方法可以交流交流。

       剩下的就是讓這個(gè)線程在電話撥出時(shí)觸發(fā),并且常駐在電話中時(shí)候準(zhǔn)備這就可以了。可以采用Service配合Receiver來(lái)實(shí)現(xiàn)。Service來(lái)實(shí)現(xiàn)常駐,Receiver來(lái)實(shí)現(xiàn)監(jiān)聽(tīng)撥出電話?;揪涂梢酝瓿晌覀兿胍墓δ芰?。

        以上代碼我都測(cè)試過(guò),99%有效,哈哈。這里面提到了一些Android的基礎(chǔ)內(nèi)容,像logcat、Service、Receiver,這些如果大家不了解的話可以找相關(guān)文章資料學(xué)習(xí)下。

        通過(guò)此文希望能幫助Android 開(kāi)發(fā)的朋友,謝謝大家對(duì)本站的支持!

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 梁河县| 京山县| 双鸭山市| 鲜城| 射阳县| 高阳县| 卓尼县| 汨罗市| 韶关市| 股票| 建瓯市| 连南| 合水县| 天津市| 山西省| 达日县| 西和县| 霍山县| 灵石县| 益阳市| 南城县| 资源县| 凤台县| 临洮县| 家居| 南乐县| 阿鲁科尔沁旗| 乐业县| 伊川县| 临漳县| 松江区| 宣恩县| 长葛市| 新民市| 昌吉市| 林周县| 濮阳县| 湖南省| 岫岩| 南京市| 肇东市|