Android:Widget Config Activity 启动两次?

标签 android android-activity android-widget android-intent

我有一个具有配置 Activity 的 Android 小部件。我还在小部件上设置了一个 ImageView“按钮”以启动配置 Activity ,以防用户在初始化后想要更改他/她的首选项。

因此,基本生命周期:

  1. 用户添加小部件
  2. 配置 Activity 弹出,用户填写字段并点击“提交”
  3. 小部件已添加到屏幕上
  4. 用户点击 ImageView 启动配置 Activity
  5. 弹出配置 Activity ,用户编辑字段
  6. 点击“提交”或退出后,小部件将更新
  7. 用户可以根据需要继续完成第 5 步和第 6 步。

我的问题是在第 5 步。非常第一次并且只有用户第一次点击 ImageView 时,似乎启动了两个配置 Activity 。也就是说,当我退出第一个时,“背后”还有另一个。然而,在配置 Activity 的所有后续启动中,只有一个启动并且一切正常。

可能是什么问题?我将在下面发布相关代码。

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 方法

任何帮助都会很棒!谢谢!

最佳答案

调用显式 Intent 时,您应该考虑使用 FLAG_ACTIVITY_CLEAR_TOP 等 Intent 标志之一来保持堆栈的组织性。例如:

configIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

您可以在 IMDB 应用等某些应用中发现此标志的缺失,在这些应用中,每次单击“主页”按钮都会在堆栈中添加另一个主页 Activity 实例,因此您需要多次单击“后退”按钮从堆栈中弹出并退出应用程序。 :)

关于Android:Widget Config Activity 启动两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4681231/

相关文章:

java - 从 Google Map 获取结果并将数据传输回之前的 fragment

android - 如何使用 TouchWiz 从 Android 上的输入/文本区域中删除橙色轮廓/边框

android - 关闭电源断开的 Activity

java - 我的 Activity 没有调用 onActivityResult

Android - ListView - 按需调用 getView()

android - 使用 LinearLayout 的自定义小部件没有得到 onDraw()

android - picasso 加载字节数组

android - 将应用程序从 Jellybean 版本扩展到 Kitkat 以用于 SMS 中止广播

android - 如果 Activity 被操作系统杀死,我们如何检索保存的状态?

android - 自定义微调器项目未作为微调器的一部分出现