针对通知栏快捷磁贴开发,Google提供了公开服务快捷设置,可以看到开发者可以通过使用此服务完成快捷开发.
此服务依赖于android N(API24)
下面进入正文
首先创建服务继承TileService
package com.mml.oneplus.nh.service
import android.annotation.SuppressLint
import android.graphics.drawable.Icon
import android.service.quicksettings.Tile
import android.service.quicksettings.TileService
import com.mml.oneplus.nh.R
import com.mml.oneplus.nh.util.log
import com.mml.oneplus.nh.util.showDebugToast
@SuppressLint("NewApi")
class QuickStartTileService : TileService() {
companion object {
const val TAG = "QuickStartTileService"
}
//当用户从Edit栏添加到快速设置中调用
override fun onTileAdded() {
super.onTileAdded()
showDebugToast(context = applicationContext, msg = "onTileAdded")
log("onTileAdded", TAG)
}
//当用户从快速设置栏中移除的时候调用
override fun onTileRemoved() {
super.onTileRemoved()
log("onTileRemoved", TAG)
}
// 点击的时候
/* 我们可以通过getQsTile来获得Tile对象,通过getState() 来获得Tile当前状态。
- STATE_ACTIVE 开启状态
- STATE_INACTIVE 关闭状态
- STATE_UNAVAILABLE 非可点击状态
最后必须调用updateTile() 来触发刷新*/
override fun onClick() {
super.onClick()
log("onClick", TAG)
val state = qsTile.state
log(tag = TAG, msg = "onClick state = " + qsTile.state.toString())
var icon: Icon = Icon.createWithResource(applicationContext, R.drawable.ic_message)
when (state) {
Tile.STATE_INACTIVE -> {
// icon = Icon.createWithResource(applicationContext, R.drawable.logo_qq)
qsTile.state = Tile.STATE_ACTIVE// 更改成活跃状态
showDebugToast(applicationContext, "STATE_INACTIVE to STATE_ACTIVE")
startOrShowNotification()
}
Tile.STATE_ACTIVE -> {
// icon = Icon.createWithResource(applicationContext, R.drawable.logo_wechat)
qsTile.state = Tile.STATE_INACTIVE//更改成非活跃状态
showDebugToast(applicationContext, "STATE_ACTIVE to STATE_INACTIVE")
cancelNotification()
}
Tile.STATE_UNAVAILABLE -> {
// icon = Icon.createWithResource(applicationContext, R.drawable.ic_noti_action_cancel)
}
}
qsTile.icon = icon//设置图标
qsTile.updateTile()//更新Tile
}
private fun cancelNotification() {
if (NotificationService.isStart) {
NotificationService.sendAction(
applicationContext,
NotificationService.ACTION_SERVICE_NOTI_HIDE
)
}
}
private fun startOrShowNotification() {
if (!NotificationService.isStart) {
NotificationService.startService(applicationContext)
} else {
if (!NotificationService.isShowed) {
NotificationService.sendAction(
applicationContext,
NotificationService.ACTION_SERVICE_NOTI_SHOW
)
}
}
}
// 打开下拉菜单的时候调用,当快速设置按钮并没有在编辑栏拖到设置栏中不会调用
//在TleAdded之后会调用一次
override fun onStartListening() {
super.onStartListening()
log("onStartListening", TAG)
}
// 关闭下拉菜单的时候调用,当快速设置按钮并没有在编辑栏拖到设置栏中不会调用
// 在onTileRemoved移除之前也会调用移除
override fun onStopListening() {
super.onStopListening()
log("onStopListening", TAG)
}
}
在mainfast声明服务
注意,服务声明时必须指定label和icon
<service
android:name=".QuickStartTileService"
android:label="@string/my_default_tile_label"
android:icon="@drawable/my_default_icon_label"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action android:name="android.service.quicksettings.action.QS_TILE" />
intent-filter>
<meta-data android:name="android.service.quicksettings.ACTIVE_TILE"
android:value="true" />
service>
生命周期介绍
法名 | 功能 |
---|---|
onTileAdded() | 当用户从Edit栏添加到快速设置中调用 |
onTileRemoved() | 当用户从快速设置区域移除一个Tile时调用,这里不要做有关于此Tile的任何操作。 |
onStartListening() | 打开下拉菜单的时候调用,当快速设置按钮并没有在编辑栏拖到设置栏中不会调用,在TleAdded之后会调用一次 |
onStopListening() | 关闭下拉菜单的时候调用,当快速设置按钮并没有在编辑栏拖到设置栏中不会调用,在onTileRemoved移除之前也会调用移除 |
onClick() | 点击磁贴时调用,我们可以通过getQsTile来获得Tile对象,通过getState() 来获得Tile当前状态。- STATE_ACTIVE: 开启状态- STATE_INACTIVE: 关闭状态 - STATE_UNAVAILABLE: 非可点击状态,最后必须调用updateTile() 来触发刷新 |
主动调用
需要在声明处调用
然后即可在代码中通过TileService.requestListeningState(this, ComponentName( BuildConfig.APPLICATION_ID, QuickStartTileService::class.java.name ))
激活服务
重写长按磁贴逻辑
默认长按磁贴逻辑为跳转到app详情界面,如果需要重写逻辑只需要在相应activity声明处添加一个action过滤即可
在添加如下代码
默认的tileservice长按是打开appinfo界面,可以通过添加上面代码实现重写长按逻辑,但是会有一个问题是,如果有多个tileservice时,长按会到同一个处理界面,这就要分别执行不同的长按逻辑,这一点官方文档指出,service会携带一个 Intent#EXTRA_COMPONENT_NAME 标识他从哪个tileservice来,所以根据它进行单独处理.
首先定一个长按接口
interface TileServiceLongClick {
fun onLongClick()
}
定义tileservice,继承长按接口
@SuppressLint("NewApi")
class QuickStartTileService : TileService(),TileServiceLongClick {
companion object {
const val TAG = "QuickStartTileService"
}
//当用户从Edit栏添加到快速设置中调用
override fun onTileAdded() {
super.onTileAdded()
showDebugToast(context = applicationContext, msg = "onTileAdded")
log("onTileAdded", TAG)
}
//当用户从快速设置栏中移除的时候调用
override fun onTileRemoved() {
super.onTileRemoved()
log("onTileRemoved", TAG)
}
// 点击的时候
/* 我们可以通过getQsTile来获得Tile对象,通过getState() 来获得Tile当前状态。
- STATE_ACTIVE 开启状态
- STATE_INACTIVE 关闭状态
- STATE_UNAVAILABLE 非可点击状态
最后必须调用updateTile() 来触发刷新*/
override fun onClick() {
super.onClick()
log("onClick", TAG)
val state = qsTile.state
log(tag = TAG, msg = "onClick state = " + qsTile.state.toString())
var icon: Icon = Icon.createWithResource(applicationContext, R.drawable.ic_message)
when (state) {
Tile.STATE_INACTIVE -> {
// icon = Icon.createWithResource(applicationContext, R.drawable.logo_qq)
qsTile.state = Tile.STATE_ACTIVE// 更改成活跃状态
showDebugToast(applicationContext, "STATE_INACTIVE to STATE_ACTIVE")
}
Tile.STATE_ACTIVE -> {
// icon = Icon.createWithResource(applicationContext, R.drawable.logo_wechat)
qsTile.state = Tile.STATE_INACTIVE//更改成非活跃状态
showDebugToast(applicationContext, "STATE_ACTIVE to STATE_INACTIVE")
}
Tile.STATE_UNAVAILABLE -> {
// icon = Icon.createWithResource(applicationContext, R.drawable.ic_noti_action_cancel)
}
}
qsTile.icon = icon//设置图标
qsTile.updateTile()//更新Tile
}
// 打开下拉菜单的时候调用,当快速设置按钮并没有在编辑栏拖到设置栏中不会调用
//在TleAdded之后会调用一次
override fun onStartListening() {
super.onStartListening()
log("onStartListening", TAG)
}
// 关闭下拉菜单的时候调用,当快速设置按钮并没有在编辑栏拖到设置栏中不会调用
// 在onTileRemoved移除之前也会调用移除
override fun onStopListening() {
super.onStopListening()
log("onStopListening", TAG)
}
override fun onLongClick(){
//通知栏快捷图快打开默认是常显示通知,可在设置更改
}
}
在对应接收长按事件的activity进行判断
获取到来源以后便通过反射调用onlongclick方法
class QuickLaunchServiceActivity : BaseActivity() {
@RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//长按通知栏快捷图标 直接启动服务
if (intent.action == TileService.ACTION_QS_TILE_PREFERENCES) {
val componentName =intent.extras?.get(Intent.EXTRA_COMPONENT_NAME) as ComponentName?
componentName?:return
Class.forName(componentName.className).newInstance().apply {
if (this is TileServiceLongClick) {
onLongClick()
}
}
}
finish()
}
}