Widget基本使用
-
编写布局文件
src/main/res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@color/gray" android:padding="@dimen/widget_margin" tools:context=".component.MainProcessActivity"> <TextView android:id="@+id/tvService" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:text="Service" android:textSize="10sp" android:textStyle="bold" /> <TextView android:id="@+id/tvServiceFromGetBroadcast" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/tvService" android:text="getBroadcast()收到广播后创建" android:textSize="10sp" /> <LinearLayout android:id="@+id/llSerFromBroadcast" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/tvServiceFromGetBroadcast" android:orientation="horizontal"> <Button android:id="@+id/btnSerWidgetFromBroad" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Widget进程" android:textSize="10sp" /> <Button android:id="@+id/btnSerMainFromBroad" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="2dp" android:text="主进程" android:textSize="10sp" /> </LinearLayout> </RelativeLayout>
-
编写AppWidgetProviderInfo
src/main/res/xml/widget_test_info.xml
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:initialLayout="@layout/activity_main" android:minWidth="150dp" android:minHeight="300dp" android:previewImage="@drawable/preview" android:resizeMode="horizontal|vertical" android:updatePeriodMillis="2000" android:widgetCategory="home_screen" > </appwidget-provider>
-
实现AppWidgetProvider
src/main/java/com/miui/widgettest/TestAppWidgetProvider.kt
class TestAppWidgetProvider : AppWidgetProvider() { override fun onUpdate( context: Context?, appWidgetManager: AppWidgetManager?, appWidgetIds: IntArray? ) { } override fun onReceive(context: Context?, intent: Intent?) { super.onReceive(context, intent) Log.i("TAG", "onReceive: ${intent.toString()}") } }
-
在manifests清单中声明
src/main/AndroidManifest.xml
<receiver android:name="TestAppWidgetProvider"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_test_info" /> </receiver>
四大组件基本使用
Activity
相关知识查看Activity启动模式的文章
-
通信
第一个Activity:startActivityForResult()启动、onResult() 接收结果
第二个Activity: setResult()
Service
-
创建使用
-
实现IntentService
src/main/java/com/miui/widgettest/component/MainProcessService.kt
class MainProcessService : IntentService(MainProcessService::class.simpleName) { private val TAG = javaClass.simpleName override fun onHandleIntent(intent: Intent?) { Toast.makeText(this, "MainProcessService", Toast.LENGTH_SHORT).show() Log.i(TAG, "onHandleIntent: MainProcessService") } }
-
在清单文件中声明
<service android:name=".component.MainProcessService" />
-
使用
startService(Intent(context, MainProcessService::class.java))
-
-
生命周期
Broadcast
-
创建使用
-
定义广播Action常量
src/main/java/com/miui/widgettest/CONST.kt
package com.miui.widgettest interface CONST { interface ACTION { companion object { // 拉起 Activity const val MAIN_PROCESS_ACTIVITY_ACTION = "widgettest.broadcast.MAIN_PROCESS_ACTIVITY_ACTION" const val WIDGET_PROCESS_ACTIVITY_ACTION = "widgettest.broadcast.WIDGET_PROCESS_ACTIVITY_ACTION" // 使用 Provider const val MAIN_PROCESS_PROVIDER_ACTION = "widgettest.broadcast.MAIN_PROCESS_PROVIDER_ACTION" const val WIDGET_PROCESS_PROVIDER_ACTION = "widgettest.broadcast.WIDGET_PROCESS_PROVIDER_ACTION" // 启动 Service 广播 const val MAIN_PROCESS_SERVICE_ACTION = "widgettest.broadcast.MAIN_PROCESS_SERVICE_ACTION" const val WIDGET_PROCESS_SERVICE_ACTION = "widgettest.broadcast.WIDGET_PROCESS_SERVICE_ACTION" // 拉起 BroadcastReceiver const val MAIN_PROCESS_BROADCAST_RECEIVER_ACTION = "widgettest.broadcast.MAIN_PROCESS_BROADCAST_RECEIVER_ACTION" const val WIDGET_PROCESS_BROADCAST_RECEIVER_ACTION = "widgettest.broadcast.WIDGET_PROCESS_BROADCAST_RECEIVER_ACTION" // getBroadcast触发后再发起的广播 const val WIDGET_PROCESS_ACTION = "widgettest.broadcast.WIDGET_PROCESS_ACTION" const val MAIN_PROCESS_ACTION = "widgettest.broadcast.MAIN_PROCESS_ACTION" } } }
-
实现 BroadcastReceiver
class MainProcessBroadcastReceiver : BroadcastReceiver() { private val TAG = MainProcessBroadcastReceiver::class.simpleName override fun onReceive(context: Context?, intent: Intent?) { Log.i(TAG, "onReceive: ") Toast.makeText(context, "MainProcessBroadcastReceiver", Toast.LENGTH_SHORT).show() } }
-
注册广播
-
静态注册
<receiver android:name=".component.MainProcessBroadcastReceiver"> <intent-filter> <action android:name="widgettest.broadcast.MAIN_PROCESS_ACTION" /> </intent-filter> </receiver>
-
上下文注册
val br = MainProcessBroadcastReceiver() val intentFilter = IntentFilter(CONST.ACTION.MAIN_PROCESS_BROADCAST_RECEIVER_ACTION) registerReceiver(br, intentFilter)
-
-
发起广播
Android O之后广播Intent得指定ComponentName
val intentBroadcast = Intent(CONST.ACTION.MAIN_PROCESS_ACTION).apply { component = ComponentName( context!!.packageName, MainProcessBroadcastReceiver::class.java.name ) } context?.sendBroadcast(intentBroadcast)
-
ContentProvider
-
创建使用
-
实现 ContentProvider
private val TAG = MainProcessProvider::class.java.simpleName class MainProcessProvider : ContentProvider() { override fun onCreate(): Boolean { return true } override fun query( uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String? ): Cursor? { return null } override fun getType(uri: Uri): String? { return "image/jpeg" } override fun insert(uri: Uri, values: ContentValues?): Uri? { Log.i(TAG, "insert: $TAG") Toast.makeText(WidgetApplication.context, "MainProcessProvider", Toast.LENGTH_SHORT).show() return uri } override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int { return 1 } override fun update( uri: Uri, values: ContentValues?, selection: String?, selectionArgs: Array<out String>? ): Int { return 1 } }
-
在 清单中注册
<provider android:name=".component.MainProcessProvider" android:authorities="com.miui.widgettest" android:enabled="true" android:exported="true" android:permission="true" />
-
使用
// 通过ContentResolver 根据URI 向ContentProvider中插入数据 try { context?.contentResolver?.insert( Uri.parse("content://com.miui.widgettest/emmm"), ContentValues() ) } catch (e: Exception) { Log.e("TestAppWidgetProvider", " ${e.message}", e) }
-
Widget调用四大组件
都是在AppWidgetProvider里onUpdate设置好
直接调用
在添加Widget添加时直接设置好点击操作
-
Activity
appWidgetIds?.forEach { appWidgetId -> // 不同case的pendingIntent // 直接启动activity val mpActPendingIntent = Intent(context, MainProcessActivity::class.java).let { intent -> PendingIntent.getActivity(context, 0, intent, 0) } // 设置监听事件 val views: RemoteViews = RemoteViews( context?.packageName, R.layout.activity_main ).apply { // activity 监听器 setOnClickPendingIntent(R.id.btnActMainFromActivity, mpActPendingIntent) } appWidgetManager?.updateAppWidget(appWidgetId, views)
-
Service
跟Activity类似
val mpSerPendingIntent = Intent(context, MainProcessService::class.java).let { PendingIntent.getService(context, 0, it, 0) }
收到广播后调用
与直接调用不用, 这里都是getBroadcast方式收到广播后再调起
-
Activity
-
设置action常量
// 拉起 Activity const val MAIN_PROCESS_ACTIVITY_ACTION = "widgettest.broadcast.MAIN_PROCESS_ACTIVITY_ACTION" const val WIDGET_PROCESS_ACTIVITY_ACTION = "widgettest.broadcast.WIDGET_PROCESS_ACTIVITY_ACTION"
-
清单中 appWidgetProvider
添加action <receiver android:name="TestAppWidgetProvider"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> <action android:name="widgettest.broadcast.MAIN_PROCESS_ACTIVITY_ACTION" /> <action android:name="widgettest.broadcast.WIDGET_PROCESS_ACTIVITY_ACTION" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_test_info" /> </receiver>
-
AppWidgetProvider 设置广播触发与回调
src/main/java/com/miui/widgettest/TestAppWidgetProvider.kt
private fun getPendingIntent(context: Context?, action: String): PendingIntent { return Intent(action).apply { component = ComponentName( context!!.packageName, this@TestAppWidgetProvider::class.java.name ) }.let { PendingIntent.getBroadcast(context, 0, it, PendingIntent.FLAG_UPDATE_CURRENT) } } // onUpdate 方法里面设置 activity pendingIntent val mpActPiFromGetBroadcast = getPendingIntent(context, CONST.ACTION.MAIN_PROCESS_ACTIVITY_ACTION) setOnClickPendingIntent(R.id.btnActMainFromBroad, mpActPiFromGetBroadcast) // onReceive方法设置回调 when (intent?.action) { CONST.ACTION.MAIN_PROCESS_ACTIVITY_ACTION -> { context?.startActivity( Intent( context, MainProcessActivity::class.java ).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }) } }
-
-
Service
CONST.ACTION.MAIN_PROCESS_SERVICE_ACTION -> { context?.startService(Intent(context, MainProcessService::class.java)) }
-
Provider
CONST.ACTION.MAIN_PROCESS_PROVIDER_ACTION -> { // 通过ContentResolver 根据URI 向ContentProvider中插入数据 try { context?.contentResolver?.insert( Uri.parse("content://com.miui.widgettest/emmm"), ContentValues() ) } catch (e: Exception) { Log.e("TestAppWidgetProvider", " ${e.message}", e) } }
-
Broadcast Receiver
CONST.ACTION.MAIN_PROCESS_BROADCAST_RECEIVER_ACTION -> { val intentBroadcast = Intent(CONST.ACTION.MAIN_PROCESS_ACTION).apply { component = ComponentName( context!!.packageName, MainProcessBroadcastReceiver::class.java.name ) } context?.sendBroadcast(intentBroadcast) }