Android开发全局音量调整的实现方式详解

 更新时间:2022年11月27日 16:19:37   作者:ChenYhong  
这篇文章主要为大家介绍了Android开发全局音量调整的实现方式详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

之前参与过一个项目,开发的是一个系统级别的软件,安装在定制的设备上,设备没有控制音量的按键,因此软件需要实现一个在任意页面都能控制音量的功能。

实现方案是在所有页面的顶部加上一个触发音量控制弹窗的按钮,用户点击该按钮后显示音量控制弹窗。

全局添加按钮

参与项目时,已经出了第一版了,包含的页面很多,因此一个个页面去加肯定不合适。项目中所有Activity都继承了一个自定义的BaseActivity,所以只能在这个BaseActivity中做文章。

Android中,每个Activity都包含一个DecorViewDecorView内部包含一个FrameLayout,可以通过android.R.id.content来获取,我们的布局包含在这个FrameLayout中。

因此如果需要在所有的页面都添加View,那么在BaseActivity中实现向android.R.id.content对应的FrameLayout添加View的逻辑,然后所有的Activity就都可以自动添加View了。

实现代码如下:

object DensityUtil {
    @JvmStatic
    fun dp2Px(dpValue: Int): Int {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpValue.toFloat(), Resources.getSystem().displayMetrics).toInt()
    }
    @JvmStatic
    fun px2Dp(pxValue: Int): Int {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, pxValue.toFloat(), Resources.getSystem().displayMetrics).toInt()
    }
}
// Base类
open class BaseActivity : AppCompatActivity() {
    override fun onResume() {
        super.onResume()
        // 在onResume中添加,确保在主布局添加完成后添加,避免被遮挡。
        initVolumeControllerView()
    }
    private fun initVolumeControllerView() {
        val controllerView = AppCompatImageView(this)
        controllerView.layoutParams = FrameLayout.LayoutParams(DensityUtil.dp2Px(80), DensityUtil.dp2Px(12)).apply {
            gravity = Gravity.START
            marginStart = DensityUtil.dp2Px(20)
            topMargin = DensityUtil.dp2Px(10)
        }
        controllerView.setImageResource(R.drawable.shape_vollume_controller)
        controllerView.setOnClickListener {
            runOnUiThread { Toast.makeText(this, "点击了全局按钮", Toast.LENGTH_SHORT).show() }
        }
        val rootView = findViewById<FrameLayout>(android.R.id.content)
        rootView.addView(controllerView)
    }
}

效果如图:

音量控制

AudioManager类提供了控制音量的方法。

实现音量控制代码如下:

class VolumeControllerDialog : DialogFragment() {
    private var binding: LayoutVolumeContollerDialogBinding? = null
    private var currentVolume = 0
    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        dialog?.window?.run {
            setBackgroundDrawable(ContextCompat.getDrawable(requireContext(), android.R.color.transparent))
            decorView.setBackgroundResource(android.R.color.transparent)
            val layoutParams = attributes
            layoutParams.width = DensityUtil.dp2Px(360)
            layoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT
            layoutParams.gravity = Gravity.CENTER
            attributes = layoutParams
        }
        binding = DataBindingUtil.inflate(inflater, R.layout.layout_volume_contoller_dialog, container, false)
        return binding?.root
    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val audioManager = requireContext().getSystemService(Context.AUDIO_SERVICE) as AudioManager
        currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
        val step = 1
        binding?.run {
            btnMute.text = getMuteButtonString(audioManager.isStreamMute(AudioManager.STREAM_MUSIC))
            btnIncreaseVolume.setOnClickListener {
                // 增加音量
                currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
                audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, currentVolume + step, AudioManager.FLAG_SHOW_UI or AudioManager.FLAG_PLAY_SOUND)
                btnMute.text = getMuteButtonString(audioManager.isStreamMute(AudioManager.STREAM_MUSIC))
            }
            btnReduceVolume.setOnClickListener {
                //减少音量
                currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
                audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, if (currentVolume - step < 0) 0 else currentVolume - step, AudioManager.FLAG_SHOW_UI or AudioManager.FLAG_PLAY_SOUND)
                btnMute.text = getMuteButtonString(audioManager.isStreamMute(AudioManager.STREAM_MUSIC))
            }
            btnMute.setOnClickListener {
                // 静音或取消静音
                val currentMute = audioManager.isStreamMute(AudioManager.STREAM_MUSIC)
                if (currentVolume == 0) {
                    btnMute.text = getMuteButtonString(true)
                } else {
                    btnMute.text = getMuteButtonString(!currentMute)
                }
                val setVolume = if (currentMute) {
                    currentVolume
                } else {
                    currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
                    0
                }
                audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, setVolume, AudioManager.FLAG_SHOW_UI or AudioManager.FLAG_PLAY_SOUND)
            }
        }
    }
    private fun getMuteButtonString(mute: Boolean): String {
        return if (mute) "UnMute" else "Mute"
    }
}
open class BaseActivity : AppCompatActivity() {
    override fun onResume() {
        super.onResume()
        // 在onResume中添加,确保在主布局添加完成后添加,避免被遮挡。
        initVolumeControllerView()
    }
    private fun initVolumeControllerView() {
        val controllerView = AppCompatImageView(this)
        controllerView.layoutParams = FrameLayout.LayoutParams(DensityUtil.dp2Px(80), DensityUtil.dp2Px(12)).apply {
            gravity = Gravity.START
            marginStart = DensityUtil.dp2Px(20)
            topMargin = DensityUtil.dp2Px(10)
        }
        controllerView.setImageResource(R.drawable.shape_vollume_controller)
        controllerView.setOnClickListener {
            VolumeControllerDialog().show(supportFragmentManager, null)
        }
        val rootView = findViewById<FrameLayout>(android.R.id.content)
        rootView.addView(controllerView)
    }
}

效果如图:

以上就是Android开发全局音量调整的实现方式详解的详细内容,更多关于Android 全局音量调整的资料请关注脚本之家其它相关文章!

相关文章

  • Android实现点击Button产生水波纹效果

    Android实现点击Button产生水波纹效果

    这篇文章主要介绍了Android实现点击Button产生水波纹效果,需要的朋友可以参考下
    2016-01-01
  • Android Dispatchers.IO线程池深入刨析

    Android Dispatchers.IO线程池深入刨析

    这篇文章主要为大家介绍了Android Kotlin线程池Dispatchers.IO原理,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-08-08
  • android获取照片的快照 思路及实现方法

    android获取照片的快照 思路及实现方法

    android获取照片的快照 思路及实现方法,需要的朋友可以参考一下
    2013-06-06
  • Android手机联系人快速索引(手机通讯录)

    Android手机联系人快速索引(手机通讯录)

    最近需要实现一个手机通讯录的快速索引功能。根据姓名首字母快速索引功能,下面通过本篇文章给大家介绍Android手机联系人快速索引(手机通讯录)的相关代码,需要的朋友参考下
    2015-12-12
  • Android数据库增删改查实战案例

    Android数据库增删改查实战案例

    我们在编程中经常会遇到数据库的操作,这篇文章主要给大家介绍了关于Android数据库增删改查的相关资料,文中通过图文以及实例代码介绍的非常详细,需要的朋友可以参考下
    2023-04-04
  • Android 遍历文件夹中所有文件的实例代码

    Android 遍历文件夹中所有文件的实例代码

    本篇文章主要介绍了Android 遍历文件夹中所有文件的实例代码,可以获得文件夹中所有文件的路径及文件名,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-06-06
  • 深入理解Android中View绘制的三大流程

    深入理解Android中View绘制的三大流程

    这篇文章主要给大家介绍了关于Android中View绘制的三大流程,View的工作流程主要是指measure、layout、draw这三大流程,即测量、布局和绘制,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-07-07
  • Android 操作系统获取Root权限 原理详细解析

    Android 操作系统获取Root权限 原理详细解析

    许多机友新购来的Android机器没有破解过Root权限,无法使用一些需要高权限的软件,以及进行一些高权限的操作,其实破解手机Root权限是比较简单及安全的,破解Root权限的原理就是在手机的/system/bin/或/system/xbin/目录下放置一个可执行文件“su”
    2013-10-10
  • Android实现socket通信统一接口的方法

    Android实现socket通信统一接口的方法

    这篇文章主要介绍了Android实现socket通信统一接口 ,实现了统一接口之后确实可以使后续修改实现更加方便,程序结构也更加工程化,需要的朋友可以参考下
    2021-12-12
  • android 仿微信demo——微信通讯录界面功能实现(移动端,服务端)

    android 仿微信demo——微信通讯录界面功能实现(移动端,服务端)

    本系列文章主要介绍了微信小程序-阅读小程序实例(demo),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望能给你们提供帮助
    2021-06-06

最新评论