Android 下拉栏中的快捷设置(二)— 状态更新与事件处理

App中可能存在一些高频使用的功能,例如扫一扫、开启收付款码等。如果能够在不先打开App的情况下快速使用这些功能,将显著提升用户体验。

在上一篇文章Android 下拉栏中的快捷设置(一)--- 创建添加中介绍了如何创建快捷设置并在下拉栏中添加。本文将进一步介绍快捷设置的状态更新与事件处理部分。

状态更新与事件处理

更新快捷设置状态

快捷设置包含下列三种状态,当用户添加了快捷设置之后,它只会在这三种状态中切换。

  • Tile.STATE_ACTIVE:启用状态,此状态下用户可以与快捷设置进行交互。
  • Tile.STATE_INACTIVE:关闭或暂停状态,此状态下用户可以与快捷设置进行交互。
  • Tile.STATE_UNAVAILABLE:暂时不可用,此状态下用户无法与快捷设置进行交互。

切换状态

可以通过代码切换快捷设置的状态,示例代码如下:

  • ExampleTileService
kotlin 复制代码
class ExampleTileService : TileService() {

    ......

    override fun onStartListening() {
        super.onStartListening()
        // 此处使用SharedPreferences记录要切换的状态
        if (!SpUtils.isInit()) {
            SpUtils.init(this)
        }
        val nextState = SpUtils.getInt("TileStatus", -1)
        if (nextState != -1) {
            // 除了更新state之外
            // 还可以更新Tile的Icon、Label、SubTitle等,根据实际需求选用
            qsTile.state = nextState
            // 调用update方法后设置才会生效
            qsTile.updateTile()
        }
    }

    ......
}
  • TileExampleActivity
kotlin 复制代码
class TileExampleActivity : AppCompatActivity() {

    private var currentStatus = Tile.STATE_ACTIVE

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = LayoutTileExmpleActivityBinding.inflate(layoutInflater).also {
            setContentView(it.root)
        }

        if (!SpUtils.isInit()) {
            SpUtils.init(this)
        }

        binding.btnChangeStatus.setOnClickListener {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                when (currentStatus) {
                    Tile.STATE_ACTIVE -> {
                        currentStatus = Tile.STATE_INACTIVE
                        SpUtils.put("TileStatus", currentStatus)
                    }

                    Tile.STATE_INACTIVE -> {
                        currentStatus = Tile.STATE_UNAVAILABLE
                        SpUtils.put("TileStatus", currentStatus)
                    }

                    Tile.STATE_UNAVAILABLE -> {
                        currentStatus = Tile.STATE_ACTIVE
                        SpUtils.put("TileStatus", currentStatus)
                    }
                }
                TileService.requestListeningState(this, ComponentName(this, ExampleTileService::class.java))
            }
        }
    }
}

如果快捷设置主要作为开关使用,官方建议在AndroidManifest中添加可切换标志,示例代码如下:

xml 复制代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <application
        ......
        >

        <service
            ......
            >

            <meta-data
                android:name="android.service.quicksettings.TOGGLEABLE_TILE"
                android:value="true" />

            ......
        </service>
    </application>
</manifest>

PS:示例代码中快捷设置的监听模式为Active mode

演示效果

禁用快捷设置

如果由于某些原因用户无法再使用快捷设置了,通过PackageManager.setComponentEnabledSetting()方法禁用对应的服务,示例代码如下:

kotlin 复制代码
class TileExampleActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = LayoutTileExmpleActivityBinding.inflate(layoutInflater).also {
            setContentView(it.root)
        }
        binding.btnDisableTile.setOnClickListener {
            packageManager.setComponentEnabledSetting(ComponentName(this, ExampleTileService::class.java), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
        }
    }
}

演示效果

处理点击

当快捷设置处于Tile.STATE_ACTIVETile.STATE_INACTIVE状态下时,用户点击时会回调TileServiceonClick()方法,可以根据需求进行处理。

打开弹窗

如果使用弹窗就能满足需求,可以调用TileServiceshowDialog()方法打开弹窗,示例代码如下:

kotlin 复制代码
class ExampleTileService : TileService() {

    ......

    override fun onClick() {
        super.onClick()
        showDialog(AlertDialog.Builder(this)
            .setTitle("Tile Example")
            .setMessage("This is a tile example dialog")
            .setPositiveButton("ok") { dialog, _ ->
                dialog?.dismiss()
            }
            .create())
    }
    
    ......
}

PS:实测中使用androidx.appcompat.app.AlertDialog会崩溃。

演示效果

打开页面

如果弹窗无法满足需求,那么可以调用TileServicestartActivityAndCollapse()方法打开Activity,示例代码如下:

kotlin 复制代码
class ExampleTileService : TileService() {

    ......

    override fun onClick() {
        super.onClick()
        // 此方法提示过时,但是在实测中,我的Google Pixel 3a XL只能使用此方法
        // 使用下面那个方法会报错。
        startActivityAndCollapse(Intent(this, CameraActivity::class.java).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))

        // 此方法为当前推荐使用的方法。
        // 实测小米14可以通过此方法打开页面。
        startActivityAndCollapse(PendingIntent.getActivity(this, this.hashCode(), Intent(this, CameraActivity::class.java), PendingIntent.FLAG_IMMUTABLE))
    }
    
    ......
}

演示效果

检验是否安全

在部分设备上,锁屏状态下也可以使用下拉栏的快捷设置,如果功能涉及敏感信息,那么就不应该锁屏状态时可以直接使用。可以使用TileServiceisSecure()方法判断是否安全,如果返回false则可以使用TileServiceunlockAndRun()方法让用户解锁后使用功能,示例代码如下:

kotlin 复制代码
class ExampleTileService : TileService() {

    ......

    override fun onClick() {
        super.onClick()
        if (isSecure) {
            handleClick()
        } else {
            unlockAndRun { handleClick() }
        }

    }

    private fun handleClick() {
        showDialog(AlertDialog.Builder(this)
            .setTitle("Tile Example")
            .setMessage("This is a tile example dialog")
            .setPositiveButton("ok") { dialog, _ ->
                dialog?.dismiss()
            }
            .create())
    }
    
    ......
}

演示效果

完整示例代码

所有演示代码已在示例Demo中添加。

ExampleDemo github

ExampleDemo gitee

相关推荐
勿问东西10 分钟前
【Android】设备操作
android
五味香17 分钟前
C++学习,信号处理
android·c语言·开发语言·c++·学习·算法·信号处理
图王大胜2 小时前
Android Framework AMS(01)AMS启动及相关初始化1-4
android·framework·ams·systemserver
工程师老罗4 小时前
Android Button “No speakable text present” 问题解决
android
小雨cc5566ru5 小时前
hbuilderx+uniapp+Android健身房管理系统 微信小程序z488g
android·微信小程序·uni-app
小雨cc5566ru6 小时前
微信小程序hbuilderx+uniapp+Android 新农村综合风貌旅游展示平台
android·微信小程序·uni-app
小雨cc5566ru6 小时前
小程序 uniapp+Android+hbuilderx体育场地预约管理系统的设计与实现
android·小程序·uni-app
佛系小嘟嘟8 小时前
Android-由switch-case和view.getId()引起的bug:错误:需要常量表达式 的解决办法
android·bug
勿问东西8 小时前
【Android】事件
android
连连斯基11 小时前
Android Framework(八)WMS-窗口动效概述
android·dubbo