Android点击桌面小部件拉起WorkManager(CoroutineWorker)后台任务并发送Notification通知到前台通知栏,kotlin(3)
1、构建桌面小部件
在AndroidManifest.xml的application里面添加:
<receiver
android:name=".AppWidget"
android:exported="true">
<intent-filter>
<action android:name="action_click" />
</intent-filter>
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/appwidget" />
</receiver>
在res/xml/下面添加文件appwidget.xml:
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/appwidget_layout"
android:minHeight="20dp"
android:minWidth="200dp"
android:previewImage="@mipmap/ic_launcher"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="0"
android:widgetCategory="home_screen" >
</appwidget-provider>
在res/layout/下面添加appwidget_layout.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/holo_red_light">
<Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:background="@color/design_default_color_surface"
android:text="点击我" />
</RelativeLayout>
实现桌面小部件的上层AppWidget.kt文件:
import android.app.PendingIntent
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.content.Intent
import android.util.Log
import android.widget.RemoteViews
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.OutOfQuotaPolicy
import androidx.work.WorkManager
class AppWidget : AppWidgetProvider() {
val ACTION_CLICK = "action_click"
/**
* 接收广播事件
*/
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
Log.d(TAG, "onReceive")
if (intent?.action == ACTION_CLICK) {
Log.d(TAG, "点击小部件")
val request = OneTimeWorkRequestBuilder<ForegroundWorker>()
.setExpedited(OutOfQuotaPolicy.DROP_WORK_REQUEST)
.build()
WorkManager.getInstance(context)
.enqueue(request)
Log.d(TAG, "启动任务")
}
}
/**
* 首次在桌面安装小部件时候调用, 将小部件上面的view组件和事件绑定。
*/
override fun onUpdate(
context: Context?,
appWidgetManager: AppWidgetManager?,
appWidgetIds: IntArray?
) {
super.onUpdate(context, appWidgetManager, appWidgetIds)
Log.d(TAG, "onUpdate")
val intent = Intent(context, AppWidget::class.java)
intent.setAction(ACTION_CLICK)
val pendingIntent =
PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE)
// 小部件在桌面的布局
val remoteViews = RemoteViews(context?.packageName, R.layout.appwidget_layout)
// 事件
remoteViews.setOnClickPendingIntent(R.id.btn, pendingIntent);
// 更新AppWidget
appWidgetManager?.updateAppWidget(appWidgetIds, remoteViews);
}
/**
* 删除AppWidget
*/
override fun onDeleted(context: Context, appWidgetIds: IntArray) {
super.onDeleted(context, appWidgetIds)
Log.d(TAG, "onDeleted")
}
override fun onDisabled(context: Context) {
super.onDisabled(context)
Log.d(TAG, "onDisabled")
}
/**
* AppWidget首次创建调用
*/
override fun onEnabled(context: Context) {
super.onEnabled(context)
Log.d(TAG, "onEnabled")
}
}
2、后台的任务,以及往通知栏发送通知。
CoroutineWorker在后台往通知栏发送通知的代码文件MyTask.kt:
import android.R
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Context
import android.graphics.Color
import android.util.Log
import androidx.core.app.NotificationCompat
import androidx.work.CoroutineWorker
import androidx.work.ForegroundInfo
import androidx.work.WorkerParameters
fun notification(context: Context, s: String): Notification {
var channelId = createNotificationChannel(context, "com.fly", "Foreground_Service") ?: ""
return NotificationCompat.Builder(context, channelId)
.setOngoing(true)
.setSmallIcon(R.drawable.ic_notification_overlay)
.setContentTitle("我的标题")
.setContentText(s)
.setPriority(NotificationCompat.PRIORITY_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build()
}
private fun createNotificationChannel(
context: Context,
channelId: String,
channelName: String
): String? {
val channel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_NONE)
channel.lightColor = Color.BLUE
channel.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
val service = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
service?.createNotificationChannel(channel)
return channelId
}
class ForegroundWorker(private val context: Context, parameters: WorkerParameters) :
CoroutineWorker(context, parameters) {
override suspend fun getForegroundInfo(): ForegroundInfo {
return ForegroundInfo(1, notification(context, "zhangphil"))
}
override suspend fun doWork(): Result {
setForeground(getForegroundInfo())
repeat(5) {
Thread.sleep(1000)
Log.d(TAG, "do work - " + it)
}
return Result.success()
}
}
MainActivity.kt,不需要做任何事情:
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
val TAG:String = "zhangphil"
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d(TAG, "onCreate")
}
override fun onStart() {
super.onStart()
Log.d(TAG, "前台")
}
override fun onStop() {
super.onStop()
Log.d(TAG, "后台")
}
}
在AndroidManifest.xml添加权限并设置程序允许通知:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />