一.系統修改默認音量
frameworks\base\media\java\android\media\AudioSystem.java
1.1.音量類型
STREAM_VOICE_CALL 通話
STREAM_SYSTEM 系統
STREAM_RING 鈴聲
STREAM_MUSIC 媒體音量
STREAM_ALARM 鬧鍾
STREAM_NOTIFICATION 通知
public static final int STREAM_DEFAULT = -1; /* The audio stream for phone calls */ public static final int STREAM_VOICE_CALL = 0; /* The audio stream for system sounds */ public static final int STREAM_SYSTEM = 1; /* The audio stream for the phone ring and message alerts */ public static final int STREAM_RING = 2; /* The audio stream for music playback */ public static final int STREAM_MUSIC = 3; /* The audio stream for alarms */ public static final int STREAM_ALARM = 4; /* The audio stream for notifications */ public static final int STREAM_NOTIFICATION = 5; /* @hide The audio stream for phone calls when connected on bluetooth */ public static final int STREAM_BLUETOOTH_SCO = 6; /* @hide The audio stream for enforced system sounds in certain countries (e.g camera in Japan) */ public static final int STREAM_SYSTEM_ENFORCED = 7;
1.2.默認音量大小
public static int getDefaultStreamVolume(int streamType) { return DEFAULT_STREAM_VOLUME[streamType]; } public static int[] DEFAULT_STREAM_VOLUME = new int[] { 11, // STREAM_VOICE_CALL 11, // STREAM_SYSTEM 11, // STREAM_RING 11, // STREAM_MUSIC 11, // STREAM_ALARM 11, // STREAM_NOTIFICATION 11, // STREAM_BLUETOOTH_SCO 11, // STREAM_SYSTEM_ENFORCED 11, // STREAM_DTMF 11 // STREAM_TTS };
二.音頻管理器 修改 系統音量
1.1.權限問題
02-17 10:29:18.007 D/AndroidRuntime( 3353): Shutting down VM 02-17 10:29:18.009 E/AndroidRuntime( 3353): FATAL EXCEPTION: main 02-17 10:29:18.009 E/AndroidRuntime( 3353): Process: com.gatsby.sound, PID: 3353 02-17 10:29:18.009 E/AndroidRuntime( 3353): java.lang.SecurityException: Not allowed to change Do Not Disturb state 02-17 10:29:18.009 E/AndroidRuntime( 3353): at android.os.Parcel.readException(Parcel.java:1692) 02-17 10:29:18.009 E/AndroidRuntime( 3353): at android.os.Parcel.readException(Parcel.java:1645) 02-17 10:29:18.009 E/AndroidRuntime( 3353): at android.media.IAudioService$Stub$Proxy.setStreamVolume(IAudioService.java:788) 02-17 10:29:18.009 E/AndroidRuntime( 3353): at android.media.AudioManager.setStreamVolume(AudioManager.java:1046) 02-17 10:29:18.009 E/AndroidRuntime( 3353): at com.gatsby.sound.MainActivity$1.onProgressChanged(MainActivity.java:48) 02-17 10:29:18.009 E/AndroidRuntime( 3353): at android.widget.SeekBar.onProgressRefresh(SeekBar.java:93)
解決方法
Android 7.0及之后,設置系統音量需要開啟勿擾模式權限,需要在AndroidManifest.xml里面申請如下權限
<uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" />
然后設置音量的時候,如果沒有權限,需要引導用戶去設置頁打開勿擾模式下設置音量的權限:
NotificationManager mNotificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && !mNotificationManager.isNotificationPolicyAccessGranted()) { Intent intent = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS); mContext.startActivity(intent); }
2.Demo
2.1.AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.gatsby.sound"> <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Sound"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
2.2.dimens.xml
<resources> <!-- Default screen margins, per the Android Design guidelines. --> <dimen name="activity_horizontal_margin">16dp</dimen> <dimen name="activity_vertical_margin">16dp</dimen> </resources>
2.3.activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingBottom="@dimen/activity_vertical_margin"> <TextView android:id="@+id/lableSys" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignEnd="@+id/媒體音量" android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:text="系統音量:" /> <TextView android:id="@+id/媒體音量" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/seekBarSys" android:layout_alignEnd="@+id/lableNotfic" android:layout_alignParentStart="true" android:layout_marginTop="19dp" android:text="媒體音量" /> <TextView android:id="@+id/lableNotfic" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/媒體音量" android:layout_alignParentStart="true" android:layout_marginTop="23dp" android:text="系統提示音" /> <Button android:id="@+id/btnSysOut" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignParentBottom="true" android:layout_marginBottom="15dp" android:text="退出" /> <TextView android:id="@+id/sysVol" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/lableSys" android:layout_alignParentTop="true" android:layout_alignParentEnd="true" android:text="15/15" /> <TextView android:id="@+id/mediaVol" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@+id/seekBarMedia" android:layout_alignBottom="@+id/seekBarMedia" android:layout_alignParentEnd="true" android:text="0/10" /> <TextView android:id="@+id/notficVol" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/seekBarNotfic" android:layout_alignParentEnd="true" android:text="0/10" /> <SeekBar android:id="@+id/seekBarMedia" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignTop="@+id/媒體音量" android:layout_toEndOf="@+id/媒體音量" /> <SeekBar android:id="@+id/seekBarSys" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentEnd="true" android:layout_toEndOf="@+id/lableSys" /> <SeekBar android:id="@+id/seekBarNotfic" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignTop="@+id/lableNotfic" android:layout_alignParentEnd="true" android:layout_toEndOf="@+id/lableNotfic" /> </RelativeLayout>
2.3.MainActivity.java
package com.gatsby.sound; import android.annotation.SuppressLint; import android.app.NotificationManager; import android.content.Context; import android.content.Intent; import android.media.AudioManager; import android.os.Build; import android.os.Bundle; import android.provider.Settings; import android.view.View; import android.widget.Button; import android.widget.SeekBar; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { Context mContext; SeekBar sbSys; SeekBar sbMedia; SeekBar sbNotfic; AudioManager am; TextView sysVol; TextView mediaVol; TextView notficVol; @SuppressLint("SetTextI18n") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContext = this; am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); Button btn = (Button) findViewById(R.id.btnSysOut); sysVol = (TextView) findViewById(R.id.sysVol); mediaVol = (TextView) findViewById(R.id.mediaVol); notficVol = (TextView) findViewById(R.id.notficVol); sysVol.setText(am.getStreamVolume(AudioManager.STREAM_SYSTEM) + "/" + am.getStreamMaxVolume(AudioManager.STREAM_SYSTEM)); mediaVol.setText(am.getStreamVolume(AudioManager.STREAM_MUSIC) + "/" + am.getStreamMaxVolume(AudioManager.STREAM_MUSIC)); notficVol.setText(am.getStreamVolume(AudioManager.STREAM_NOTIFICATION) + "/" + am.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION)); sbSys = (SeekBar) findViewById(R.id.seekBarSys); sbSys.setMax(am.getStreamMaxVolume(AudioManager.STREAM_SYSTEM)); sbSys.setProgress(am.getStreamVolume(AudioManager.STREAM_SYSTEM)); sbMedia = (SeekBar) findViewById(R.id.seekBarMedia); sbMedia.setMax(am.getStreamMaxVolume(AudioManager.STREAM_MUSIC)); sbMedia.setProgress(am.getStreamVolume(AudioManager.STREAM_MUSIC)); sbNotfic = (SeekBar) findViewById(R.id.seekBarNotfic); sbNotfic.setMax(am.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION)); sbNotfic.setProgress(am.getStreamVolume(AudioManager.STREAM_NOTIFICATION)); //設置音量權限 NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && !mNotificationManager.isNotificationPolicyAccessGranted()) { Intent intent = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS); mContext.startActivity(intent); } //系統聲音 sbSys.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int i, boolean b) { am.setStreamVolume(AudioManager.STREAM_SYSTEM, i, AudioManager.FLAG_PLAY_SOUND); sysVol.setText(am.getStreamVolume(AudioManager.STREAM_SYSTEM) + "/" + am.getStreamMaxVolume(AudioManager.STREAM_SYSTEM)); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); //媒體聲音 sbMedia.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int i, boolean b) { am.setStreamVolume(AudioManager.STREAM_MUSIC, i, AudioManager.FLAG_PLAY_SOUND); mediaVol.setText(am.getStreamVolume(AudioManager.STREAM_MUSIC) + "/" + am.getStreamMaxVolume(AudioManager.STREAM_MUSIC)); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); //系統提示音 sbNotfic.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int i, boolean b) { am.setStreamVolume(AudioManager.STREAM_NOTIFICATION, i, AudioManager.FLAG_PLAY_SOUND); notficVol.setText(am.getStreamVolume(AudioManager.STREAM_NOTIFICATION) + "/" + am.getStreamMaxVolume(AudioManager.STREAM_NOTIFICATION)); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } }); //退出APP btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { System.exit(0); } }); } }
2.4.VolumeControl.java
package com.gatsby.sound; import android.app.Activity; import android.content.Context; import android.media.AudioManager; public class VolumeControl extends Activity { AudioManager am=(AudioManager) getSystemService(Context.AUDIO_SERVICE); /*手機鬧鈴的聲音*/ public static final int DEVICE_ALARM= AudioManager.STREAM_ALARM; /*手機音樂的聲音*/ public static final int DEVICE_MUSIC= AudioManager.STREAM_MUSIC; /*DTMF音調的聲音*/ public static final int DEVICE_DTMF= AudioManager.STREAM_DTMF; /*電話鈴聲的聲音*/ public static final int DEVICE_RING= AudioManager.STREAM_RING; /*系統提示的聲音*/ public static final int DEVICE_NOTFICATION= AudioManager.STREAM_NOTIFICATION; /*系統的聲音*/ public static final int DEVICE_SYSTEM= AudioManager.STREAM_SYSTEM; /*語音電話聲音*/ public static final int DEVICE_VOICE_CALL= AudioManager.STREAM_VOICE_CALL; /*降低音量*/ public static final int VOLUME_LOWER= AudioManager.ADJUST_LOWER; /*升高音量*/ public static final int VOLUME_RAISE= AudioManager.ADJUST_RAISE; /*保持不變*/ public static final int VOLUME_SAME= AudioManager.ADJUST_SAME; /*調整音量時播放聲音*/ public static final int FLAG_PLAY_SOUND= AudioManager.FLAG_PLAY_SOUND; /*調整時顯示音量條*/ public static final int FLAG_SHOW_UI = AudioManager.FLAG_SHOW_UI; /*調整音量時什么都不做*/ public static final int FLAG_NONE = 0; /** * 控制聲音大小 * @param streamType int AudioManager.STREAM_* 指定音量類型 * @param direction int AudioManager.ADJUST_* 調整音量大小 * @param flags int AudioManager.FLAG_* 調整音量時標志 * @return int 得到音量的當前值 */ public int volumeControl(int streamType,int direction,int flags){ am.adjustStreamVolume(streamType,direction,flags); return am.getStreamVolume(streamType); } /** * 設置音量指定值 * @param streamType int AudioManager.STREAM_* 指定音量類型 * @param index int [0,MAX_VOLUME] 調整音量大小值 * @param flag int AudioManager.FLAG_* 調整音量時標志 */ public void setVolume(int streamType,int index,int flag){ int maxVol=am.getStreamMaxVolume(streamType); index=index>maxVol?maxVol:index; am.setStreamVolume(streamType,index<=0?0:index,flag); } }