1. 程式人生 > >Android 監聽系統媒體音量變化

Android 監聽系統媒體音量變化

在做 SAPA 適配時由於其直連驅動層不經過 Android 的音量增益控制,所以調節系統媒體音量對音量改變無效。現要調節系統音量時也可以控制播放的音量,那麼就需要監聽系統音量變化,然後轉換成增益給輸出資料乘以對應比率從而實現對音量的控制。

一般監聽音量多是監聽手機物理音量按鍵的點選事件,但是在音量控制面板拖動音量條改變音量就無法監聽。那麼我們需要分析無論是按音量鍵還是拖動音量條,系統都做了什麼呢?有什麼共性?

從文中可以知道,當音量變化時,系統會發出廣播,所以我們只要監聽音量改變的廣播就可以了,不用關心具體是哪種方式改變的音量。該廣播的 action 為AudioManager.VOLUME_CHANGED_ACTION ,但是該常量被隱藏了,所以直接用 "android.media.VOLUME_CHANGED_ACTION" ,在收到廣播時可以通過 AudioManager的getStreamVolume(AudioManager.STREAM_MUSIC) 方法獲得當前的音量,也可以從廣播中攜帶的資料獲取,我對此做了個封裝。

封裝如下

package com.ushow.sapademo;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import java.lang.ref.WeakReference;

/**
 * Author: Alan Wang.
 * Date: 18/5/29 16:39.
 * Mail: 
[email protected]
*/ public class VolumeChangeObserver {    private static final String VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION";    private static final String EXTRA_VOLUME_STREAM_TYPE = "android.media.EXTRA_VOLUME_STREAM_TYPE";    public interface VolumeChangeListener
{
       /**         * 系統媒體音量變化         * @param volume         */        void onVolumeChanged(int volume);   }    private VolumeChangeListener mVolumeChangeListener;    private VolumeBroadcastReceiver mVolumeBroadcastReceiver;    private Context mContext;    private AudioManager mAudioManager;    private boolean mRegistered = false;    public VolumeChangeObserver(Context context) {        mContext = context;        mAudioManager = (AudioManager) context.getApplicationContext()               .getSystemService(Context.AUDIO_SERVICE);   }    /**     * 獲取當前媒體音量     * @return     */    public int getCurrentMusicVolume() {        return mAudioManager != null ? mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC) : -1;   }    /**     * 獲取系統最大媒體音量     * @return     */    public int getMaxMusicVolume() {        return mAudioManager != null ? mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) : 15;   }    public VolumeChangeListener getVolumeChangeListener() {        return mVolumeChangeListener;   }    public void setVolumeChangeListener(VolumeChangeListener volumeChangeListener) {        this.mVolumeChangeListener = volumeChangeListener;   }    /**     * 註冊音量廣播接收器     * @return     */    public void registerReceiver() {        mVolumeBroadcastReceiver = new VolumeBroadcastReceiver(this);        IntentFilter filter = new IntentFilter();        filter.addAction(VOLUME_CHANGED_ACTION);        mContext.registerReceiver(mVolumeBroadcastReceiver, filter);        mRegistered = true;   }    /**     * 解註冊音量廣播監聽器,需要與 registerReceiver 成對使用     */    public void unregisterReceiver() {        if (mRegistered) {            try {                mContext.unregisterReceiver(mVolumeBroadcastReceiver);                mVolumeChangeListener = null;                mRegistered = false;           } catch (Exception e) {                e.printStackTrace();           }       }   }    private static class VolumeBroadcastReceiver extends BroadcastReceiver {        private WeakReference<VolumeChangeObserver> mObserverWeakReference;        public VolumeBroadcastReceiver(VolumeChangeObserver volumeChangeObserver) {            mObserverWeakReference = new WeakReference<>(volumeChangeObserver);       }        @Override        public void onReceive(Context context, Intent intent) {            //媒體音量改變才通知            if (VOLUME_CHANGED_ACTION.equals(intent.getAction())                    && (intent.getIntExtra(EXTRA_VOLUME_STREAM_TYPE, -1) == AudioManager.STREAM_MUSIC)) {                VolumeChangeObserver observer = mObserverWeakReference.get();                if (observer != null) {                    VolumeChangeListener listener = observer.getVolumeChangeListener();                    if (listener != null) {                        int volume = observer.getCurrentMusicVolume();                        if (volume >= 0) {                            listener.onVolumeChanged(volume);                       }                   }               }           }       }   } }

對外暴露有以下幾個方法:

  • VolumeChangeObserver(Context context):建構函式;

  • VolumeChangeListener:音量改變介面,當媒體音量變化時會呼叫其 onVolumeChanged(int volume) 方法;

  • setVolumeChangeListener(VolumeChangeListener volumeChangeListener):設定音量改變的監聽器;

  • getCurrentMusicVolume():獲取當前媒體音量;

  • registerReceiver():註冊接收器;

  • unregisterReceiver():解註冊接收器

呼叫邏輯如下

package com.ushow.sapademo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

//實現 VolumeChangeListener 介面
public class MainActivity extends AppCompatActivity implements VolumeChangeObserver.VolumeChangeListener {
    private final static String TAG = MainActivity.class.getSimpleName();

    private VolumeChangeObserver mVolumeChangeObserver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //例項化物件並設定監聽器
        mVolumeChangeObserver = new VolumeChangeObserver(this);
        mVolumeChangeObserver.setVolumeChangeListener(this);
        int initVolume = mVolumeChangeObserver.getCurrentMusicVolume();
        Log.e(TAG, "initVolume = " + initVolume);
    }

    @Override
    protected void onResume() {
        //註冊廣播接收器
        mVolumeChangeObserver.registerReceiver();
        super.onResume();
    }

    @Override
    protected void onPause() {
        //解註冊廣播接收器
        mVolumeChangeObserver.unregisterReceiver();
        super.onPause();
    }

    @Override
    public void onVolumeChanged(int volume) {
        //系統媒體音量改變時的回撥
        Log.e(TAG, "onVolumeChanged()--->volume = " + volume);
    }
}

相關推薦

Android 系統媒體音量變化

在做 SAPA 適配時由於其直連驅動層不經過 Android 的音量增益控制,所以調節系統媒體音量對音量改變無效。現要調節系統音量時也可以控制播放的音量,那麼就需要監聽系統音量變化,然後轉換成增益給輸出

Android 系統音樂播放器播放的音樂的方法

  最近在做專案的時候遇到一個小問題,就是需要自己寫一個View來控制系統音樂播放器的播放行為,並且要能得到正在播放的音樂的資訊,可能剛開始是想省點時間,所以就沒有直接去看原始碼,而是上網搜尋了一下,但令我十分驚訝的是網上竟然沒有這個,難道說沒有童鞋做過這個?嘿嘿,啥

Android系統來電,彈出提示視窗

1.問題 專案中有自己企業的通訊錄,但是在應用中撥打公司通訊錄的聯絡人,由於手機通訊錄中沒有相應的資訊,只顯示一串電話號 2 .目的 監聽系統來電,獲取到電話號碼,通過呼叫介面,查詢出來相應電話號碼的詳細資訊,並彈出系統懸浮框,給使用者提示。 3

Android系統廣播 和自定義廣播遇到的問題

現在有一個專案需要做一個開機自啟動的功能,這個怎麼實現呢?一頓咔咔咔百度,發現很多推薦 使用監聽系統開機廣播BOOT_COMPLETED,CONNECTIVITY_CHANGE 來實現。那好吧  我也這麼來做。先寫一個RootReceiver  extends Broadc

[Android] 系統網路連線開啟或者關閉的訊息

很簡單,所以直接看程式碼。 package xxx; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; impo

android 網路狀態的變化+Observer

平時我們在請求錯誤的情況下,通常會進行處理一下,一般來說,主要分為兩方面的錯誤: 1、沒有網路的錯誤 2、在有網路的情況下,我們客戶端的錯誤或者伺服器端的錯誤 今天這篇部落格主要闡述以下問題: 1、怎樣監聽網路狀態的變化,包括是否開啟WiFi,否開啟資料

android 網路狀態的變化及實戰

android 監聽網路狀態的變化及實際應用 本篇文章已授權微信公眾號 guolin_blog (郭霖)獨家釋出 平時我們在請求錯誤的情況下,通常會進行處理一下,一般來說,主要分為兩方面的錯誤 - 沒有網路的錯誤 - 在有網路的情況下,我們客

android 電池電量的變化

package com.example.test; import android.app.Activity; import android.app.Dialog; import android.content.BroadcastReceiver; import andro

廣播小案例-系統網絡狀態 --Android開發

演示 系統網絡 perm new reat inf roi ron str 本例通過廣播實現簡單的監聽系統網絡狀態改變的小案例。 1、案例效果演示 當手機連網後,系統提示“已連接網絡”, 當手機斷網後,系統提示“當前網絡不可

Android使用者開啟系統相機進行錄影行為

首先,新建一個廣播: public class CameraReceiver extends BroadcastReceiver { @Override public void o

android】解決方案--用BroadcastReceiver手機網路狀態變化

實現一個功能,可以有很多種方法,但我們所追求的是最適合於自己專案的那一種方法。 就比如app要判斷網路狀態,如果在每次使用網路的時候去判斷一次網路狀態的話,有些耗費時間。例如,你要在開啟網頁之前先判斷網路是否暢通以及在下載圖片之前判斷網路型別,那麼務必造成等待時間的增加

Android開發動態的網路狀態的變化

主要思路:使用Android中的四大元件之:BrocastReceiver監聽網路狀態的變化。接收到網路狀態改變的廣播之後判斷當前的網路是否可用。 建立廣播接收器MyNetworkReceiver public class MyNetworkRecei

Android——變數的變化

這是對上一篇的補充: 如何合理的監聽程式中一個變數的變化。 有時候,我們在程式中會設定一個變數作為標誌,而程式需要監聽這個標誌,當這個標誌發生改變時,程式做出相應的處理。 主要的程式碼解釋如下: 1、將變數放置在一個類中,在該類中對變數有get 、set方法,並在set方法

Android網路變化並跳轉到WiFi設定

在開啟App進入程式時,一般都會進行網路請求資料,但如果手機沒有聯網怎麼辦?總不能什麼都不顯示吧,然後使用者又連線上網路了,這個時候我們應該繼續網路請求吧,所以我們應該實時的監聽手機的網路. 先簡單說

android網路狀態變化

許可權 uses-permission android:name=”android.permission.ACCESS_NETWORK_STATE” uses-permission android:name=”android.permission.INTER

ng 數據的變化

style 例子 代碼 ctype user src $scope angular round $scope.$watch(‘監聽的變量的名稱‘,func) 在angularJs之所以能夠實現綁定,是因為angularJS框架在背後為每一個模型數據添加了一個監聽,與$w

js 實時input中值變化

對象 不同 round 字符 實時 char div har 但是 摘自:http://blog.csdn.net/spy19881201/article/details/25537225 示例: <!DOCTYPE html> <html>

實時輸入框值變化的完美方案:oninput & onpropertychange

ner 監聽 jpg number ima 方案 radio 技術 search   oninput 是 HTML5 的標準事件,對於檢測 textarea, input:text, input:password 和 input:search 這幾個元素通過用戶界面發生

jquery實時輸入框值變化

property per 並且 details dom 支持 觸發事件 java 不能 在做web開發時候很多時候都需要即時監聽輸入框值的變化,以便作出即時動作去引導瀏覽者增強網站的用戶體驗感。而采用onchange時間又往往是在輸入框失去焦點(onblur)時候觸發,有時

vue data數據變化

watch func raw () vue 監聽 data ret color 當被監聽的數據發生變化是,函數被執行 created() { this.$watch("Withdrawals", function (newValue, oldValue) {