Android提供了可以进行对原生系统进行控制API。AudioManager用来对音量、模式(静音,震动,震动加声音等模式)等进行管理。可以用Vibrator、HapticFeedback进行管理手机震动。本人带着案例进行讲解,先温柔点讲控制系统音量,再说撩人的震动棒...呸..是振荡器。
//1、自定义音频文件test
MediaPlayer player = MediaPlayer.create(getApplicationContext(), R.raw.test);
//2、系统电话铃声TYPE_RINGTONE\系统通知铃声TYPE_NOTIFICATION
Uri uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
MediaPlayer mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource(PlayerService.this, uri);
————————————————————————————————————————————————————————————————
mMediaPlayer.setLooping(true); // 设置循环播放
mMediaPlayer.prepare();//准备
mMediaPlayer.start();//播放
首先,拿到音频管理实例对象。 AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
然后,设置音量。例如 audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 30, 0);
(1)修改音量
adjustVolume(int direction , int flag) //修改音量
direction(方向):顾名思义,就是点击事件发生,往上增加音量,往下减少音量,和保持音量不变。
(2) 修改类型、音量
adjustStreamVolume(int streamType ,int direction , int flag) //修改类型、音量
streamType(音频流类型):即指定声音类型,有下述几种声音类型:
STREAM_ALARM:手机闹铃 STREAM_MUSIC:手机音乐
STREAM_RING:电话铃声 STREAM_SYSTEAM:手机系统
STREAM_DTMF:音调 STREAM_NOTIFICATION:系统提示
STREAM_VOICE_CALL:语音电话
flag(标志):其实是点击事件发生后,音量的表现形式。
(3)设置音量大小
setStreamVolume(int streamType, int index, int flags)//直接设置音量大小
index(音量的值) ,int类型。
XML 写一个SeekBar控件
Activiy中的代码
声明变量
private MediaPlayer player;//测试音乐
private int maxVolume, currentVolume;//音量值
private AudioManager audioManager;//音频管理类
private SeekBar mView_sb_play_volume; //控件
初始化操作
mView_sb_play_volume = (SeekBar) findViewById(R.id.play_volume);//滑动进度条
myRegisterReceiver();//注册同步更新的广播
player = MediaPlayer.create(getApplicationContext(), R.raw.test);//自定义音频文件test
audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);//实例
maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC); //获取系统最大音量
mView_sb_play_volume.setMax(maxVolume);
currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC); //获取当前值
mView_sb_play_volume.setProgress(currentVolume);
player.setLooping(true);
mView_sb_play_volume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
player.pause();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
player.start();
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, progress, 0);
seekBar.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
// seekBar.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
// seekBar.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
//HapticFeedbackConstants的常量值,我们要用到的有三个触摸震动方式:
// 一个是LONG_PRESS(长按),
// 第二个是FLAG_IGNORE_VIEW_SETTING(不受Xml里view的属性设置影响,即不受isHapticFeedbackEnabled()的影响),
// 第三个是FLAG_IGNORE_GLOBAL_SETTING(不受系统设置的影响,即不受是否开启震动反馈的影响)
}
});
广播监听音量变化
//注册当音量发生变化时接收的广播
private void myRegisterReceiver(){
MyVolumeReceiver mVolumeReceiver = new MyVolumeReceiver() ;
IntentFilter filter = new IntentFilter() ;
filter.addAction("android.media.VOLUME_CHANGED_ACTION") ;
registerReceiver(mVolumeReceiver, filter) ;
}
//处理音量变化时的界面显示
private class MyVolumeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//如果音量发生变化则更改seekbar的位置
if(intent.getAction().equals("android.media.VOLUME_CHANGED_ACTION")){
//AudioManager mAm = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
// 当前的媒体音量
currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) ;
mView_sb_play_volume.setProgress(currentVolume) ;
}
}
}
首先,说明该震动方式不需要设置震动权限!!不需要设置震动权限!!不需要设置震动权限!!重要的事情说三遍。
从上面案例中所见,在SeekBar设置改变监听里自定义触发震动,下面先看一下源码讲解。
如下文所示,点击也会触发震动反馈了:
click.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
}
});
现在我们就去performHapticFeedback源码看下,都执行了什么。View.performHapticFeedback源码:
/**
* BZZZTT!!1!
*
* Provide haptic feedback to the user for this view.
*
*
The framework will provide haptic feedback for some built in actions,
* such as long presses, but you may wish to provide feedback for your
* own widget.
*
*
The feedback will only be performed if
* {@link #isHapticFeedbackEnabled()} is true.
*
* @param feedbackConstant One of the constants defined in
* {@link HapticFeedbackConstants}
*/
public boolean performHapticFeedback(int feedbackConstant) {
return performHapticFeedback(feedbackConstant, 0);
}
这里解释三个知识点:
1、只有在isHapticFeedbackEnabled()为true的情况下,才会触发震动。之后会解释在为false的情况下,为何不会触发震动。
在xml里,可以通过android:hapticFeedbackEnabled=”false|true”来进行设置
在java代码里,可以通过view.setHapticFeedbackEnabled(boolean)来设置,不过默认是true哦。
2、HapticFeedbackConstants的常量值,我们要用到的有三个:
3、最终是返回的performHapticFeedback(int feedbackConstant, int flags)这个方法。
View.performHapticFeedback(int feedbackConstant, int flags)源码:
/**
* BZZZTT!!1!
*
* Like {@link #performHapticFeedback(int)}, with additional options.
*
* @param feedbackConstant One of the constants defined in
* {@link HapticFeedbackConstants}
* @param flags Additional flags as per {@link HapticFeedbackConstants}.
*/
public boolean performHapticFeedback(int feedbackConstant, int flags) {
if (mAttachInfo == null) {
return false;
}
//noinspection SimplifiableIfStatement
if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
&& !isHapticFeedbackEnabled()) {
return false;
}
return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
(flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
}
看第15行的if语句,当flags=0时,flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING为0,又isHapticFeedbackEnabled()为false,整个条件为真,所以会执行17行,直接return。这也是为什么performHapticFeedback(int feedbackConstant)方法一定要在isHapticFeedbackEnabled()为ture的情况下才会触发震动。 在这里说一下,&是按位与,返回数值,&&逻辑与,返回布尔值。 第19-20行,就是触发底层震动的代码了,之后代码不做分析。
在单击事件,会触发震动:
click.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);//长按
}
});
如果xml加上 android:hapticFeedbackEnabled=”false”这句话,单击事件没有震动效果了。如下所示:
如果这时,想让其震动,可以用如下方法来做:
click.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS
,HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);//忽略view属性设置
}
});
还记得本篇文章之前,说去设置里打开触摸时震动的开关吗,其实,用户不打开,照样可以让其震动,只需要用如下的方法:
click.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS
,HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
}
});
震动的系统权限
获取实例:
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
两种震动方式:
1、按照指定的模式去震动:
vibrator.vibrate(new long[]{100,1000,1000,1000}, -1);
数组参数意义:
2、指定震动的时间,数据类型long,单位为毫秒,一毫秒为1/1000秒
vibrator.vibrate(2000);
取消震动:
注意:震动为一直震动的话,如果不取消震动,就算退出,也会一直震动
vibrator.cancel();
XML
Activity
private Button vibrator1,vibrator2;//控件
private Vibrator vibrator;//震动
vibrator1 = (Button) findViewById(R.id.vibrator1);
vibrator2 =(Button)findViewById(R.id.vibrator2);
vibrator1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(new long[]{100,1000,1000,1000}, -1);
//按照指定的模式去震动。数组参数意义:
// 第一个参数为等待指定时间后开始震动,震动时间为第二个参数; 后边的参数依次为等待震动和震动的时间;
// 第二个参数为重复次数,-1为不重复,0为一直震动;
}
});
vibrator2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(2000);//震动指定时间 ,数据类型long,单位为毫秒,一毫秒为1/1000秒
}
});
// vibrator.cancel();//取消震动,立即停止震动震动为一直震动的话,如果不取消震动,就算退出,也会一直震动
源码:安卓系统音频震动demohttp://download.csdn.net/download/csdn_aiyang/9970166
加群一起学习,我们不是一个人战斗: