Start Activity from preferences.xml and get the re

2019-03-23 12:45发布

It's a complement to this question.

I can launch the Activity but I also need to be able to get the result. How do I do it?

I tried overriding onActivityResult on my PreferencesActivity to no avail.

Am I missing some extra properties in the preferences.xml?

4条回答
We Are One
2楼-- · 2019-03-23 13:08

If you want to pass data from the preference activity to your main activity use this code:

In your main activity class (launch):

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

In your preference activity class (set the result):

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

In your main activity class (get the result):

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

You can put as many extras as you want and not only strings but all standard data types.

Hope i did everything right ;)

EDIT

As Kaarel told me, I probably missunderstood the question. This is how you can recieve data from the main activiy in the preferences activity:

In your main activity: launch the preferences activity and attach the data

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);

In your preferences activity: recieve the data attached to the intent

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

查看更多
ゆ 、 Hurt°
3楼-- · 2019-03-23 13:21

Try overriding startActivity() in your PreferencesActivity class and make it call startActivityForResult() instead after checking that the intent is the one we are interested in, similar to the following (with 1234 as the request code):

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
        }
    }

    // ...
}

Depending on your needs, this could be simpler compared to adding several OnPreferenceClickListener in your code :)

查看更多
\"骚年 ilove
4楼-- · 2019-03-23 13:24

If you take a look at PreferenceActivity.java in platform source code here at line 1000 you can see that your intent is called via startActivity startActivity(header.intent); and not via startActivityForResult, so I don't think this is possible.

However you could try to override the onHeaderClick function along with the onActivityResult of the PreferenceActivity and see what happens. I didn't try it myself so I don't know and there is a good chance that this approach will be broken in future versions.

But maybe there is another approach that could work for you. As I can see from your reference question you are launching an activity via an intent. If this activity is for settings editing then this is NOT the correct approach since android uses this intent just for launching an activity and nothing more. In my opinion it is better to create your specific preference activity by extending any of the available ones in order to customize it. Here is my customized ListPreference that I use in order to let the user select an application:

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 -----
} 

And i am using it in my preferences.xml like this:

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

By using this approach I can control everything my user does in this activity without breaking android's rules about preferences.

Hope this helps.

查看更多
Root(大扎)
5楼-- · 2019-03-23 13:29

The cleanest solution that I know of is to listen to the click on the preference and launch the intent explicitly. This way onActivityResult will be called as usual.

Assuming that your intent-preference is defined in XML you can attach a listener to it like this (where 1234 is a request code for onActivityResult):

Preference pref = (Preference) findPreference("prefKey");
pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
  @Override
  public boolean onPreferenceClick(Preference preference) {
    startActivityForResult(preference.getIntent(), 1234);
    return true;
  }
});
查看更多
登录 后发表回答