App中可能存在一些高频使用的功能,例如扫一扫、开启收付款码等。如果能够在不先打开App的情况下快速使用这些功能,将显著提升用户体验。
在上一篇文章Android 桌面小组件(一)--- 添加桌面小组件中介绍了如何创建桌面小组件并在桌面上添加。本文将进一步介绍提示用户添加小组件与启用小组件的配置页面。
提示用户添加小组件
App中配置好小组件之后,除了像上一篇文章中演示的那样在桌面直接添加小组件之外,从Android 8.0开始,系统支持App提示用户添加小组件到桌面。
具体步骤如下:
- 在
AndroidManifest
中声明App的小组件(在上一篇文件中已经介绍过,本文不再赘述)。 - 调用
AppWidgetManager.requestPinAppWidget()
方法,提示用户添加小组件。
调用requestPinAppWidget
调用AppWidgetManager.requestPinAppWidget()
示例代码如下:
less
class DesktopWidgetExampleActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = LayoutDesktopWidgetExampleActivityBinding.inflate(layoutInflater).also {
setContentView(it.root)
}
binding.btnAddDesktopWidget.setOnClickListener {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
AppWidgetManager.getInstance(this).run {
// 先判断是否支持添加小组件
if (isRequestPinAppWidgetSupported) {
// 小组件信息
val widgetProvider = ComponentName(this@DesktopWidgetExampleActivity, DesktopWidgetExampleProvider::class.java)
// 添加成功的广播(如果不需要,可以用null)
val successCallback = PendingIntent.getBroadcast(this@DesktopWidgetExampleActivity, 0, Intent(this@DesktopWidgetExampleActivity, DesktopWidgetExampleProvider::class.java).apply { action = ACTION_PIN_WIDGET }, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
// 请求添加小组件
requestPinAppWidget(widgetProvider, null, successCallback)
}
}
}
}
}
}
效果演示
如图:
启用小组件的配置页面
假如小组件有一些可配置项,系统支持使用一个独立的配置页面对小组件的可配置项进行管理。
具体步骤如下:
- 创建配置页面。
- 在
AndroidManifest
中声明配置页面。 - 在
AppWidgetProviderInfo
配置文件中声明配置页面。
创建配置页面
注意事项:
- 小组件的宿主(例如桌面)会将小组件的id通过
Intent
传入。 Activity
必须返回结果,并且结果必须包含传入的小组件id。
创建的配置页面示例代码如下:
kotlin
class DesktopWidgetConfigExampleActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = LayoutDesktopWidgetConfigExampleActivityBinding.inflate(layoutInflater).also {
setContentView(it.root)
}
if (!SpUtils.isInit()) {
SpUtils.init(this)
}
val appWidgetId = intent?.extras?.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID)
?: AppWidgetManager.INVALID_APPWIDGET_ID
// 先将结果设置为Activity.RESULT_CANCELED,如果没有顺利执行完整个流程,系统会取消添加widget。
setResult(Activity.RESULT_CANCELED, Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId))
binding.btnSave.setOnClickListener {
val targetWaterCount = binding.etInputTargetWaterCount.text.toString()
updateWidget(this, AppWidgetManager.getInstance(this), appWidgetId, targetWaterCount)
setResult(Activity.RESULT_OK, Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId))
finish()
}
}
private fun updateWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int, targetWaterCount: String) {
// 可能不是初次创建时打开配置,所以需要使用保存的数据。
val currentTotalWaterCount = SpUtils.getInt("currentTotalWaterCount", 0)
appWidgetManager.updateAppWidget(appWidgetId, RemoteViews(context.packageName, R.layout.layout_desktop_widget_example).apply {
setTextViewText(R.id.tv_target_water_count, "目标饮水量(杯):$targetWaterCount")
setTextViewText(R.id.tv_example_content, "当前饮水量(杯):$currentTotalWaterCount")
setOnClickPendingIntent(R.id.btn_plus, PendingIntent.getBroadcast(context, 0, Intent(context, DesktopWidgetExampleProvider::class.java).apply { action = ACTION_INCREASE }, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE))
setOnClickPendingIntent(R.id.btn_reduce, PendingIntent.getBroadcast(context, 0, Intent(context, DesktopWidgetExampleProvider::class.java).apply { action = ACTION_DECREASE }, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE))
})
}
}
在AndroidManfiest
中添加配置页面
小组件的宿主会通过携带ACTION_APPWIDGET_CONFIGURE
的Intent
打开配置页面,因此配置页面的intent-filter
要添加对应的action
,示例代码如下:
xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
......
<application
......
>
android:name=".androidapi.desktopwidgets.DesktopWidgetConfigExampleActivity"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
</application>
</manifest>
在AppWidgetProviderInfo配置文件中声明配置页面
在AppWidgetProviderInfo配置文件中,使用android:configure
属性来声明配置文件,示例代码如下:
xml
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:configure="com.chenyihong.exampledemo.androidapi.desktopwidgets.DesktopWidgetConfigExampleActivity"
android:widgetFeatures="reconfigurable"
...... />
PS: Android 9开始,增加了android:widgetFeatures
属性,配置为reconfigurable
时允许用户重新配置小组件,但是从Android 12开始才得到广泛支持。
效果演示
如图:
完整示例代码
所有演示代码已在示例Demo中添加。