widget点击无法响应,Widget开发中遇到的坑

273 篇文章 4 订阅
251 篇文章 3 订阅

1.在Manifest文件中声明

​
android:name="android.appwidget.provider"

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

​

这个就相当于一个广播接收者,然后android:name属性指定在第四步的时候创建的文件名

android:resource="@xml/example_appwidget_info"/>是widget的配置文件

2.添加Widget配置信息

在项目的 res/xml/ 目录下。如果没有xml目录,需要新建一个

android:minWidth="40dp"

android:minHeight="40dp"

android:updatePeriodMillis="86400000"

android:previewImage="@drawable/preview"

android:initialLayout="@layout/example_appwidget"

android:resizeMode="horizontal|vertical"

android:widgetCategory="home_screen">

initialLayout是widget的布局文件

previewImage就是widget的预览效果

3.新建一个appwidget_layout文件

android:layout_width="match_parent"

android:layout_height="match_parent"

android:padding="@dimen/widget_margin">



android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="horizontal"

android:background="@drawable/my_widget_background">

…

4.新建一个AppWidgetProvider类

这个类其实是继承至广播接收者的

public class AppWidgetProvider extends BroadcastReceiver {

然后呢,我们一般只需要用到onUpdate()方法,这个方法的更新时间,是你在example_appwidget_info配置文件中设置的android:updatePeriodMillis属性决定的,这个地方有个坑,稍候再说

public class GoldWidgetProvider extends AppWidgetProvider {

public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

final int N = appWidgetIds.length;

for (int i=0; i

int appWidgetId = appWidgetIds[i];

Intent intent = new Intent(context, ExampleActivity.class);

PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);

views.setOnClickPendingIntent(R.id.button, pendingIntent);

widget

appWidgetManager.updateAppWidget(appWidgetId, views);

}

}

}

5.开发中的一些坑

1. updateMillies更新时间低于30分钟,系统默认为30分钟。如果想要自己更新widget,将这个值设置为0,然后自己开timer或者通过广播去更新。我是通过广播去更新的

// 重写OnReceiver方法

@Override

public void onReceive(Context context, Intent intent) {

super.onReceive(context, intent);

String action = intent.getAction();

// 需要在Manifest中注册这个Action

if (ACTION_UPDATE_WIDGET.equals(action)) { // update widget

RemoteViews views = getRemoteViews(context, null);

ComponentName name = new ComponentName(context, GoldWidgetProvider.class);

AppWidgetManager.getInstance(context).updateAppWidget(name, views);

}else if (ACTION_CLICK_UPDATE_WIDGET.equals(action)){

RemoteViews remoteViews = getRemoteViews(context, "正在刷新...");

ComponentName name = new ComponentName(context, GoldWidgetProvider.class);

AppWidgetManager.getInstance(context).updateAppWidget(name, remoteViews);

Intent goldPrice = new Intent(context, GoldPriceService.class);

context.startService(goldPrice);

}

}

public static RemoteViews getRemoteViews(Context context, String updating) {

RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.goldwidget);

//1,设置金价

if (TextUtils.isEmpty(updating)) {

String buyGoldPrice = ShaPreUtils.getBuyGoldPrice(context);

views.setTextViewText(R.id.widget_tv_goldprice, buyGoldPrice);

} else {

views.setTextViewText(R.id.widget_tv_goldprice, updating);

}

//2,设置持有金

if (GoldApplication.getInstance().isLogined()) {

String total = GoldApplication.getInstance().getUserLoginInfo().getAccountInfo().getTotal();

ShaPreUtils.putTotalGold(context,total);

views.setTextViewText(R.id.widget_tv_total, total);

views.setViewVisibility(R.id.widget_total_layout,View.VISIBLE);

}else if (TextUtils.isEmpty(ShaPreUtils.getTotalGold(context))){

views.setViewVisibility(R.id.widget_total_layout,View.GONE);

}else{

views.setViewVisibility(R.id.widget_total_layout,View.VISIBLE);

views.setTextViewText(R.id.widget_tv_total,ShaPreUtils.getTotalGold(context));

}

//3,点击事件

Intent toStartActivity = new Intent(context, AppStart.class);

views.setOnClickPendingIntent(R.id.widget_to_app, PendingIntent.getActivity(context, 0, toStartActivity, 0));

// 买金的时候发送一个广播,当前类接收

Intent to_buygold = new Intent(context, GoldWidgetProvider.class);

to_buygold.setAction(ACTION_TO_BUYGOLD);

views.setOnClickPendingIntent(R.id.widget_to_buygold, PendingIntent.getBroadcast(context, 0,to_buygold , 0));

// 主动刷新广播

Intent layout = new Intent(context, GoldWidgetProvider.class);

layout.setAction(ACTION_CLICK_UPDATE_WIDGET);

views.setOnClickPendingIntent(R.id.widget_layout, PendingIntent.getBroadcast(context, 0, layout, 0));

return views;

}

2.appwidget_info里的android:configure属性

一开始的时候照着官方文档在appwidget_info xml文件里设置了这个属性,在添加到桌面上的时候总是不成功,将这个属性去掉就可以了,不知道这个属性具体怎么用,有知道的麻烦告诉我一声,感激不尽...

查看官方文档法相这个属性是给widget设置一个config,具体怎么使用可以查看官方文档

3.appWidgetManager更新的两个方法

updateAppWidget(int[] appWidgetIds, RemoteViews views)

updateAppWidget(ComponentName provider, RemoteViews views) {

updateAppWidget(int[] appWidgetIds, RemoteViews views)代码如下:

// 更新 widget 的广播对应的action

private final String ACTION_UPDATE_ALL = "com.skywang.widget.UPDATE_ALL";

// 保存 widget 的id的HashSet,每新建一个 widget 都会为该 widget 分配一个 id。

private static Set idsSet = new HashSet();

@Override

public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {

Log.d(TAG, "onUpdate(): appWidgetIds.length="+appWidgetIds.length);

// 每次 widget 被创建时,对应的将widget的id添加到set中

for (int appWidgetId : appWidgetIds) {

idsSet.add(Integer.valueOf(appWidgetId));

}

}

@Override

public void onDeleted(Context context, int[] appWidgetIds) {

Log.d(TAG, "onDeleted(): appWidgetIds.length="+appWidgetIds.length);

// 当 widget 被删除时,对应的删除set中保存的widget的id

for (int appWidgetId : appWidgetIds) {

idsSet.remove(Integer.valueOf(appWidgetId));

}

super.onDeleted(context, appWidgetIds);

}

//接收广播的回调函数

@Override

public void onReceive(Context context, Intent intent) {

final String action = intent.getAction();

if (ACTION_UPDATE_ALL.equals(action)) {

// “更新”广播

updateAllAppWidgets(context, AppWidgetManager.getInstance(context), idsSet);

}

}

// 更新所有的 widget

private void updateAllAppWidgets(Context context, AppWidgetManager appWidgetManager, Set set) {

Log.d(TAG, "updateAllAppWidgets(): size="+set.size());

// widget 的id

int appID;

// 迭代器,用于遍历所有保存的widget的id

Iterator it = set.iterator();

while (it.hasNext()) {

appID = ((Integer)it.next()).intValue();

if (DEBUG) Log.d(TAG, "onUpdate(): index="+index);

// 获取 example_appwidget.xml 对应的RemoteViews

RemoteViews remoteView = getRemoteViews(context,"");

// 更新 widget

appWidgetManager.updateAppWidget(appID, remoteView);

}

}

上面这些代码有个隐患,在应用退出后,或是被第三方软件杀死,点击桌面widget就不会更新了。原因是updateid我是用static的set集合保存的,应用退出后,这个set集合就被清空了,后面又换成了updateAppWidget(ComponentName)方法后就好了。

RemoteViews views = getRemoteViews(context, null);

ComponentName name = new ComponentName(context, GoldWidgetProvider.class);

AppWidgetManager.getInstance(context).updateAppWidget(name, views);

4.在用setOnClickPendingIntent()方法设置点击事件发送Broadcast时,不能直接new Intent(acton)

Intent intent = new Intent(ACTION_CLICK_UPDATE_WIDGET);

views.setOnClickPendingIntent(R.id.widget_layout, PendingIntent.getBroadcast(context, 0, intent, 0));

上面这种写法在应用退出后在有些手机上收不到广播,然后换成下面这种写法

Intent layout = new Intent(context, GoldWidgetProvider.class);

layout.setAction(ACTION_CLICK_UPDATE_WIDGET);

views.setOnClickPendingIntent(R.id.widget_layout, PendingIntent.getBroadcast(context, 0, layout, 0));

转自:android widget点击无法响应,Widget开发中遇到的坑_weixin_42421284的博客-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值