Android 铃声多媒体音量、静音、震动!震动!震动!哈哈(附源码)

来源:互联网 发布:照片电子相册制作软件 编辑:程序博客网 时间:2024/05/18 02:32

导读:

Android提供了可以进行对原生系统进行控制API。AudioManager用来对音量、模式(静音,震动,震动加声音等模式)等进行管理。可以用Vibrator、HapticFeedback进行管理手机震动。本人带着案例进行讲解,先温柔点讲控制系统音量,再说撩人的震动棒...呸!..是振荡器!

一、AudioManager (音频管理)

初始化获得实例

 AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);

三种修改音量方式

adjustVolume(direction,flag) //修改音量
adjustStreamVolume(streamType,direction,flag) //修改类型、音量
setStreamVolume(int streamType, int index, intflags)//直接设置音量大小

第一种参数讲解

direction(方向):顾名思义,就是点击按钮后,往上增加音量,往下减少音量,和保持音量不变。  

 AudioManager.ADJUST_LOWER(降低)      AudioManager.ADJUST_RAISE(升高)      AudioManager.ADJUST_SAME(锁定不变)

flag(标志):其实是点击按钮后,音量的一种表现形式。

AudioManager.FLAG_SHOW_UI :会弹出调节音量的界面AudioManager.FLAG_ALLOW_RINGER_MODES :最低声音会振动

第二种参数讲解

streamType(音频流类型):即指定声音类型,有下述几种声音类型:

STREAM_ALARM:手机闹铃     STREAM_MUSIC:手机音乐STREAM_RING:电话铃声      STREAM_SYSTEAM:手机系统STREAM_DTMF:音调         STREAM_NOTIFICATION:系统提示STREAM_VOICE_CALL:语音电话

第三种参数讲解:
index:音量的值 ,int类型。

案例:

XML 写一个SeekBar控件
<android.support.v7.widget.AppCompatSeekBar    android:id="@+id/play_volume"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:layout_marginTop="50dp"/>
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);        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) {                // TODO Auto-generated method stub                    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) ;}/** * 处理音量变化时的界面显示 * @author long */private class MyVolumeReceiver extends BroadcastReceiver {    @Override    public void onReceive(Context context, Intent intent) {        //如果音量发生变化则更改seekbar的位置        if(intent.getAction().equals("android.media.VOLUME_CHANGED_ACTION")){            //AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);            currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) ;// 当前的媒体音量            mView_sb_play_volume.setProgress(currentVolume) ;        }    }}

二、HapticFeedback(震动反馈)

首先,说明该震动方式不需要设置震动权限!!不需要设置震动权限!!不需要设置震动权限!!重要的事情说三遍。

从上面案例中所见,在SeekBar设置改变监听里自定义触发震动,下面先看一下源码讲解。

如下文所示,点击也会触发震动反馈了:

        click.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);            }        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

现在我们就去performHapticFeedback源码看下,都执行了什么。View.performHapticFeedback源码:

/**     * BZZZTT!!1!     *     * <p>Provide haptic feedback to the user for this view.     *     * <p>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.     *     * <p>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
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

这里解释三个知识点:

1、只有在isHapticFeedbackEnabled()为true的情况下,才会触发震动。之后会解释在为false的情况下,为何不会触发震动。

      在xml里,可以通过android:hapticFeedbackEnabled=”false|true”来进行设置

      在java代码里,可以通过view.setHapticFeedbackEnabled(boolean)来设置,不过默认是true哦。

2、HapticFeedbackConstants的常量值,我们要用到的有三个:

  • LONG_PRESS(长按);
  • FLAG_IGNORE_VIEW_SETTING(不受view的设置影响,即不受isHapticFeedbackEnabled()的影响);
  • FLAG_IGNORE_GLOBAL_SETTING(不受系统设置的影响,即不受是否开启震动反馈的影响);

3、最终是返回的performHapticFeedback(int feedbackConstant, int flags)这个方法。

    View.performHapticFeedback(int feedbackConstant, int flags)源码:

/**     * BZZZTT!!1!     *     * <p>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);    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

看第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”这句话,单击事件没有震动效果了。如下所示:

<Button        android:layout_width="wrap_content"        android:id="@+id/click"        android:layout_height="wrap_content"        android:hapticFeedbackEnabled="false"        android:text="make" />
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
如果这时,想让其震动,可以用如下方法来做:

 click.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS ,HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);//忽略view属性设置            }        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

还记得本篇文章之前,说去设置里打开触摸时震动的开关吗,其实,用户不打开,照样可以让其震动,只需要用如下的方法:

 click.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS ,HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);            }        });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

三、Vibrator(振荡器)

首先,这是安卓系统需要获取权限的震动:

<uses-permission android:name="android.permission.VIBRATE"/>


获取实例:

 Vibrator  vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);


两种震动方式:

1、按照指定的模式去震动:

 vibrator.vibrate(new long[]{100,1000,1000,1000}, -1);
数组参数意义:

  • 第一个参数为等待指定时间后开始震动,震动时间为第二个参数; 后边的参数依次为等待震动和震动的时间;
  • 第二个参数为重复次数,-1为不重复,0为一直震动;

2、指定震动的时间,数据类型long,单位为毫秒,一毫秒为1/1000秒

  vibrator.vibrate(2000);

取消震动:

注意:震动为一直震动的话,如果不取消震动,就算退出,也会一直震动

vibrator.cancel();

案例:

XML 

<Button    android:id="@+id/vibrator1"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:layout_marginTop="35dp"    android:text="震动模式一间断性"/><Button    android:id="@+id/vibrator2"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:layout_marginTop="20dp"    android:text="震动模式二独立性"/>

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


加群一起学习,我们不是一个人战斗:

 



原创粉丝点击