Android 桌面小组件 AppWidgetProvider
廢話
桌面小組件,絕對是小程序中的小程序,說白了就是任何復雜一丁點的操作都不適合做成桌面小組件。
所以這里采用的演示的例子,就只有一個白色圓角背景,外加一個文本框,顯示文字。
小組件的教程網上一搜一大堆,所以我這里主要就是介紹一些坑的地方,跟大致處理流程,具體細節還得看其他大神的騷操作。
預覽圖
注意事項
1、UI 適配
小組件的寬高是可以支持用戶自行調整的,只需簡單的設置最低寬高,但是可調整的最小粒度是根據手機的 icon 為標準,這樣就會導致一個比較難處理的點。
如果手機是 4x 布局的,即一行可以顯示 4 個 APP 圖標,那調節的粒度就是 90dp(理想情況下),實際情況的話,還得考慮小組件的固定邊距,這個邊距,不同牌子的手機可能還不一樣。
如果手機是 5x 布局的,即一行可以顯示 5 個 APP 圖標……
解決方案:小組件數量無限制,用戶也是用就加不用就不加,所以解決方案就簡單粗暴一點,你能想到的適配尺寸,每種尺寸搞一個,用戶自己選擇合適的尺寸就好。大、中、小、大中、中小、微小、超大等亂七八糟的,全部一股腦上。
2、更新時間
更新時間為主動更新和定時更新;
主動更新:即在 APP 中可以動態更新這個桌面小組件,這種情況更新沒有時間限制。
定時更新:小組件需要展示的數據可能已經發生了變化,但是 APP 已經被系統殺死了,無法主動更新數據,就會導致小組件展示的數據可能是已過期的或者是舊的,這時候就可以用到小組件的定時更新功能,但是這個定時更新有一個限制,基于省電邏輯,最快的更新周期為 30 分鐘。(如果是再 onUpdate 方法中寫個定時器定時更新,抱歉,不行,會被系統殺死,殺死之后小組件不會消失,而是一直顯示最后一次更新時候的狀態,直到下一次更新數據,類似于電子水墨屏的邏輯。)
3、點擊事件
我這里圖省事,只用了最簡單的,點擊整個小組件直接調起 APP,所以其他復雜一點的點擊事件的處理方法我就不懂了。
點擊跳轉頁面需要用到 PendingIntent,這玩意的 Flag 有很多種模式,具體可以查看文章底部的參考文檔,坑就坑在這個 Flag,31 之后的系統有改動,會報錯,所以 31 的系統需要用 PendingIntent.FLAG_IMMUTABLE,具體看代碼。
4、調起 APP
通過 PendingIntent 就可以直接調起 APP 的相關頁面,不過這里也有坑,假設你 APP 的啟動頁面是 MainActivity 頁面,點擊小組件你就讓它跳轉到 MainActivity 頁面走正常的 APP 啟動流程,就等同于是點擊小組件就能啟動 APP,哪怕 APP 被殺死了,也不影響啟動(聽著好像沒毛病)。
坑就坑在于,通過這種方式打開的 APP,他…… 他不走 Application 類,也就是你如果是在 Application 中初始化了某些東西,但是 APP 已經被系統殺死了,這時候你再點擊小組件啟動 APP,就會發現,好多組件用不了(沒初始化)。
我這里圖省事的做法就是把 Application 的所有需要初始化的東西都放 MainActivity 里面初始化了(但是 Content 還是用的 Application,而不是用 MainActivity)。
開搞
需求
一個小組件,居中顯示一個文本,點擊可進入 APP
1、準備一個布局文件 widget_test.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/lly_bg"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/bg_test"android:orientation="vertical"><TextViewandroid:id="@+id/tv_test"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="測試" /></LinearLayout>附上背景文件 bg_test.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"><!-- 背景色--><solid android:color="#ffffff" /><!-- 圓角--><corners android:radius="20dp" /> </shape>2、res 文件夾下新建一個 xml 文件夾,新建 app_widget_test.xml 配置文件
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"android:minWidth="360dp"android:minHeight="120dp"android:updatePeriodMillis="1800000"android:previewImage="@drawable/ic_widget_big"android:initialLayout="@layout/widget_test"android:resizeMode="horizontal|vertical"android:widgetCategory="home_screen"> </appwidget-provider>minWidth、minHeight? ? 最小寬高
updatePeriodMillis? ? 更新周期
previewImage? ? 添加桌面小組件時候顯示的預覽圖
initialLayout? ? 布局
widgetCategory? ??home_screen 是代表的桌面小組件,其他參數自行百度了
3、合適的地方新建一個 TestAppWidget 類,繼承 AppWidgetProvider
/*** 桌面小組件** @author Admin*/ public class TestAppWidget extends AppWidgetProvider {/*** 每次窗口小部件被更新都調用一次該方法(創建、時間到更新周期都會調起這里)*/@Overridepublic void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {super.onUpdate(context, appWidgetManager, appWidgetIds);//更新數據updateWidgetView(context, UUID.randomUUID().toString());}/*** 接收窗口小部件點擊時發送的廣播*/@Overridepublic void onReceive(Context context, Intent intent) {super.onReceive(context, intent);}/*** 每刪除一次窗口小部件就調用一次*/@Overridepublic void onDeleted(Context context, int[] appWidgetIds) {super.onDeleted(context, appWidgetIds);}/*** 當最后一個該窗口小部件刪除時調用該方法*/@Overridepublic void onDisabled(Context context) {super.onDisabled(context);}/*** 當該窗口小部件第一次添加到桌面時調用該方法*/@Overridepublic void onEnabled(Context context) {super.onEnabled(context);}/*** 當小部件大小改變時*/@Overridepublic void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);}/*** 當小部件從備份恢復時調用該方法*/@Overridepublic void onRestored(Context context, int[] oldWidgetIds, int[] newWidgetIds) {super.onRestored(context, oldWidgetIds, newWidgetIds);ALog.e("當小部件從備份恢復時調用該方法");}/*** 更新桌面小組件數據用,APP中也可以在任意地方傳入任意數據進來主動更新小組件數據*/public static void updateWidgetView(Context context, String str) {//初始化RemoteViewsComponentName componentName = new ComponentName(context, TestAppWidget.class);RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_test);//點擊事件,點擊跳轉到MainActivity頁面Intent startActivityIntent = new Intent(context, MainActivity.class);PendingIntent processInfoIntent;if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {//31,Android11以上系統processInfoIntent = PendingIntent.getActivity(context, 0, startActivityIntent, PendingIntent.FLAG_IMMUTABLE);} else {processInfoIntent = PendingIntent.getActivity(context, 0, startActivityIntent, PendingIntent.FLAG_ONE_SHOT);}remoteViews.setOnClickPendingIntent(R.id.lly_bg, processInfoIntent);//更新文本數據remoteViews.setTextViewText(R.id.tv_test, str);//開始更新視圖AppWidgetManager awm = AppWidgetManager.getInstance(context);awm.updateAppWidget(componentName, remoteViews);}}4、AndroidManifest.xml 中配置小組件,與 Activity 頁面同級
<receiverandroid:name=".TestAppWidget"android:exported="false"><intent-filter><action android:name="android.appwidget.action.APPWIDGET_UPDATE" /></intent-filter><meta-dataandroid:name="android.appwidget.provider"android:resource="@xml/app_widget_test" /></receiver>參考文章
https://blog.csdn.net/weixin_43499030/article/details/90264915
https://blog.csdn.net/weixin_43499030/article/details/90264915
總結
以上是生活随笔為你收集整理的Android 桌面小组件 AppWidgetProvider的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: html5怎么获取当前星期几,javas
- 下一篇: 冗余索引