我开发了一个appwidget,它是一个集合小部件,使用Loader从数据库中检索数据,当用户点击列表项时,项目详细信息将保存到intent中的bundle中,并且将启动主要活动,并向用户显示捆绑信息。
我的代码按预期工作;但是,我担心小部件实际工作,初始化和更新的可能边缘情况,我没有想到。我认为我的代码正常工作了大约5天后,我发现了一个边缘案例。同样,我是小部件开发的新手,小部件的API花了我很多力气。
使用我的appwidget的所有东西似乎都可以在我的手机上正常工作,但在我的平板电脑上,它可以在打开应用程序并在主屏幕上添加新小部件后正常工作。如果我没有先打开应用程序,那么我的小部件中就不会显示任何内容。
此外,如果我的平板电脑重新启动或打开电源,那么我当前的小部件将不会显示任何内容。即使在打开我的应用程序之后,我也必须为我的其他小部件添加一个新的小部件以进行更新。
对于我的手机,除非我添加其他小部件,否则我很少会在小部件上显示任何内容。至少我不能复制任何东西,并保证它不会像在平板电脑上那样工作。
那么这款手机怎么能在我的手机上完全正常工作,但我的平板电脑上一直有问题?有没有办法确保我的数据是否可用,无论我是否在应用程序上打开,以及我是否重新启动设备?
GitHub Link。直接链接到我的Hub Flavor,它实现了appwidget(java和res文件夹,以及清单文件)
public class ResumeHubWidgetProvider extends AppWidgetProvider {
private static final String LAUNCH_RESUME_ACTION = "io.github.ciscorucinski.personal.intro.hub.LAUNCH_RESUME_ACTION";
private static Intent createIntent(Context context) {
return new Intent(context, ResumeHubWidgetProvider.class);
}
private static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
Intent serviceIntent = MyWidgetService.createIntent(context);
serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)));
// Construct the RemoteViews object
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.resume_hub_list_widget);
views.setRemoteAdapter(R.id.widget_list, serviceIntent);
Intent widgetProviderIntent = ResumeHubWidgetProvider.createIntent(context);
widgetProviderIntent.setAction(ResumeHubWidgetProvider.LAUNCH_RESUME_ACTION);
widgetProviderIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
serviceIntent.setData(Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)));
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, widgetProviderIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
views.setPendingIntentTemplate(R.id.widget_list, pendingIntent);
// Instruct the widget manager to update the widget
appWidgetManager.updateAppWidget(appWidgetId, views);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple similar widgets active, so update all of them
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
@Override
public void onReceive(Context context, Intent intent) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
if (intent.getAction().equals(LAUNCH_RESUME_ACTION)) {
Timber.i("Intent Action is LAUNCH_RESUME_ACTION");
// Open the Resume activity with the user selected resume info
Bundle bundle = intent.getBundleExtra(CREATE_INTENT_BUNDLE);
context.startActivity(ResumeActivity
.createIntentWithFlags(context, bundle,
Intent.FLAG_ACTIVITY_NEW_TASK));
}
int appWidgetIds[] = appWidgetManager.getAppWidgetIds(new ComponentName(context, ResumeHubWidgetProvider.class));
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.widget_list);
super.onReceive(context, intent);
}
}
class HubWidgetAdapter implements RemoteViewsService.RemoteViewsFactory,
Loader.OnLoadCompleteListener<List<Resume.People>> {
private Context context;
private List<Resume.People> data;
private int appWidgetId;
private PeopleLoader loader;
HubWidgetAdapter(Context context, Intent intent) {
this.context = context;
appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
}
@Override
public RemoteViews getViewAt(int position) {
RemoteViews view = new RemoteViews(context.getPackageName(),
android.R.layout.simple_list_item_1);
Resume.People person = data.get(position);
view.setTextViewText(android.R.id.text1, person.seeking_position());
view.setTextColor(android.R.id.text1, Color.BLACK);
Bundle bundle = new Bundle();
bundle.putLong(ResumeActivity.ID, person._id());
bundle.putString(ResumeActivity.NAME, person.name());
bundle.putString(ResumeActivity.EMAIL, person.email());
bundle.putString(ResumeActivity.PHONE, person.phone());
bundle.putString(ResumeActivity.GITHUB, person.github());
bundle.putString(ResumeActivity.LINKEDIN, person.linkedin());
bundle.putString(ResumeActivity.SEEKING, person.seeking_position());
Intent intent = new Intent();
intent.putExtra(CREATE_INTENT_BUNDLE, bundle);
Timber.i("Bundled Person%s", intent);
view.setOnClickFillInIntent(android.R.id.text1, intent);
return view;
}
@Override
public void onLoadComplete(Loader<List<Resume.People>> loader, List<Resume.People> data) {
this.data = data;
}
@Override
public void onCreate() {
data = new ArrayList<>();
}
@Override
public void onDestroy() {
if (loader != null) {
loader.unregisterListener(this);
loader.cancelLoad();
loader.stopLoading();
loader = null;
}
data = null;
}
@Override public void onDataSetChanged() {
loader = new PeopleLoader(context);
loader.registerListener(0, this);
loader.startLoading();
}
@Override public int getCount() { return data.size(); }
@Override public RemoteViews getLoadingView() { return null; }
@Override public int getViewTypeCount() { return 1; }
@Override public long getItemId(int position) { return position; }
@Override public boolean hasStableIds() { return true; }
}
public class MyWidgetService extends RemoteViewsService {
static Intent createIntent(Context context) {
return new Intent(context, MyWidgetService.class);
}
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
return new HubWidgetAdapter(this.getApplicationContext(), intent);
}
}
Hub flavor是我的代码中唯一具有appwidgets的方面,因此我只在此处包含Hub Manifest文件,该文件已合并到主Manifest文件中。
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity
android:name="io.github.ciscorucinski.personal.intro.ui.ResumeActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar"/>
<receiver android:name="io.github.ciscorucinski.personal.intro.hub.ResumeHubWidgetProvider">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/resume_hub_list_widget_info" />
</receiver>
<service
android:name="io.github.ciscorucinski.personal.intro.hub.MyWidgetService"
android:exported="false"
android:permission="android.permission.BIND_REMOTEVIEWS" />
</application>
</manifest>