Android 7.1 修改系统默认音量
一.系统修改默认音量
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); } }