In my Android application, when the user exits the preference screen, the ui needs to be updated according to the updated preferences. Is there any simple way to do this?
EDIT:
Preferences activity:
public class Settings extends PreferenceActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.prefs);
}
}
and in the app, a TextView needs to be changed to one of the preferences strings.
Wherever the UI needs to be updated, those values should be obtained from the SharedPreferences. When you change the preferences simply update your shared preferences values and when you return back to the view (onResume()) update your views (by getting the values again from the shared preferences).
Implement OnSharedPreferenceChangeListener in the activity to be updated and include the code you want to execute in the method onSharedPreferenceChanged(...)
I think its so easy
From what ever activity you are Starting this activity you shall start it using
startActivityForResult(<Your intent>, MY_PREFERENCE);
and now you can override onActivityResult
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
Log.d("VideoListActivity.onActivityResult ", "Opening");
switch(requestCode)
{
case MY_PREFERENCE:
switch(resultCode)
{
case RESULT_OK:
// do your stuff
break;
case RESULT_CANCELED:
// do your stuff
break;
default:
break;
}
break;
default:
break;
}
Log.d("VideoListActivity.onActivityResult ", "Closing");
super.onActivityResult(requestCode, resultCode, data);
}
and Remember when your job done in your child activity you must set result using this
Intent intent = new Intent();
intent.putExtra("isUpdated", true);
setResult(RESULT_OK, intent);
Related
I am trying to do the following:
Show dialog fragment from an Activity (not Fragment);
Retrieve result in the Activity.
The problem is that onActivityResult in the Activity is not being called.
Here is how I am showing a DialogFragment
DriverRatingDialogFragment dp = new DriverRatingDialogFragment();
// this solution works well in case of showing dialog from a fragment
// but I have to show it from the Activity
// dp.setTargetFragment(getSupportFragmentManager().findFragmentById(R.id.flContent), DriverRatingDialogFragment.REQUEST_CODE);
dp.show(getSupportFragmentManager(), DriverRatingDialogFragment.ARG_RATING);
And here is how I am trying to return result from DialogFragment:
Intent intent = new Intent();
// This solution works well in case of previously setting target Fragment,
// but I have to return result to Activity
// getTargetFragment().onActivityResult(
// getTargetRequestCode(), REQUEST_CODE, intent);
// and with this attempt App crashes
// this.onActivityResult(REQUEST_CODE, Activity.RESULT_OK, intent);
here is where I want to retrieve result in the Activity, but it doesn't get called:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == DriverRatingDialogFragment.REQUEST_CODE) {
// todo
}
super.onActivityResult(requestCode, resultCode, data);
}
What's wrong?
I start the DialogFragment the same way you do.
CreatePostDialog createPostDialog = new CreatePostDialog();
createPostDialog.show(getSupportFragmentManager(), "create_post_dialog");
And I send back data using a public method in the activity rather than with intents.
((MainActivity)mContext).logout(Utils.getLocation(v));
The snippets above are copy pasted examples of my working code. Logout in this case is a public method in MainActivity that takes in a point and does what is needs with it.
you can use callback
1.define a callback in you dialog fragment
public Call mCall;
public interface Call {
void returnData(Data data);
}
2.on dialog fragment life circle
#Override
public void onDetach() {
super.onDetach();
mCall = (Call) getActivity();
mCall.returnData(data);
}
3.activity just implements Call
activity implements DiaFragment.Call
onActivityResult is there to receive informations after startActivityForResult is called, which is not your case.
What kind of datas you need to get from the dialog ?
DialogFragment is usually used in a fragment, not an activity. Look at alert dialog.
So I have a boolean value in Activity A that is set to false. Then, in another activity I want to change that value to true. Then when i press the back button back to activity A, that boolean is now true and it runs that in the onCreate.
here's what I mean, Activity A
private static boolean newCardcheck = false;
#Override
protected void onCreate(Bundle savedInstanceState)
{
}
public static void setNewCardcheck() {
newCardcheck = true;
}
#Override
public void onResume() {
super.onResume();
if(newCardcheck)
{
Toast.makeText(this,"hey everyone",Toast.LENGTH_SHORT).show();
}
else
{
alfunction();
sendCards(storeCards);
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if(requestCode == RESULT_LOAD_IMAGE)
{
newCardcheck = true;
}
}
Activity B:
#Override
public void onBackPressed()
{
MyActivity.setNewCardcheck();
super.onBackPressed();
setResult(Activity.RESULT_OK, getIntent());
finish();
}
So when I press back, I want newCardcheck to be true and run the "if" statement not the else statement.
Hope you guys can help.
thanks.
And I also tried putting setNewCard() method in an onClick it didn't work either.
The best way to do this is through SharedPreferences. SharedPreferences will write your data to a private file in a key/value within your app's apk that will persist even you turn your device off.
You can initialize SharedPreferences in onCreate like so: SharedPreferences sharedPreferences = getSharedPreferences(getPackageName(), MODE_PRIVATE).
To store a value simply call: sharedPreferences.edit().putString("myKey", stringValue).commit();
To retrieve that value anywhere from your application, initialize SharedPreferences, and then use the following code: String myData = sharedPreferences.getString("myKey");
Let me know if that helps!
EDIT: You may also want to look into getting a result from your Intent. See Getting a Result from an Activity. Use SharedPreferences if you need the boolean to be persistent (ie: written to storage and available on reboot), otherwise you may want to try onActivityResult.
Edit 2:
Try overriding onActivityResult in Activity A as so:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
myBoolean = true;
}
}
Then in Activity B try
setResult(Activity.RESULT_OK, getIntent());
finish();
This is the standard way of passing data to and from activities. Check out my link above about getting a result from an activity to delve a little deeper.
From what I have researched, Android does not have a practical way to change overall application themes.
My application is somewhat simple, Activity wise, and I think this method of handling theme changes is safe.
I want to know if the method below is a safe, or is this a hack job and there are better ways to implement application wide themes?
Notes:
MainActivtiy.java is the entry point and only Activity besides the SettingsActivty.java
SettingsActivity.java extends the PreferenceActivty to display a typical preference screen. The theme setting is stored in the default shared preference identified by R.string.colorThemeListPrefStr where the android:entryValues are {"0", "1"}
Settings.java is just a class for static variables that are safe while the application is in memory, anything that needs to be saved between session is saved to shared preferences during onPause().
MainActivity.java:
public class MainActivity extends ListActivity implements OnClickListener{
public void onCreate(Bundle savedInstanceState) {
sp = PreferenceManager.getDefaultSharedPreferences(this);
// get the int representing the theme selected from shared preferences
switch (Integer.valueOf(sp.getString(getString(R.string.colorThemeListPrefStr), Settings.DEFAULT_COLOR_THEME_INDEX))) {
case 0:
super.setTheme(android.R.style.Theme_Light);
break;
case 1:
super.setTheme(android.R.style.Theme_Black);
break;
}
super.onCreate(savedInstanceState);
// ...
}
public void onPause() {
super.onPause();
// ...
// store the current theme int
Settings.currentTheme = Integer.valueOf(sp.getString(getString(R.string.colorThemeListPrefStr), Settings.DEFAULT_COLOR_THEME_INDEX));
// ...
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.inputSettingsButton:
startActivityForResult(new Intent(this, SettingsActivity.class), Settings.PREFERENCES_REQUEST_CODE);
break;
// ...
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case Settings.PREFERENCES_REQUEST_CODE:
// check if the new and old themes are different
if (Settings.currentTheme != Integer.valueOf(sp.getString(getString(R.string.colorThemeListPrefStr), Settings.DEFAULT_COLOR_THEME_INDEX))) {
this.finish();
startActivity(new Intent(this, MainActivity.class));
}
break;
// ...
}
}
}
You should restart your Application using this simple one line of code that comes with the support library.
startActivity(IntentCompat.makeRestartActivityTask(getActivity().getComponentName()));
Can you please clarify me, what's the best practice for this example:
Activity1 does INSERTS on SQLite and starts Activity2.
On Activity2, the user clicks on Back button and goes back to Activity1.
But instead of making INSERT, I want to make UPDATE to the data on SQLite.
How do I control, that user "came" back?
What's the best practice?
Assume on button click you starting Activity 2
public static final int YOURCONSTANTNUMBER = 77;
//Button Value
Button second = (Button)findViewById(R.id.firstButton);
second.setOnClickListner(this);
#Override
public void onClick(View v)
{
switch(v.getId())
{
case R.id.btnSecondActivity:
//Code for inserting data into database
Intent secondactivity = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(secondactivity);
break;
}
}
In your second activity
To take control over the back button use the below code
#Override
public void onBackPressed()
{
//Code for update
}
EDIT
Call your second activity with startActivityForResult() method which will let you know the result.
In First Activity
Intent secondactivity = new Intent(FirstActivity.this, SecondActivity.class);
startActivityForResult(secondactivity,YOURCONSTANTNUMBER);
Getting Result
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode)
{
case YOURCONSTANTNUMBER:
// It will execute if you returning from second activity
//Update you database here
}
}
In Your Second Activity
Call this method were appropriate setResult(YOURCONSTANTNUMBER);
Hope it helps
Assuming you want to do both DB operations in Activity1, consider startActivityForResult() here:
http://developer.android.com/reference/android/app/Activity.html#startActivityForResult(android.content.Intent, int)
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?
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;
}
});
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 :)
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
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.