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

导读:

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


一、AudioManager (音频管理)

1、音乐的播放方式

//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();//播放


2、修改音量方式

首先,拿到音频管理实例对象。 AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);

然后,设置音量。例如 audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 30, 0);

(1)修改音量

adjustVolume(int direction , int  flag) //修改音量

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

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

(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(标志):其实是点击事件发生后,音量的表现形式。

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

(3)设置音量大小 

setStreamVolume(int streamType, int index, int flags)//直接设置音量大小

index(音量的值) ,int类型。

 

4、实用小案例

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);//自定义音频文件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) ;
            }
        }
    }

二、HapticFeedback(震动反馈)

 

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

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

 

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

      click.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);

            }
        });

现在我们就去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、只有在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);
    }

 

看第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" />

如果这时,想让其震动,可以用如下方法来做:

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(振荡器)

震动的系统权限

<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

 

 

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

 

 

 

 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:书香水墨 设计师:CSDN官方博客 返回首页
评论

打赏作者

艾阳Blog

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值