我有一个具有配置活动的Android小部件。我还在小部件上设置了一个ImageView“按钮”来启动配置活动,以防用户在初始化后想要更改他/她的首选项。
所以,基本生命周期:
我的问题在第5步。第一次和仅第一次用户点击ImageView时,看起来启动了两个配置活动。也就是说,当我退出第一个时,还有一个“落后”它。然而,在配置活动的所有后续启动中,只启动了一个,一切都很好。
可能是什么问题?我将在下面发布相关代码。
的AndroidManifest.xml
<activity
android:name=".ConfigActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
<receiver
android:name=".Widget"
android:label="Widget" >
<intent-filter>
<action
android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<intent-filter>
<action
android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<data android:scheme="sample_widget" />
</intent-filter>
<intent-filter>
<action
android:name="com.this.that.WIDGET_CONTROL" />
<data
android:scheme="sample_widget" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/widget" />
</receiver>
AppWidget-Provider widget.xml
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider
xmlns:android="http://schemas.android.com/apk/res/android"
android:updatePeriodMillis="5000"
android:minWidth="294dp"
android:minHeight="220dp"
android:initialLayout="@layout/widgetlayout"
android:configure="com.this.that.ConfigActivity" >
</appwidget-provider>
ConfigActivity.java
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get the data we were launched with
Intent launchIntent = getIntent();
Bundle extras = launchIntent.getExtras();
if (extras != null) {
appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
Intent cancelResultValue = new Intent();
cancelResultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
setResult(RESULT_CANCELED, cancelResultValue);
} else {
// Only launch if it's for configuration
finish();
}
setContentView(R.layout.myconfig);
// Create Buttons/EditTexts
SubmitBTN = (Button) findViewById(R.id.BTNSubmit);
SampleET= (EditText) findViewById(R.id.ETSample);
SubmitBTN.setOnClickListener(submitListener);
loadPreferences(ConfigActivity.this, appWidgetId);
}
private OnClickListener submitListener = new OnClickListener() {
public void onClick(View v) {
final Context context = PriorityViewConfig.this;
// Save strings in our prefs
String sample = SampleET.getText().toString();
SharedPreferences.Editor prefs = context.getSharedPreferences(PREFS_NAME, 0).edit();
prefs.putString(PREF_PREFIX_KEY + appWidgetId + "sample", sample);
prefs.commit();
if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
// Tell the AppWidgetManager that we're now configured
Intent resultValue = new Intent();
//resultValue.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
setResult(RESULT_OK, resultValue);
// Get an instance of the AppWidgetManager
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
// Update the App Widget with the layout
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widgetlayout);
Widget.updateDisplayState(context, appWidgetId);
}
// Activity is now done
finish();
}
};
private void loadPreferences(Context context, int appWidgetId) {
SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, 0);
String sample = prefs.getString(PREF_PREFIX_KEY + appWidgetId + "sample", null);
if (sample != null) {
SampleET.setText(sample);
} else {
// Nothing stored, don't need to do anything
}
}
Widget.java
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
Log.d(LOG_TAG, "OnReceive:Action: " + action);
if (ACTION_WIDGET_CONTROL.equals(action)) {
// Pass this on to the action handler where we'll figure out what to do and update the widget
final int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
this.onHandleAction(context, appWidgetId, intent.getData());
}
}
super.onReceive(context, intent);
}
public static void updateDisplayState(Context context, int appWidgetId) {
Intent configIntent = new Intent(context, ConfigActivity.class);
configIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
// Make this unique for this appWidgetId
configIntent.setData(Uri.withAppendedPath(Uri.parse(Widget.URI_SCHEME + "://widget/id/"), String.valueOf(appWidgetId)));
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, configIntent, PendingIntent.FLAG_UPDATE_CURRENT);
views.setOnClickPendingIntent(R.id.IVConfig, pendingIntent);
AppWidgetManager.getInstance(context).updateAppWidget(appWidgetId, views);
}
private void onHandleAction(Context context, int appWidgetId, Uri data) {
String controlType = data.getFragment();
// Nothing here yet
updateDisplayState(context, appWidgetId);
}
我认为这些是最相关的部分。我将要进一步研究的地方是在submitListener中的ConfigActivity.java和Widget.java中的updateDisplayState方法
任何帮助都会很棒!谢谢!
答案 0 :(得分:4)
调用显式意图时,应考虑使用其中一个意图标志(如FLAG_ACTIVITY_CLEAR_TOP)来保持堆栈的有序性。例如:
configIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
您可以在某些应用程序(如IMDB应用程序)中发现缺少此标记,其中每次单击“主页”按钮都会在堆栈上添加另一个主页活动实例,因此您需要多次单击“返回”按钮弹出堆栈并退出应用程序。:)
答案 1 :(得分:0)
添加到清单文件android的活动:noHistory =“true”和android:excludeFromRecents =“true”
它假设要解决问题
<activity
android:name=".ConfigActivity"
android:label="@string/app_name"
android:noHistory="true"
android:excludeFromRecents="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>