Start Activity from preferences.xml and get the result in onActivityResult - android

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.

Related

What is the right way to hold and restore the data temporarily between activities in android?

I am creating an Android app. One of the functions is to collect some data (item name, item ID and the barcode string) from the user .
Activity1 is a form. User enters the item name and item number manually. For the barcode string, user clicks on the "scan" button then Activity2 (Scanner) is started in order to scan and read the barcode. Once the barcode is read, Activity1 (the form) starts again and all data should appear on the form.
When Activity2 starts by Intent, Activity1 is killed. So, I have to get the item name and item number and store them temporarily before staring the Intent. Then when Activity1 starts again, those data will be rendered on the form again.
Now I am thinking to use Intent Extra to keep the item name and number, and pass them to Activity2 and back to Activity1. Given that Activity2 doesn't need those data, I wonder if that is the right way to do in this scenario. Is there any better way? Should I use Shared Preferences instead?
In Your first activity use put extra argument to intent like this:
// Assuming Activity2.class is second activity
Intent intent = new Intent(this, Activity2.class);
intent.putExtra("variable_name", var); // here you are passing var to second activity
startActivity(intent);
Then in second activity retrieve argument like this:
String var2 = getIntent().getStringExtra(variable_name);
You could create a singleton class and expose setter(for saving) and getter (for retrieving) methods for the model objects (here two private string variables).This class will be alive with your application:
public class MyClass{
private static MyClass instance=null;
public static getInstance(){
if(instance==null){
instance=new MyClass();
}
return instance;
}
private String itemName;
private String itemNumber;
//setter and getter methods here
}
why need to kill the Activity 1, try to call
on Activity 1
declare private int SCAN_BARCODE_REQUEST = 101;
and then
//finish(); dont use this to destroy activity 1
startActivityForResult(new intent(this,Activity2.class), SCAN_BARCODE_REQUEST);
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == SCAN_BARCODE_REQUEST) {
if (resultCode == RESULT_OK) {
String barcode = data.getStringExtra("BARCODE");
//handle your barcode string here
}
}
}
on your Activity 2,
change your start Activity1 with
Intent intent = new Intent();
intent.putExtra("BARCODE", barcodeString);
setResult(RESULT_OK, intent);
finish();
You can use SharedPreferences.
You can learn how to use them here:
https://www.tutorialspoint.com/android/android_shared_preferences.htm
https://developer.android.com/training/basics/data-storage/shared-preferences.html
SharedPreferences is a really good solution for such applications. It is very simple and easy to use and implement.

How do I change an activities's boolean values or other variable values in another activity?

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.

Calling a method in my PreferenceActivity Activity form another Activity

Hi and thanks for your help,
I have the following situation.
In my App I use PreferenceActivity to show and allow changes of settings, let's call it PreferenceActivity A.
If the user selects one particular preference a new Activity is launched, let's call it Activity B (A is not destroyed).
What I need to do is to call a method of PreferenceActivity A form inside Activity B.
Please note: that the method in PreferenceActivity A cannot be static.
Any help very much appreciated.
EDIT EDIT EDIT EDIT EDIT EDIT
This is how Activty B is launched:
When the user taps on the correspondent item in the PreferenceActivity A screen the intent is triggered.
<PreferenceScreen
android:key="addstocks"
android:summary="Click here to add stocks"
android:title="Add stocks" >
<intent
android:targetClass="com.stocktickerwidget.QuotesActivity"
android:targetPackage="com.stocktickerwidget" />
Instead of starting the activity like that, manually set an OnPreferenceClickListener on the preference and use startActivityForResult().
private static final int RESUEST_CODE = 1;
protected void onCreate() {
/* ... */
Preference pref = getPreferenceManager().findPreference("addstocks");
pref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference() {
if (preference.getKey().equals("addstocks") {
startActivityB();
return true;
}
return false;
}
});
}
private void startActivityB() {
Intent intent = new Intent(this, ActivityB.class);
startActivityForResult(intent, REQUEST_CODE);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {
// do something here
}
}

restart activity in android

I have one activity A, that has one button and one list view which shows names of books . on click of the button, activity B starts, there user fill the book form and save it . when he press back button , user comes to activity A. Here the book name should be updated in listview. I think I have to write some code in onResume() . Can u please tell me what to write. I am using customised list view.
Start activity B with startActivityForResult() and use method onActivityResult() to restart or process the new data
For example, to start Activity B:
String callingActivity = context.getLocalClassName();
Intent newActivity = new Intent(getApplicationContext(),ActivityB.class);
newActivity.setData(Uri.parse(callingActivity));
startActivityForResult(newActivity, 0);
Then somewhere in your Activity A class:
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if(requestCode == 0){
// do processing here
}
}
The other answers should suffice, but onResume() can be called in cases where the activity is resumed by other means.
To simply restart Activity A when user presses back button from Activity B, then put the following inside the onActivityResult:
if(requestCode == 0){
finish();
startActivity(starterintent);
}
And in the onCreate of Activity A, add starterintent = getIntent();
Just remember to initiate the variable with Intent starterintent; somewhere before your onCreate is called.
e.g.
public class ActivityA extends ListActivity {
Intent starterintent;
public void onCreate(Bundle b){
starterintent = getIntent();
}
protected void onActivityResult(int requestCode, int resultCode, Intent data){
if(requestCode == 0){
finish();
startActivity(starterintent);
}
}
private void startActivityB(){
String callingActivity = context.getLocalClassName();
Intent newActivity = new Intent(getApplicationContext(),ActivityB.class);
newActivity.setData(Uri.parse(callingActivity));
startActivityForResult(newActivity, 0);
}
}
Then just call startActivityB() from a button click or whatever
YES you are right. Write code in onResume.
When you updated date just call notifyDataSetChanged(); for your ListView adapter
Hope, it help you!
You can either start the activity when user press on Save, and it will fix it for you.
Or if you want to press back:
#Override
public void onResume(){
super.onResume();
list.clear();
list.addAll(getBooks());
adapter.notifyDataSetChanged();
}

Android - How to retrieve data from activity

I am new to android so please excuse the newbie question. I have a game I am trying to port from an old Java applet to android. My goal is to get this functional and then post an article on a site like CodeProject (or a better one if there are ones more appropriate). The idea is to show that a person brand new to android development can create an app in a reasonable amount of time.
I am making some progress but have run into a problem. I have the main activity in which the user interacts with. I then created a menu item that in turn starts a second activity (call it child) with a modest number of checkbox's, seekbar's etc to fill in parameters. I can successfully pass the class containing all the options from main to child. But I cannot get the child to pass this data back to the main.
First here is my main code that starts the child activity:
public void addBalls()
{
Intent myIntent = new Intent(this, GameOptions.class);
Bundle b = new Bundle();
b.putSerializable("options", gameParams);
myIntent.putExtras(b);
startActivityForResult(myIntent,STATIC_OPTIONS_VALUE);
}
The data passed to the child (and hopefully back again) is:
public class GameOptionParams implements Serializable
{
private static final long serialVersionUID = 1L;
public int speedBarPosition;
public int vgravityBarPosition;
public int mgravityBarPosition;
public int viscosityBarPosition;
public int restititionBarPosition;
public boolean trace;
public boolean collide;
public boolean mush;
public boolean wrap;
public boolean flicker;
}
And here is the expected return (again in main)
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode)
{
case (STATIC_OPTIONS_VALUE) :
{
if (resultCode == Activity.RESULT_OK)
{
//retrieve intended options
Bundle b = data.getExtras();
gameParams = (GameOptionParams) b.getSerializable("options");
}
break;
}
}
}
The child activity successfully receives the gameParams data. It then interacts with the user to update the values and then I attempt to return it but it does not seem to get sent to main. Here is the child code in the onStop() override.
Maybe this code should not be in the onStop() override but I can't determine where else to place it.
#Override
public void onStop()
{
super.onStop();
//read widget values
gameParams.speedBarPosition = speedBar.GetPosition();
gameParams.vgravityBarPosition = vgravityBar.GetPosition();
gameParams.mgravityBarPosition = mgravityBar.GetPosition();
gameParams.viscosityBarPosition = viscosityBar.GetPosition();
gameParams.restititionBarPosition = restititionBar.GetPosition();
//todo save to persistent
Intent resultIntent = new Intent(this, TiltBall2ImpactActivity.class);
Bundle b = new Bundle();
b.putSerializable("options", gameParams);
resultIntent.putExtras(b);
setResult(Activity.RESULT_OK, resultIntent);
}
Back in the main onActivityResult override I always see requestCode=0, resultCode=0, data=null. I assume this is a typical newbie problem, I have been reading the sdk documentation, user forums etc and have come close to a solution but just not quite there yet. Any help would be appreciated.
Since this is sort of a setting menu for the game, I assume you are going to need these values for more than one activity. If so you extend the android.app.Application class.
In that class you can create attributes to hold your values. In any activity you can call
MyApplication myApp = (MyApplication)getApplicationContext();
where myApp is a singleton. So you will get the values you set from another activity.
You will need to add this code to your application tag in the manifest file for it to work
android:name=".MyApplication"
If you need to keep these values for next startup of the application, you need to use SharedPreferences. This is a good tutorial for that
http://saigeethamn.blogspot.com/2009/10/shared-preferences-android-developer.html
Assuming in your 'child' activity, the user has to press an 'OK' or 'Save' button then put the code to set the gameParams parameters in the button's onClick(...) handler.
Use the default constructor for instantiating the Intent, example...
Intent resultIntent = new Intent();
...then after creating the Bundle and adding gameParams to it and calling setResult(...), simply call finish() to terminate the 'child' activity. There aren't many occasions that I can think of to override onStop() and I suspect you don't want to be using it to attempt returning the Intent.

Categories

Resources