设备旋转时的Android小部件内容突然消失。
设备旋转时是否需要重新填充?但是小部件没有配置改变来听。
我也使用alarmmanager和service来为新应用程序填充小部件(添加到viewflipper)每1分钟显示一次。
小部件代码:
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
try{
// create intent service per APP id
for(int i = 0; i < appWidgetIds.length; i++)
{
Log.e("onUpdate -- Widget_2_6", "onUpdate -- Widget_2_6: widget ID: " + appWidgetIds[i]);
// check if alarms not created, create 1
if(!GlobalStorage.tempStorage.containsKey(Widget_2_6.class.toString() + appWidgetIds[i]))
{
createAlarmService(context, appWidgetIds[i]);
// put to hash for alarms created
GlobalStorage.tempStorage.put(Widget_2_6.class.toString() + appWidgetIds[i], 0);
//CustomAndroidTools.popToast(Widget_2_6.class.toString() + appWidgetIds[i], context);
}
}
}
catch(Exception e)
{
Log.e("onUpdate -- Widget_2_6", "onUpdate -- Widget_2_6: error: " + e.toString());
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
private void createAlarmService(Context context, int id)
{
if(alarm == null)
{
createAlarm(context);
}
// each new alarm will repeat in increasing half minute: so first is 1 min next is 1 min and 30 sec ...
alarm.setRepeating(AlarmManager.RTC, 0, (1000 * (60 + (GlobalStorage.tempStorage.size() * 30))), createPendingIntent(context, id));
Log.e("createAlarmService -- Widget_2_6", "createAlarmService -- Widget_2_6, creating alarm for widget id: " + id);
}
服务代码:
if(CustomAndroidTools.checkDeviceIsInteractive(context))
{
new Thread(new Runnable() {
public void run() {
try{
ArrayList<AppInfo> appInfos = init(context, _class, widgetID);
buildUpdate(context, _class, widgetID, appInfos);
// update the limit offset here instead so that to ensure no exception came from building the UI of the widget
updateLimitOffset(_class, widgetID);
}
catch(Exception e)
{
Log.e("Thread -- onStartCommand -- WidgetUpdateService", "Thread -- onStartCommand -- WidgetUpdateService: error: " + e.toString());
}
}
}).start();
}
private ArrayList<AppInfo> init(Context context, Class<?> _class, int widgetID)
{
ArrayList<AppInfo> appInfos = new ArrayList<AppInfo>();
try{
appListManager alm = new appListManager(context);
int skip = 0;
//int limit = 10;
if(GlobalStorage.tempStorage.containsKey(_class.toString() + widgetID))
{
skip = GlobalStorage.tempStorage.get(_class.toString() + widgetID);
}
if(skip == 0) // first initialize
{
///TODO: for testing, get the first 5 used by banner
appInfos.add(alm.getAppById(30));
appInfos.add(alm.getAppById(16));
appInfos.add(alm.getAppById(13));
appInfos.add(alm.getAppById(12));
appInfos.add(alm.getAppById(6));
}
//appInfos = alm.getAllAppsUnderTheCategory(-1, skip, limit);
}
catch(Exception e)
{
Log.e("init -- WidgetUpdateService", "init -- WidgetUpdateService: error: " + e.toString());
}
return appInfos;
}
private void updateLimitOffset(Class<?> _class, int widgetID){
int skip = 0;
int limit = 10;
if(GlobalStorage.tempStorage.containsKey(_class.toString() + widgetID))
{
skip = GlobalStorage.tempStorage.get(_class.toString() + widgetID);
}
if(skip != 0)
{
limit = 5;
}
GlobalStorage.tempStorage.put(_class.toString() + widgetID, skip + limit); // update offset limit here
}
private void buildUpdate(Context context, Class<?> _class, int widgetID, ArrayList<AppInfo> appInfos) throws Exception
{
RemoteViews views = null;
appListManager alm = new appListManager(context);
try{
if(_class.equals(Widget_1_6.class) || _class.equals(Widget_1_6_2.class))
{
views = new RemoteViews(getPackageName(), R.layout.widget_1_6);
}
else if(_class.equals(Widget_2_6.class) || _class.equals(Widget_2_6_2.class))
{
views = new RemoteViews(getPackageName(), R.layout.widget_2_6);
}
if(alm.getTotalApps(-1) < 1)
{
views.setViewVisibility(R.id.app, View.GONE);
views.setViewVisibility(R.id.sorryText, View.VISIBLE);
views.setViewVisibility(R.id.loadingText, View.GONE);
}
else
{
views.setViewVisibility(R.id.app, View.VISIBLE);
views.setViewVisibility(R.id.sorryText, View.GONE);
views.setViewVisibility(R.id.loadingText, View.GONE);
if(appInfos != null)
{
for(int i = 0; i < appInfos.size(); i++)
{
views.addView(R.id.appInfo, inflateLayout(appInfos.get(i), context, _class, widgetID));
}
}
Intent refreshWidgetIncrement = new Intent(context, WidgetControlService.class);
refreshWidgetIncrement.putExtra(WidgetControlService.INCREMENT, true);
refreshWidgetIncrement.putExtra(WidgetControlService.DECREMENT, false);
refreshWidgetIncrement.putExtra(WidgetControlService.CLASS, _class);
refreshWidgetIncrement.putExtra(WidgetControlService.WIDGET_ID, widgetID);
refreshWidgetIncrement.setData(Uri.withAppendedPath(Uri.parse("BFR://widget/id/#togetituniqie" + WidgetControlService.class.toString()), UUID.randomUUID().toString()));
PendingIntent pIntentIncrement = PendingIntent.getService(context, 0, refreshWidgetIncrement, PendingIntent.FLAG_CANCEL_CURRENT);
views.setOnClickPendingIntent(R.id.arrowRight, pIntentIncrement);
Intent refreshWidgetDecrement = new Intent(context, WidgetControlService.class);
refreshWidgetDecrement.putExtra(WidgetControlService.DECREMENT, true);
refreshWidgetDecrement.putExtra(WidgetControlService.INCREMENT, false);
refreshWidgetDecrement.putExtra(WidgetControlService.CLASS, _class);
refreshWidgetDecrement.putExtra(WidgetControlService.WIDGET_ID, widgetID);
refreshWidgetDecrement.setData(Uri.withAppendedPath(Uri.parse("BFR://widget/id/#togetituniqie" + WidgetControlService.class.toString()), UUID.randomUUID().toString()));
PendingIntent pIntentDecrement = PendingIntent.getService(context, 0, refreshWidgetDecrement, PendingIntent.FLAG_CANCEL_CURRENT);
views.setOnClickPendingIntent(R.id.arrowLeft, pIntentDecrement);
}
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(widgetID, views);
}
catch(Exception e)
{
Log.e("buildUpdate -- WidgetUpdateService", "buildUpdate -- WidgetUpdateService: error: " + e.toString());
}
}
private RemoteViews inflateLayout(AppInfo appInfo, Context context, Class<?> _class, int widgetID) throws IOException
{
RemoteViews view = null;
if(_class.equals(Widget_1_6.class) || _class.equals(Widget_1_6_2.class))
{
view = new RemoteViews(getPackageName(), R.layout.widget_1_6_body_fragment);
view = inflateWidget1_6(view, appInfo, context, _class, widgetID);
}
else if(_class.equals(Widget_2_6.class) || _class.equals(Widget_2_6_2.class))
{
view = new RemoteViews(getPackageName(), R.layout.widget_2_6_body_fragment);
view = inflateWidget2_6(view, appInfo, context, _class, widgetID);
}
return view;
}
private RemoteViews inflateWidget1_6(RemoteViews view, AppInfo appInfo, Context context, Class<?> _class, int widgetID) throws IOException
{
view.setTextViewText(R.id.appTitle, appInfo.title);
view.setTextViewText(R.id.appDesc, appInfo.shortDesc);
File file = new File(Constants.saveImageLocation + appInfo.iconLoc);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
Bitmap bitmap = null;
if(file.exists()) // if exists in local
{
bitmap = BitmapFactory.decodeFile(Constants.saveImageLocation + appInfo.iconLoc, options);
}
else if (CustomAndroidTools.isImageFoundInAssets(appInfo.iconLoc, context))
{
bitmap = CustomAndroidTools.getImageFromAssets(appInfo.iconLoc, context);
}
else
{
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.broken, options);
}
view.setImageViewBitmap(R.id.appIcon, bitmap);
view.setOnClickPendingIntent(R.id.appIcon, null);
view.setOnClickPendingIntent(R.id.appDetail, null);
Intent openApp = new Intent(context, AppDetailViewActivity.class);
openApp.putExtra(AppDetailViewActivity.LAST_SELECTED_APP, appInfo);
Log.e("current App", "current App: name: " + appInfo.title + ", category index: " + appInfo.category + ". For Widget type: " + _class.toString() + ", id: " + widgetID);
openApp.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
openApp.setData(Uri.withAppendedPath(Uri.parse("BFR://widget/id/#togetituniqie" + new ComponentName(context, _class)), UUID.randomUUID().toString()));
PendingIntent pIntent = PendingIntent.getActivity(context, 0, openApp, 0);
view.setOnClickPendingIntent(R.id.appIcon, pIntent);
view.setOnClickPendingIntent(R.id.appDetail, pIntent);
return view;
}
private RemoteViews inflateWidget2_6(RemoteViews view, AppInfo appInfo, Context context, Class<?> _class, int widgetID) throws IOException
{
File file = new File(Constants.saveImageLocation + appInfo.bannerLoc);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 1;
Bitmap bitmap = null;
if(file.exists()) // if exists in local
{
bitmap = BitmapFactory.decodeFile(Constants.saveImageLocation + appInfo.bannerLoc, options);
}
else if (CustomAndroidTools.isImageFoundInAssets(appInfo.bannerLoc, context))
{
bitmap = CustomAndroidTools.getImageFromAssets(appInfo.bannerLoc, context);
}
else
{
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.broken, options);
}
view.setImageViewBitmap(R.id.appBanner, bitmap);
view.setOnClickPendingIntent(R.id.appBanner, null);
Intent openApp = new Intent(context, AppDetailViewActivity.class);
openApp.putExtra(AppDetailViewActivity.LAST_SELECTED_APP, appInfo);
Log.e("current App", "current App: name: " + appInfo.title + ", category index: " + appInfo.category + ". For Widget type: " + _class.toString() + ", id: " + widgetID);
openApp.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
openApp.setData(Uri.withAppendedPath(Uri.parse("BFR://widget/id/#togetituniqie" + new ComponentName(context, _class)), UUID.randomUUID().toString()));
PendingIntent pIntent = PendingIntent.getActivity(context, 0, openApp, 0);
view.setOnClickPendingIntent(R.id.appBanner, pIntent);
return view;
}
有什么我错过的吗?
答案 0 :(得分:0)
确定。让它工作,问题在于RemoteView的行为。(注意:RemoteView会向需要刷新/更新的视图发送最新的更改)
所以我所做的不是使用manager.updateAppWidget(widgetID,views);无论如何。
我使用了一个标志来知道何时使用updateAppWidget或partialUpdateAppWidget。
下面是上面列出的buildUpdate函数下的修改代码,替换了manager.updateAppWidget(widgetID,views);成:
if(!GlobalStorage.tempStorage.containsKey(_class.toString() + widgetID) || GlobalStorage.tempStorage.get(_class.toString() + widgetID) == 0)
{
Log.e("buildUpdate -- WidgetUpdateService", "buildUpdate -- WidgetUpdateService: either not in collection or is 0: do full update");
manager.updateAppWidget(widgetID, views);
}
else
{
Log.e("buildUpdate -- WidgetUpdateService", "buildUpdate -- WidgetUpdateService: is not 0: do partial update");
manager.partiallyUpdateAppWidget(widgetID, views);
}
使用修改过的逻辑,当视图需要刷新/更新时(我们无法控制大部分时间,如方向更改)。它不会覆盖整个视图,只会覆盖局部视图。