android 小部件会起冲突吗,Android小部件Widget开发过程中的坑和总结

@

概述

官方参考

效果图

放张效果图,这是我玩的桌面 app 文件夹

e96b3123f70554993a902e72d1b892ba.png

AndroidManifest.xml

Receiver

切记里面的字母不要弄错,最好复制粘贴再修改相对应自定义的地方就好,一个字母的错误搞了我一天,吐血

android:name="android.appwidget.provider"

android:resource="@xml/widget_desktop_options" />

Service

如果小部件中使用到了列表项如 ListView,GridView 等,在绑定数据时需要使用 RemoteViewsService 并提供一个 RemoteViewsFactory 实例来填充数据 而非 Adapter

再提,这里面一定不能敲错字母,特别是那个 permission 也一定要有,不然无法绑定数据

android:name=".desktop.DesktopViewsService"

android:permission="android.permission.BIND_REMOTEVIEWS" />

Options

res/xml/

widget_desktop_options.xml

android:minWidth="40dp"

android:minHeight="40dp"

android:initialLayout="@layout/widget_desktop"

android:resizeMode="horizontal|vertical"

android:widgetCategory="home_screen">

常用参数

Size

尺寸大小最终以单元格数据来显示,但定义时为 dp

单元格数转换基本工式 size = 70 x cells - 30

如:1格 = 70 x 1 - 30 = 40dp

最小尺寸定义时最好不要超过 4 个单元格就是 250dp

updatePeriodMillis

更新时间毫秒数,即间隔多少时间呼叫一次 onUpdate() 方法

initialLayout

加载布局文件

Using App Widgets with Collections

小部件中使用列表项

官方参考

AppWidgetProvider

public class DesktopWidget extends AppWidgetProvider {

public String ACTION_START_ACTIVITY = "STARTACTIVITYACTION";

public DesktopWidget() {

super();

}

//当接收到广播的时候会被调用

//onUpdate, onEnabled等时都会发送广播

@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

//第一个参数为要绑定的widget的Gridview的id,第二个参数为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方式测试不成功,改用广播的方式进行发送并执行事件

//此处不能是空的Intent 否则广播无法发送

//定义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);

}

//被添加或者更改大小时调用,在这个方法中可以选择性的根据界面大小显示或隐藏某些控件

@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() 加载数据, getViewAt() 方法返回布局绑定数据

public class DesktopViewsFactory implements RemoteViewsService.RemoteViewsFactory {

private Context mContext;

private int mAppWidgetId;

private List lstApps = new ArrayList();

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() {

//这里我加了重新加载数据的调用,用于更新小部件的列表内容

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

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值