Android語音開發(fā)-聽筒揚聲器自動切換

業(yè)務描述

公司項目是做IM即時通訊的蚣抗,在項目開發(fā)的過程中遇到這樣一個需求:語音播放的場景下侈百,當手機靠近面部時,顯示屏熄滅翰铡,語音播放自動切換為聽筒模式钝域,當手機遠離面部時,語音播放切換為揚聲器模式锭魔。

實現(xiàn)思考

其實原理很簡單例证,android手機一般都有距離感應裝置,根據(jù)距離感應裝置的相應回調(diào)參數(shù)去做聽筒迷捧,揚聲器织咧,和屏幕點亮熄滅的操作。但是在開發(fā)中還是遇到了很多坑漠秋,下面會一一陳述烦感。

代碼開發(fā)

屏幕喚醒鎖(WakeLock)

先說說這個WakeLock

powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, this.getClass().getName());

可以看出WakeLock是PowerManager的一個內(nèi)部類。先說newWakeLock(int levelAndFlags, String tag)這個方法膛堤,改方法創(chuàng)建一個新的喚醒鎖手趣,需要兩個參數(shù),levelAndFlags是喚醒鎖的類型,第二個參數(shù)tag就是WakeLock的一個tag绿渣。

在一個頁面中可以有一個或者多個WakeLock,只要有一個WakeLock持有著屏幕朝群,則屏幕不會熄滅

在newWakeLoke方法中我傳入了PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK參數(shù),關(guān)于該參數(shù)的描述

Wake lock level: Turns the screen off when the proximity sensor activates.
* If the proximity sensor detects that an object is nearby, the screen turns off
* immediately. Shortly after the object moves away, the screen turns on again.

簡單就是說中符,當距離傳感器感應到距離接近時就會關(guān)閉屏幕姜胖,當遠離時就會關(guān)閉屏幕。
屏幕點亮調(diào)用 wakeLock.acquire();
屏幕熄滅調(diào)用 wakeLock.release();
這里還有一個方法

wakeLock.setReferenceCounted(false); // 設(shè)置不啟用引用計數(shù)

屏幕鎖有一個機制淀散,在設(shè)置引用計數(shù)的情況下(wakeLock.setReferenceCounted(true)其實系統(tǒng)默認的就是true),這時候wakeLock.acquire()和wakeLock.release()是需要成對出現(xiàn)的右莱,也就是說兩個方法的調(diào)用次數(shù)要相同,否則wakeLock就不能釋放档插,影響正常的操作慢蜓。如果wakeLock.setReferenceCounted(false),則不啟用引用計數(shù)郭膛,無論你調(diào)用了多少次wakeLock.acquire()晨抡,只需要一個wakeLock.release()就可以釋放屏幕鎖。

這里貼一下acquire()则剃,release()的代碼

public void acquire() {
    synchronized (mToken) {
        acquireLocked();
    }
}
private void acquireLocked() {
        if (!mRefCounted || mCount++ == 0) {
                         mHandler.removeCallbacks(mReleaser);
            Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);
            try {
                mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource,
                        mHistoryTag);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
        }
        mHeld = true;
    }
}

acquire()方法中調(diào)用了acquireLocked()耘柱,在acquireLocked()中,有一個判斷條件(!mRefCounted || mCount++ == 0)棍现。

  1. mRefCounted為false時才會調(diào)用屏幕管理進程去點亮屏幕调煎,在不做任何設(shè)置的情況下,默認該值是true的己肮。也就是主要看下一個判斷條件
  2. mCount++ == 0 為true時才能調(diào)用到屏幕管理進程點亮屏幕

在看release()的源碼

 public void release(int flags) {
    synchronized (mToken) {
        if (!mRefCounted || --mCount == 0) {
            mHandler.removeCallbacks(mReleaser);
            if (mHeld) {
                Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, mTraceName, 0);
                try {
                    mService.releaseWakeLock(mToken, flags);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
                mHeld = false;
            }
        }
        if (mCount < 0) {
            throw new RuntimeException("WakeLock under-locked " + mTag);
        }
    }
}

同acquire的判斷條件相同士袄,是否設(shè)置了引用計數(shù),在設(shè)置了的情況下朴肺,點亮屏幕的操作與熄滅屏幕的操作次數(shù)是否相等窖剑。
到此坚洽,屏幕鎖的使用及原理就說完了
下面直接看距離感應的相關(guān)代碼

sensorManager.registerListener(new SensorEventListener() {
                @Override
                public void onSensorChanged(SensorEvent event) {
                    float[] dis = event.values;
                    if (0.0f == dis[0]){ // 靠近身體
                        wakeLock.release(); // 熄滅屏幕
                        switchToEarpiece(); // 切換到聽筒
                    }else {
                        wakeLock.acquire(); // 點亮屏幕
                        switchToSpeaker(); // 切換到揚聲器
                    }
                }

                @Override
                public void onAccuracyChanged(Sensor sensor, int accuracy) {

                }
            },sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY),SensorManager.SENSOR_DELAY_NORMAL);

sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY 是獲取一個距離傳感器類型戈稿,SensorManager.SENSOR_DELAY_NORMAL 是一個傳感器靈敏度的參數(shù),選擇普通靈敏度讶舰。

至此鞍盗,根據(jù)距離傳感器實現(xiàn)語音切換,屏幕點亮熄滅功能的基本實現(xiàn)都已講完(主干實現(xiàn))跳昼。在開發(fā)過程中還是遇到了不少的坑的般甲。這里說幾點開發(fā)中需要注意的問題:

  1. 使用wakelock.release()熄滅屏幕并不會走Activity的生命周期(本人親測),所以不要指望在屏幕熄滅的時候在生命周期回調(diào)中做一些工作鹅颊,但是點bakc鍵還是會正常的回調(diào)生命周期敷存。
  2. 記得在activity的生命周期中unregisterListener,解注冊掉感應器。
  3. 如果沒解注冊掉感應器锚烦,或者wakelock沒有合理的使用(任何一著)都會導致你回退到上個界面觅闽,或者切到桌面,wakelock和感應鎖依然正常工作涮俄,影響其他功能的正常使用蛉拙,我就是在wakelock的使用上耽誤了一天。

結(jié)尾貼一下聽筒揚聲器切換的代碼

if (!speakerphoneOn){
            mAudioManager.setSpeakerphoneOn(false);
            mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
        }else {
            mAudioManager.setMode(AudioManager.MODE_NORMAL);
            mAudioManager.setSpeakerphoneOn(true);
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
}

(完)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末彻亲,一起剝皮案震驚了整個濱河市孕锄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌苞尝,老刑警劉巖畸肆,帶你破解...
    沈念sama閱讀 207,248評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異野来,居然都是意外死亡恼除,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,681評論 2 381
  • 文/潘曉璐 我一進店門曼氛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來豁辉,“玉大人,你說我怎么就攤上這事舀患』占叮” “怎么了?”我有些...
    開封第一講書人閱讀 153,443評論 0 344
  • 文/不壞的土叔 我叫張陵聊浅,是天一觀的道長餐抢。 經(jīng)常有香客問我,道長低匙,這世上最難降的妖魔是什么旷痕? 我笑而不...
    開封第一講書人閱讀 55,475評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮顽冶,結(jié)果婚禮上欺抗,老公的妹妹穿的比我還像新娘。我一直安慰自己强重,他們只是感情好绞呈,可當我...
    茶點故事閱讀 64,458評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著间景,像睡著了一般佃声。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上倘要,一...
    開封第一講書人閱讀 49,185評論 1 284
  • 那天圾亏,我揣著相機與錄音,去河邊找鬼。 笑死志鹃,一個胖子當著我的面吹牛父晶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播弄跌,決...
    沈念sama閱讀 38,451評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼甲喝,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了铛只?” 一聲冷哼從身側(cè)響起埠胖,我...
    開封第一講書人閱讀 37,112評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎淳玩,沒想到半個月后直撤,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,609評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡蜕着,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,083評論 2 325
  • 正文 我和宋清朗相戀三年谋竖,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片承匣。...
    茶點故事閱讀 38,163評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡蓖乘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出韧骗,到底是詐尸還是另有隱情嘉抒,我是刑警寧澤,帶...
    沈念sama閱讀 33,803評論 4 323
  • 正文 年R本政府宣布袍暴,位于F島的核電站些侍,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏政模。R本人自食惡果不足惜岗宣,卻給世界環(huán)境...
    茶點故事閱讀 39,357評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望淋样。 院中可真熱鬧耗式,春花似錦、人聲如沸习蓬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,357評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽躲叼。三九已至,卻和暖如春企巢,著一層夾襖步出監(jiān)牢的瞬間枫慷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,590評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留或听,地道東北人探孝。 一個月前我還...
    沈念sama閱讀 45,636評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像誉裆,于是被迫代替她去往敵國和親顿颅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,925評論 2 344

推薦閱讀更多精彩內(nèi)容