Android小部件Widget開發(fā)過程中的坑和問題小結
概述
官方參考
效果圖
放張效果圖,這是我玩的桌面 app 文件夾

AndroidManifest.xml
Receiver
切記里面的字母不要弄錯,最好復制粘貼再修改相對應自定義的地方就好,一個字母的錯誤搞了我一天,吐血
<receiver android:name=".desktop.DesktopWidget"> <meta-data android:name="android.appwidget.provider" android:resource="@xml/widget_desktop_options" /> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> </receiver>
Service
如果小部件中使用到了列表項如 ListView,GridView 等,在綁定數(shù)據(jù)時需要使用 RemoteViewsService 并提供一個 RemoteViewsFactory 實例來填充數(shù)據(jù) 而非 Adapter
再提,這里面一定不能敲錯字母,特別是那個 permission 也一定要有,不然無法綁定數(shù)據(jù)
<service android:name=".desktop.DesktopViewsService" android:permission="android.permission.BIND_REMOTEVIEWS" />
Options
res/xml/
widget_desktop_options.xml
<?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:minWidth="40dp" android:minHeight="40dp" android:initialLayout="@layout/widget_desktop" android:resizeMode="horizontal|vertical" android:widgetCategory="home_screen"> </appwidget-provider>
常用參數(shù)
Size
- 尺寸大小最終以單元格數(shù)據(jù)來顯示,但定義時為 dp
- 單元格數(shù)轉換基本工式 size = 70 x cells - 30
- 如:1格 = 70 x 1 - 30 = 40dp
- 最小尺寸定義時最好不要超過 4 個單元格就是 250dp
updatePeriodMillis
更新時間毫秒數(shù),即間隔多少時間呼叫一次 onUpdate() 方法
initialLayout
加載布局文件
Using App Widgets with Collections
小部件中使用列表項
官方參考
AppWidgetProvider
public class DesktopWidget extends AppWidgetProvider {
public String ACTION_START_ACTIVITY = "STARTACTIVITYACTION";
public DesktopWidget() {
super();
}
//當接收到廣播的時候會被調用
//onUpdate, onEnabled等時都會發(fā)送廣播
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
pub.log("onReceive:" + intent.getAction());
if (intent.getAction().equals(ACTION_START_ACTIVITY)) {
String strPackage = intent.getStringExtra("app_package");
Intent appIntent = context.getPackageManager().getLaunchIntentForPackage(strPackage);
pub.log(appIntent.getPackage());
if (appIntent != null) {
appIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
pub.log("start activity");
context.startActivity(appIntent);
pub.log("finish");
}
}
}
//被添加或者被更新時調用
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
super.onUpdate(context, appWidgetManager, appWidgetIds);
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
private void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {
pub.log("onUpdate:" + appWidgetId);
// Construct the RemoteViews object
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_desktop);
//設定小部件上 TextView 值
//views.setTextViewText(R.id.tv_widget_desktop_title, "ZGTools");
//setRemoteAdapter設定Listivew,Gridview等復雜布局的adapter
//第一個參數(shù)為要綁定的widget的Gridview的id,第二個參數(shù)為RemoteViewsService的intent
Intent intent = new Intent(context, DesktopViewsService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
views.setRemoteAdapter(R.id.gv_app_group, intent);
//綁定 item 的定點事件
//Activity方式測試不成功,改用廣播的方式進行發(fā)送并執(zhí)行事件
//此處不能是空的Intent 否則廣播無法發(fā)送
//定義Intent事件模板,相當于公用設定,再在fillIntent里面設定具體的 extra 值
Intent templateIntent = new Intent(context, DesktopWidget.class);
templateIntent.setAction(ACTION_START_ACTIVITY);
templateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
templateIntent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, appWidgetId, templateIntent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setPendingIntentTemplate(R.id.gv_app_group, pendingIntent);
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
//被添加或者更改大小時調用,在這個方法中可以選擇性的根據(jù)界面大小顯示或隱藏某些控件
@Override
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) {
super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions);
updateAppWidget(context, appWidgetManager, appWidgetId);
}
@Override
public void onEnabled(Context context) {
super.onEnabled(context);
// Enter relevant functionality for when the first widget is created
}
@Override
public void onDisabled(Context context) {
super.onDisabled(context);
// Enter relevant functionality for when the last widget is disabled
}
}
RemoteViewsService
public class DesktopViewsService extends RemoteViewsService {
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new DesktopViewsFactory(this, intent);
}
}
RemoteViewsFactory
類型于 BaseAdapter,重點是 onCreate() 加載數(shù)據(jù), getViewAt() 方法返回布局綁定數(shù)據(jù)
public class DesktopViewsFactory implements RemoteViewsService.RemoteViewsFactory {
private Context mContext;
private int mAppWidgetId;
private List<AppPackage> lstApps = new ArrayList<AppPackage>();
public DesktopViewsFactory(Context context, Intent intent){
this.mContext = context;
this.mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
}
@Override
public void onCreate() {
DesktopDbHelper dbHelper = new DesktopDbHelper(mContext);
SQLiteDatabase db = dbHelper.getReadableDatabase();
String strSql = "Select * from tb_app";
try {
Cursor cursor = db.rawQuery(strSql, null);
if (cursor != null && cursor.getCount() > 0) {
lstApps.clear();
while (cursor.moveToNext()) {
byte[] blob = cursor.getBlob(cursor.getColumnIndex("app_icon"));
Bitmap bmpIcon = BitmapFactory.decodeByteArray(blob, 0, blob.length);
String strLabel = cursor.getString(cursor.getColumnIndex("app_label"));
String strPackage = cursor.getString(cursor.getColumnIndex("app_package"));
lstApps.add(new AppPackage(strLabel, strPackage, bmpIcon));
}
}
if (cursor != null) {
cursor.close();
}
} catch (Exception e) {
db.close();
e.printStackTrace();
}
db.close();
}
@Override
public void onDataSetChanged() {
//這里我加了重新加載數(shù)據(jù)的調用,用于更新小部件的列表內容
onCreate();
}
@Override
public void onDestroy() {}
@Override
public int getCount() {return 0;}
@Override
public RemoteViews getViewAt(int i) {
if (i < 0 || i >= lstApps.size()) return null;
//Construct a remote views item based on the app widget item XML file
RemoteViews views = new RemoteViews(mContext.getPackageName(), R.layout.widget_desktop_item);
views.setTextViewText(R.id.tv_widget_desktop_label, lstApps.get(i).getAppLabel());
views.setImageViewBitmap(R.id.iv_widget_desktop_icon, lstApps.get(i).getAppIcon());
Intent intent = new Intent();
Bundle bundle = new Bundle();
bundle.putString("app_package", lstApps.get(i).getAppPackage());
intent.putExtras(bundle);
views.setOnClickFillInIntent(R.id.iv_widget_desktop_icon, intent);
views.setOnClickFillInIntent(R.id.tv_widget_desktop_label, intent);
return views;
}
@Override
public RemoteViews getLoadingView() { return null;}
@Override
public int getViewTypeCount() {return 0;}
@Override
public long getItemId(int i) { return 0;}
@Override
public boolean hasStableIds() { return false; }
}
DesktopActivity
//更新widget布局
private void updateWidget(){
AppWidgetManager widgetManager = AppWidgetManager.getInstance(this);
ComponentName componentName = new ComponentName(this, DesktopWidget.class);
int[] ids = widgetManager.getAppWidgetIds(componentName);
widgetManager.notifyAppWidgetViewDataChanged(ids, R.id.gv_app_group);
}
總結
到此這篇關于Android小部件Widget開發(fā)過程中的坑和總結的文章就介紹到這了,更多相關Android小部件Widget內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Android基于Glide v4.x的圖片加載進度監(jiān)聽
本篇文章主要介紹了基于Glide v4.x的圖片加載進度監(jiān)聽的示例代碼,具有一定的參考價值,有興趣的可以了解一下2017-08-08
Android Fragment 和 FragmentManager 的代碼分析
這篇文章主要介紹了Android Fragment 和 FragmentManager 的代碼分析,非常不錯,具有參考借鑒價值,需要的的朋友參考下吧2017-01-01
Android ScrollView實現(xiàn)反彈效果的實例
這篇文章主要介紹了 Android ScrollView實現(xiàn)反彈效果的實例的相關資料,這里自定義scrollview 并實現(xiàn)反彈效果,需要的朋友可以參考下2017-07-07
解決android Listview的item中最外層Margin失效的問題
下面小編就為大家?guī)硪黄鉀Qandroid Listview的item中最外層Margin失效的問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04
Android實現(xiàn)檢查并下載APK更新、安裝APK及獲取網(wǎng)絡信息的方法
這篇文章主要介紹了Android實現(xiàn)檢查并下載APK更新、安裝APK及獲取網(wǎng)絡信息的方法,很實用的功能,需要的朋友可以參考下2014-07-07

