理解 RemoteViews -- 重读《Android 开发艺术探索》

202 阅读1分钟

本篇为第五章的内容

本章内容的思维导图

image.png

image.png

image.png

image.png

相关代码

显示一条通知

// 显示一条通知
private fun showNotification() {

    // 点击通知打开一个新页面
    val intent = Intent(this, DemoActivity::class.java)
    val pendingIntent =
        PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)

    val notification: Notification

    val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    if (Build.VERSION.SDK_INT >= 26) {
        val channelId = "notify_i"
        val channel =
            NotificationChannel(channelId, "notify_n", NotificationManager.IMPORTANCE_DEFAULT)
        manager.createNotificationChannel(channel)
        notification = Notification.Builder(this, channelId)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setWhen(System.currentTimeMillis())
            .setContentText("contentText")
            .setContentIntent(pendingIntent)
            .setSubText("subText")
            .setAutoCancel(true)
            .build()
    } else {
        notification = Notification.Builder(this)
            .setSmallIcon(R.mipmap.ic_launcher)
            .setWhen(System.currentTimeMillis())
            .setContentText("contentText")
            .setContentIntent(pendingIntent)
            .setSubText("subText")
            .setAutoCancel(true)
            .build()
    }
    // id 不变,则只会弹出一个通知,后面的通知会替代上一次的
    manager.notify(1, notification)
}

自定义通知栏布局

// 自定义通知栏布局
val remoteViews = RemoteViews(packageName, R.layout.layout_notification)
// 设置显示内容
remoteViews.setTextViewText(R.id.tv_title, "This is title.")
remoteViews.setTextViewText(R.id.tv_content, "This is content.")
remoteViews.setImageViewResource(R.id.iv_icon, R.drawable.ic_launcher_foreground)
// 设置点击事件
remoteViews.setOnClickPendingIntent(R.id.rl_open_activity, pendingIntent)

// 设置自定义布局
notification.setCustomContentView(remoteViews) 

实现一个简单的桌面小部件

1. 创建布局文件

路径 res/layout/desktop_widget

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:id="@+id/ll_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/iv_icon"
        android:src="@mipmap/monkey"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>
2. 定义配置信息

路径 res/xml/appwidget_provider_info

<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:initialLayout="@layout/desktop_widget"
    android:minHeight="84dp"
    android:minWidth="84dp"
    android:updatePeriodMillis="864000">

</appwidget-provider>
3. 部件实现类
class MyAppWidgetProvider : AppWidgetProvider() {

    companion object {
        const val TAG = "MyAppWidgetProvider"
    }

    override fun onUpdate(
        context: Context,
        appWidgetManager: AppWidgetManager,
        appWidgetIds: IntArray,
    ) {
        super.onUpdate(context, appWidgetManager, appWidgetIds)
        Log.d(TAG, "onUpdate")

        val counter = appWidgetIds.size
        Log.d(TAG, "onUpdate counter = $counter")
        for (i in 0 until counter) {
            val appWidgetId = appWidgetIds[i]
            onWidgetUpdate(context, appWidgetManager, appWidgetId)
        }
    }

    private fun onWidgetUpdate(
        context: Context,
        appWidgetManager: AppWidgetManager,
        appWidgetId: Int,
    ) {
        Log.d(TAG, "onWidgetUpdate appWidgetId = $appWidgetId")
        val remoteViews = RemoteViews(context.packageName, R.layout.desktop_widget)
        val pendingIntent = PendingIntent.getActivity(context, 0, Intent(context, DemoActivity::class.java), PendingIntent.FLAG_UPDATE_CURRENT)
        remoteViews.setOnClickPendingIntent(R.id.iv_icon, pendingIntent)
        appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
    }

}
4. 在清单文件中声明
<receiver
    android:name=".appwidget.MyAppWidgetProvider"
    android:exported="true">
    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/appwidget_provider_info" />
    <intent-filter>
        <!-- 必须添加,否则不显示在小部件列表 -->
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
</receiver>