从preferences.xml启动Activity并在onActivityResult中获取结果

时间:2012-03-03 10:12:24

标签: android android-preferences android-activity

它是this question的补充。

我可以启动Activity,但我也需要能够获得结果。我该怎么做?

我尝试在我的PreferencesActivity上覆盖onActivityResult无济于事。

我在偏好.xml中错过了一些额外的属性吗?

4 个答案:

答案 0 :(得分:17)

我所知道的最干净的解决方案是听取偏好的点击并明确启动意图。这样onActivityResult将照常调用。

假设您的意图偏好是用XML定义的,您可以像这样附加一个监听器(其中1234onActivityResult的请求代码):

Preference pref = (Preference) findPreference("prefKey");
pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
  @Override
  public boolean onPreferenceClick(Preference preference) {
    startActivityForResult(preference.getIntent(), 1234);
    return true;
  }
});

答案 1 :(得分:14)

尝试覆盖PreferencesActivity类中的startActivity()并在检查意图是我们感兴趣的意图后调用startActivityForResult(),类似于以下内容(使用1234作为请求代码):

public class PreferencesActivity {
    // ...

    @Override
    public void startActivity(Intent intent) {
        if (thisIsTheExpected(intent)) {
            super.startActivityForResult(intent, 1234);
        } else {
            super.startActivity(intent);
        }
    }

    @Override
    protected void onActivityResult(int reqCode, int resCode, Intent data) {
        if (reqCode == 1234) {
            // should be getting called now
        }
    }

    // ...
}

根据您的需求,与在代码中添加多个OnPreferenceClickListener相比,这可能更简单:)

答案 2 :(得分:3)

如果要将首选项活动中的数据传递到主要活动,请使用以下代码:

在您的主要活动类(发布)中:

startActivityForResult(new Intent(main.this, preferences.class), 0);

在您的偏好活动类中(设置结果):

Intent i;
i.putStringExtra("name", "tom");
setResult(RESULT_OK, i);
finish();

在您的主要活动类中(获取结果):

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == 0) {
        if (resultCode == RESULT_OK){
            Log.d("test", data.getExtraString("name");
        }
    }
}

您可以根据需要添加多个附加内容,而不仅仅是字符串,而是所有标准数据类型。

希望我做的一切都正确;)

修改

卡雷尔告诉我,我可能错过了这个问题。 这是您可以在首选项活动中从主要活动中接收数据的方式:

在您的主要活动中:启动偏好设施活动并附加数据

String foo = "hello";
Intent i = new Intent();
i.putExtra("testString", foo);//You can also add other types of variables here, see [1] for reference
i.setClass(main.this, preferences.class);
startActivity(i);

在您的偏好设置活动中:接收附加于意图的数据

Bundle b = this.getIntent().getExtras();//[2]
if (b!=null){
    String recievedString = b.getString("testString");
    //The recievedString variable contains the String "hello" now, see [3]
}

[1] https://developer.android.com/reference/android/content/Intent.html

[2] https://developer.android.com/reference/android/content/Intent.html#getExtras%28%29

[3] https://developer.android.com/reference/android/os/Bundle.html

答案 3 :(得分:1)

如果您在第1000行的平台源代码here中查看PreferenceActivity.java,您可以看到您的意图是通过startActivity startActivity(header.intent);而不是通过startActivityForResult调用的,所以我不认为这是可能的。

但是,您可以尝试覆盖onHeaderClick函数以及PreferenceActivity的onActivityResult,看看会发生什么。我没有亲自尝试,所以我不知道,这种方法很有可能在未来的版本中被打破。

但也许还有另一种方法可以帮到你。正如我从您的参考问题中看到的那样,您正在通过意图启动活动。如果此活动是用于设置编辑,那么这不是正确的方法,因为Android仅使用此意图来启动活动而已。在我看来,最好通过扩展任何可用的首选项活动来创建您的特定首选项活动,以便自定义它。这是我使用的自定义ListPreference,以便让用户选择一个应用程序:

public class CustomSelectAppPreference extends ListPreference {

//----- Constructor -----
public CustomSelectAppPreference(Context context, AttributeSet attrs) {
    super(context, attrs);
}
//----- Constructor END -----



//----- Public Code -----
public void SetResult(String packageName) {
    if(this.callChangeListener(packageName)) {
        Editor edit = this.getSharedPreferences().edit();
        edit.putString(this.getKey(), packageName);
        edit.commit();
    }

    this.getDialog().dismiss();
}
//----- Public Code END -----



//----- ListPreference Overrides -----
@Override
protected void onPrepareDialogBuilder(Builder builder) {
    Log.d("CustomSelectAppPreference", "onPrepareDialogBuilder");

    super.onPrepareDialogBuilder(builder);

    String selectedPackage = this.getSharedPreferences().getString(this.getKey(), "");

    ListAdapter listAdapter = (ListAdapter) new ApplicationsArrayAdapter(this.getContext(), Utilities.getInstalledApplications(this.getContext(), selectedPackage), this);

    builder.setAdapter(listAdapter, this);
}   
//----- ListPreference Overrides END -----
} 

我正在我的偏好.xml中使用它:

<PreferenceScreen android:key="connection_screen"
        android:title="@string/wpref_Connection_Screen_title"
        android:summary="@string/wpref_Connection_Screen_summary"
        android:shouldDisableView="true">

    <com.test.app.CustomSelectAppPreference android:key="userSelectedApplication"
            android:title="@string/wpref_userSelectedApplication_title"
            android:summary="@string/wpref_userSelectedApplication_summary"
            android:dialogTitle="@string/userselectedApplication_dialogTitle"
            android:entries="@array/selectedapps_dummy_actions"
            android:entryValues="@array/selectedapps_dummy_actionsvalues"           
            android:defaultValue=""
            android:shouldDisableView="true"/>
</PreferenceScreen>

通过使用这种方法,我可以控制用户在此活动中所做的一切,而不会违反Android关于偏好的规则。

希望这有帮助。