一个android应用向Home screen添加多个Widget
来源:互联网 发布:淘宝开店诈骗 编辑:程序博客网 时间:2024/05/21 19:31
如Twitter客户端或者HTC的日历应用,可以添加大小不同的Widget。此疑问。
原来如此简单,只是我原来不会罢了。
首先在AndroidManifest.xml中太假多个接收器:
- <receiver android:name="com.jftt.widget.MyWidgetProvider1" android:label="天气 4 x 1">
- <meta-data android:name="android.appwidget.provider"
- android:resource="@xml/my_widget1" />
- <intent-filter>
- <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
- </intent-filter>
- </receiver>
- <receiver android:name="com.jftt.widget.MyWidgetProvider" android:label="全部 4 x 2">
- <meta-data android:name="android.appwidget.provider"
- android:resource="@xml/my_widget" />
- <intent-filter>
- <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
- </intent-filter>
- </receiver>
- <receiver android:name="com.jftt.widget.MyWidgetProvider2" android:label="步数 4 x 1">
- <meta-data android:name="android.appwidget.provider"
- android:resource="@xml/my_widget2" />
- <intent-filter>
- <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
- </intent-filter>
- </receiver>
CreateWidget.java文件内容如下:
- package com.jftt.activity;
- import android.app.Activity;
- import android.appwidget.AppWidgetManager;
- import android.content.Intent;
- import android.os.Bundle;
- import android.util.Log;
- import com.jftt.widget.R;
- public class CreateWidget extends Activity {
- private static final String TAG = "CreateWidget";
- int mAppWidgetId;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Log.i(TAG, " on WidgetConf ... ");
- setResult(RESULT_CANCELED);
- // Find the widget id from the intent.
- Intent intent = getIntent();
- Bundle extras = intent.getExtras();
- if (extras != null) {
- mAppWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
- }
- // If they gave us an intent without the widget id, just bail.
- if (mAppWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
- finish();
- }
- // return OK
- Intent resultValue = new Intent();
- resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
- setResult(RESULT_OK, resultValue);
- finish();
- }
- }
MyWidgetProvider.java内容如下:
- package com.jftt.widget;
- import android.app.PendingIntent;
- import android.appwidget.AppWidgetManager;
- import android.appwidget.AppWidgetProvider;
- import android.content.ComponentName;
- import android.content.Context;
- import android.content.Intent;
- import android.content.pm.PackageManager;
- import android.util.Log;
- import android.view.View;
- import android.widget.RemoteViews;
- import com.jftt.activity.WidgetSetting;
- public class MyWidgetProvider extends AppWidgetProvider {
- private static final String TAG = "MyWidgetProvider";
- @Override
- public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
- super.onUpdate(context, appWidgetManager, appWidgetIds);
- Log.i(TAG, "onUpdate");
- final int N = appWidgetIds.length;
- for (int i = 0; i < N; i++) {
- int appWidgetId = appWidgetIds[i];
- Log.i(TAG, "this is [" + appWidgetId + "] onUpdate!");
- Intent intent = new Intent(context, WidgetSetting.class);
- PendingIntent pending = PendingIntent.getActivity(context, 0, intent, 0);
- Intent intent2 = new Intent(context, MyWidgetProvider.class);
- intent2.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
- Log.i(TAG, "appWidgetId "+appWidgetId);
- PendingIntent doubleClick = PendingIntent.getBroadcast(context, appWidgetId, intent2, PendingIntent.FLAG_UPDATE_CURRENT);
- RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
- remoteViews.setOnClickPendingIntent(R.id.pic5, pending);
- remoteViews.setOnClickPendingIntent(R.id.widget, doubleClick);
- appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
- }
- }
- @Override
- public void onDeleted(Context context, int[] appWidgetIds) {
- super.onDeleted(context, appWidgetIds);
- Log.i(TAG, "onDeleted");
- final int N = appWidgetIds.length;
- for (int i = 0; i < N; i++) {
- int appWidgetId = appWidgetIds[i];
- Log.i(TAG, "this is [" + appWidgetId + "] onDelete!");
- }
- }
- @Override
- public void onDisabled(Context context) {
- super.onDisabled(context);
- Log.i(TAG, "onDisabled");
- PackageManager pm = context.getPackageManager();
- pm.setComponentEnabledSetting(new ComponentName("com.jftt.widget", "com.jftt.widget.MyWidgetProvider"), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
- }
- @Override
- public void onEnabled(Context context) {
- super.onEnabled(context);
- Log.i(TAG, "onEnabled");
- PackageManager pm = context.getPackageManager();
- pm.setComponentEnabledSetting(new ComponentName("com.jftt.widget", "com.jftt.widget.MyWidgetProvider"), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
- }
- static long start = 0;
- @Override
- public void onReceive(Context context, Intent intent) {
- super.onReceive(context, intent);
- if ((System.currentTimeMillis() - start) < 500) {
- AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
- RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
- remoteViews.setViewVisibility(R.id.setting, View.VISIBLE);
- int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, 0);
- appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
- } else {
- start = System.currentTimeMillis();
- }
- }
- }
效果如图。
Android AppWidget 开发中PendingIntent传送数据丢失解决办法
AppWidget要向外部发送数据,可以把数据放在Intent里,再用intent对象生成一个PendingIntent对象,然后用RemoteViews的setOnClickPendingIntent绑定到相应控件上,具体代码如下:
1 2 3 4 5 6 7 8 9 10
- RemoteViews updateViews <SPAN style="COLOR: #339933">=</SPAN> <SPAN style="FONT-WEIGHT: bold; COLOR: #000000">new</SPAN> RemoteViews<SPAN style="COLOR: #009900">(</SPAN>context.<SPAN style="COLOR: #006633">getPackageName</SPAN><SPAN style="COLOR: #009900">(</SPAN><SPAN style="COLOR: #009900">)</SPAN>, R.<SPAN style="COLOR: #006633">layout</SPAN>.<SPAN style="COLOR: #006633">widget</SPAN><SPAN style="COLOR: #009900">)</SPAN><SPAN style="COLOR: #339933">;</SPAN> ComponentName thisWidget <SPAN style="COLOR: #339933">=</SPAN> <SPAN style="FONT-WEIGHT: bold; COLOR: #000000">new</SPAN> ComponentName<SPAN style="COLOR: #009900">(</SPAN>context,Widget.<SPAN style="FONT-WEIGHT: bold; COLOR: #000000">class</SPAN><SPAN style="COLOR: #009900">)</SPAN><SPAN style="COLOR: #339933">;</SPAN> AppWidgetManager manager <SPAN style="COLOR: #339933">=</SPAN> AppWidgetManager.<SPAN style="COLOR: #006633">getInstance</SPAN><SPAN style="COLOR: #009900">(</SPAN>context<SPAN style="COLOR: #009900">)</SPAN><SPAN style="COLOR: #339933">;</SPAN> Intent intent<SPAN style="COLOR: #339933">=</SPAN><SPAN style="FONT-WEIGHT: bold; COLOR: #000000">new</SPAN> Intent<SPAN style="COLOR: #009900">(</SPAN>context,Main.<SPAN style="FONT-WEIGHT: bold; COLOR: #000000">class</SPAN><SPAN style="COLOR: #009900">)</SPAN><SPAN style="COLOR: #339933">;</SPAN> Bundle extras<SPAN style="COLOR: #339933">=</SPAN><SPAN style="FONT-WEIGHT: bold; COLOR: #000000">new</SPAN> Bundle<SPAN style="COLOR: #009900">(</SPAN><SPAN style="COLOR: #009900">)</SPAN><SPAN style="COLOR: #339933">;</SPAN> extras.<SPAN style="COLOR: #006633">putInt</SPAN><SPAN style="COLOR: #009900">(</SPAN><SPAN style="COLOR: #0000ff">"appWidgetId"</SPAN>, appWidgetIds<SPAN style="COLOR: #009900">[</SPAN><SPAN style="COLOR: #cc66cc">0</SPAN><SPAN style="COLOR: #009900">]</SPAN><SPAN style="COLOR: #009900">)</SPAN><SPAN style="COLOR: #339933">;</SPAN> intent.<SPAN style="COLOR: #006633">putExtras</SPAN><SPAN style="COLOR: #009900">(</SPAN>extras<SPAN style="COLOR: #009900">)</SPAN><SPAN style="COLOR: #339933">;</SPAN> PendingIntent pendingIntent<SPAN style="COLOR: #339933">=</SPAN>PendingIntent.<SPAN style="COLOR: #006633">getActivity</SPAN><SPAN style="COLOR: #009900">(</SPAN>context,<SPAN style="COLOR: #cc66cc">0</SPAN>, intent,PendingIntent.0<SPAN style="COLOR: #009900">)</SPAN><SPAN style="COLOR: #339933">;</SPAN> updateViews.<SPAN style="COLOR: #006633">setOnClickPendingIntent</SPAN><SPAN style="COLOR: #009900">(</SPAN>R.<SPAN style="COLOR: #006633">id</SPAN>.<SPAN style="COLOR: #006633">abs</SPAN>,pendingIntent<SPAN style="COLOR: #009900">)</SPAN><SPAN style="COLOR: #339933">;</SPAN> manager.<SPAN style="COLOR: #006633">updateAppWidget</SPAN><SPAN style="COLOR: #009900">(</SPAN>thisWidget, updateViews<SPAN style="COLOR: #009900">)</SPAN><SPAN style="COLOR: #339933">;</SPAN>
RemoteViews updateViews = new RemoteViews(context.getPackageName(), R.layout.widget); ComponentName thisWidget = new ComponentName(context,Widget.class); AppWidgetManager manager = AppWidgetManager.getInstance(context); Intent intent=new Intent(context,Main.class); Bundle extras=new Bundle(); extras.putInt("appWidgetId", appWidgetIds[0]); intent.putExtras(extras); PendingIntent pendingIntent=PendingIntent.getActivity(context,0, intent,PendingIntent.0); updateViews.setOnClickPendingIntent(R.id.abs,pendingIntent); manager.updateAppWidget(thisWidget, updateViews);
网上的例子代码基本上是这样的,但是如果在启动的Activity接收Intent过来的数据,你会发现得到的Bundle其实是空的,也就是说,根本没有数据传过来。
这里我们需要改一下第8行代码,getActivity方法的最后一个参数是int flag,根据官方开发指南,这个值可以是FLAG_ONE_SHOT, FLAG_NO_CREATE, FLAG_CANCEL_CURRENT, FLAG_UPDATE_CURRENT
简单翻译一下:
int FLAG_CANCEL_CURRENT:如果该PendingIntent已经存在,则在生成新的之前取消当前的。
int FLAG_NO_CREATE:如果该PendingIntent不存在,直接返回null而不是创建一个PendingIntent.
int FLAG_ONE_SHOT:该PendingIntent只能用一次,在send()方法执行后,自动取消。
int FLAG_UPDATE_CURRENT:如果该PendingIntent已经存在,则用新传入的Intent更新当前的数据。
我们需要把最后一个参数改为PendingIntent.FLAG_UPDATE_CURRENT,这样在启动的Activity里就可以用接收Intent传送数据的方法正常接收。
AppWidget开发中主屏幕多个Widget,PendingIntent的处理(只能取到最后一个PendingIntent)
前面说到PendingIntent传送数据丢失解决办法,但是如果主屏幕上有多个Widget,而PendingIntent在不同的Widget有不同的Bundle参数时,你会发现,不管在哪个Widget上点击,启动的Activity或者Service接收到的参数都是最后一个Widget的,后面在添加PendingIntent时,把前面的PendingIntent也替换了。
其实解决方法很简单,还是如前文一样,修改getActivity方法的参数,不过这次改的是第二个参数,
1
- PendingIntent pendingIntent<SPAN style="COLOR: #339933">=</SPAN>PendingIntent.<SPAN style="COLOR: #006633">getActivity</SPAN><SPAN style="COLOR: #009900">(</SPAN>context,<SPAN style="COLOR: #cc66cc">0</SPAN>, intent,PendingIntent.<SPAN style="COLOR: #006633">FLAG_UPDATE_CURRENT</SPAN><SPAN style="COLOR: #009900">)</SPAN><SPAN style="COLOR: #339933">;</SPAN>
PendingIntent pendingIntent=PendingIntent.getActivity(context,0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
如上面的代码,第二个参数是固定的0,Android开发文档里称为request Code,英文原文为”Private request code for the sender”,直译为发送器的私有请求代码。其实这个int值就相当于PendingIntent的一个ID,PendingIntent会根据这个ID来查看是否已存在该PendingIntent,然后根据第四个参数来作相应的操作,关于第四个参数的含义,请参考PendingIntent传送数据丢失解决办法一文。
如果在生成PendingIntent时,第二个参数相同,那么就相当于在原来的PendingIntent上修改,我们看到的当然是最后一次修改的结果。所以解决方法就是把第二个参数设为一个动态的值,这里最好的办法就是设为appWidgetId,每个Widget都有一个唯一的ID,不会重复。
发现一个奇怪的问题,在我自己的程序中,是用一个for循环来循环绑定PendingIntent的,同时循环里还有一个线程来处理耗时操作。按上面的修改,我发现如果把绑定PendingIntent的代码放在循环体内,Thread外,上面的修改无效,但是如果放在Thread内,就有效了,暂时不知道原因,如有知道的同学希望留言说一声。
- 一个android应用向Home screen添加多个Widget
- 一个android应用向Home screen添加多个Widget
- Android学习笔记:Home Screen Widgets(1):关于Widget
- Android学习笔记:Home Screen Widgets(2):关于Widget
- Home Screen Widgets(2):Widget定义
- Android一个应用中展示多个多种样式的Widget
- Android定制Home Screen
- Pro Android学习笔记(一三五):Home Screen Widgets(1):关于Widget
- Pro Android学习笔记(一三六):Home Screen Widgets(2):Widget定义
- Pro Android学习笔记(一三八):Home Screen Widgets(4):App Widget Provider
- Making new Android HOME screen
- Android: Launch the HOME screen
- Android应用程序设置Home Screen
- QT 一个widget设置多个tooltips
- Android 一个ListView添加多个Adapter
- Android添加Widget
- 定制替换Android桌面(home screen)
- 定制替换Android桌面(home screen)
- 如何在VS2010中的MFC中配置GDI+
- POJ 1350 Cabric Number Problem(我的水题之路——字符串和数字间的转换)
- 五款超级本大比拼
- use Fiddler to debug Development Fabric
- 一个拼图游戏,包含很多内容。
- 一个android应用向Home screen添加多个Widget
- window下查当前运行进程
- java类文件批量编译语法及依赖类文件的运行
- POJ 1450 Gridland(我的水题之路——找规律)
- socket实现大型文件传输 .
- 正则表达式基础(一)
- 3.Coding Struts 2 Actions
- POJ 1493 Machined Surfaces(我的水题之路——移动后的空格)
- MyEclipse优化加载速度和去掉一些没用的设置