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) }
 
                    