Android 下拉栏中的快捷设置(一)— 创建与添加

1,193 阅读3分钟

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

在之前的文章Android 快捷方式中介绍了如何添加桌面快捷方式。除此之外,还可以使用Android系统的Tiles来实现在下拉栏中创建快捷设置。本文将简单介绍如何使用Tiles相关API在下拉栏中实现快捷设置。

实现快捷设置

自定义TileService

要实现下拉栏中的快捷设置,需要自定义一个Service继承TileService,实现自定义的TileService之前,首先来了解一下TileService的监听模式和生命周期。

TileService的生命周期

TileService是绑定服务,所以正常绑定服务拥有的onCreate()onBind()onUnbind()onDestory()等生命周期方法会在对应的阶段执行。此外TileService还实现了4个独有的生命周期方法,如下:

  • onTileAdded():当用户添加快捷设置时执行此方法,初次添加或者删除后再添加都会执行。
  • onTileRemoved():当用户移除快捷设置时执行此方法。
  • onStartListening():当系统开始监听Tile的状态、内容时调用。
  • onStopListening():当系统停止监听Tile的状态、内容时调用。

TileService的监听模式

TileService存在Active modeNon-active mode两种监听模式,那么二者有什么区别呢?

Non-active mode

此模式为默认模式。在此模式下,自定义的快捷设置对用户可见时,如果TileService还未被绑定则会被绑定,并且会执行onStartListening()方法。

Active mode

在此模式下,自定义的快捷设置对用户可见时,即使TileService还未被绑定也不会立刻被绑定。可以在应用中通过TileService.requestListeningState()方法请求开始监听状态并触发onStartListening()方法,对Tile进行更新。此模式的优势在于减少了系统资源的消耗。

要使用此模式,需要在AndroidManifest中添加额外配置,代码如下:

<?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.ACTIVE_TILE"
                android:value="true" />

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

自定义ExampleTileService

自定义ExampleTileService继承TileService,示例代码如下:

class ExampleTileService : TileService() {

    override fun onTileAdded() {
        super.onTileAdded()
        // 当用户添加App提供的Tile时调用此方法
    }

    override fun onTileRemoved() {
        super.onTileRemoved()
        // 当用户移除App提供的Tile时调用此方法
    }

    override fun onClick() {
        super.onClick()
        // 用户在下拉栏中点击Tile时调用此方法
    }

    override fun onStartListening() {
        super.onStartListening()
        // 系统开始监听Tile的状态、内容时调用此方法
    }

    override fun onStopListening() {
        super.onStopListening()
        // 系统结束监听Tile的状态、内容时调用此方法
    }
}

AndroidManifest中声明自定义TileService

示例代码如下:

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

    <application
        ......
        >

        <service
            android:name=".androidapi.tiles.ExampleTileService"
            android:exported="true"
            android:icon="@drawable/icon_scan"
            android:label="@string/label_tile_example_scan"
            android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">

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

            <intent-filter>
                <action android:name="android.service.quicksettings.action.QS_TILE" />
            </intent-filter>
        </service>
    </application>
</manifest>

效果演示

效果如下图:

Screen_recording_202 -big-original.gif

提示用户添加快捷设置

从Android 13开始,可以使用StatusBarManagerrequestAddTileService()方法快速添加快捷设置,示例代码如下:

class TileExampleActivity : AppCompatActivity() {

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

        val statusBarManager: StatusBarManager? = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            getSystemService(StatusBarManager::class.java)
        } else {
            null
        }
        binding.btnAddTile.setOnClickListener {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                statusBarManager?.requestAddTileService(
                    ComponentName(this, ExampleTileService::class.java),
                    getString(R.string.label_tile_example_scan),
                    Icon.createWithResource(this, R.drawable.icon_scan),
                    ContextCompat.getMainExecutor(this),
                ) { code ->
                    // 添加事件回调,返回下列状态码之一
                    // TILE_ADD_REQUEST_RESULT_TILE_NOT_ADDED(未添加成功)
                    // TILE_ADD_REQUEST_RESULT_TILE_ALREADY_ADDED (之前已经添加过)
                    // TILE_ADD_REQUEST_RESULT_TILE_ADDED(添加成功)
                }
            }
        }
    }
}

效果演示

效果如下图:

Screen_recording_202 -original-original.gif

完整示例代码

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

ExampleDemo github

ExampleDemo gitee