I have created a PreferenceFragment that loads an xml file. Within the xml is an intent item that starts the image picker. The intent is as follows:
<PreferenceCategory
android:title="Your Details">
<Preference android:title="Your picture" >
<intent android:action="android.intent.action.PICK"
android:mimeType="image/*"
/>
</Preference>
</PreferenceCategory>
This works fine at displaying the picker and allowing me to make a choice and then return to the settings.
My problem is - how do I find out which image (if any) was chosen?
All the examples I have found so far only seem to demonstrate the intent being used to view something. Is it actually possible to get a result using this method?
I didn't create the intent with the xml so I used the event listener to launch the Picker. Here is my code:
public class AccountFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener {
static final int PICK_AVATAR_REQUEST_CODE = 1000;
static final String AVATAR_KEY = "avatar_key";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.account_preferences);
Preference avatar = findPreference(AVATAR_KEY);
avatar.setOnPreferenceClickListener(this);
}
#Override
public boolean onPreferenceClick(Preference preference) {
if(preference.getKey().equals(AVATAR_KEY)){
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, PICK_AVATAR_REQUEST_CODE);
return true;
}
return false;
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// super.onActivityResult(requestCode, resultCode, data);
if(requestCode == PICK_AVATAR_REQUEST_CODE){
/**
* You have to call the getData or getDataString to get the images address
*/
Log.i("CCC", data.getDataString());
}
}
}
But also when you are creating the xml the documentation tells the answer:
Enjoy.
Related
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.
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
}
}
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.
When using Android startActivityForResult, I don't have any guarantee about what I'll get in the Intent returned by onActivityResult.
I would like to define some kind of interface to limit the possibility of errors when transmitting data from an Activity to another (eg mistyped variable name).
Is there a way to do that? For example could I use something similar to the Android Interface Definition Language but between Activitys?
There are 2 scenarios when passing data between two activities A,B.
Activity A wants to pass data on Activity B ( through the startActivity Intent )
Activity B wants to return data on Activity A when it ends using setResult
on both cases i suggest to create some public static final variables for the extra keys to use.
For example if you need to pass an integer using the key "rating" from A to B i would probably do
class A extends Activity {
public static final String RESULT_STATUS = "RESULT_STATUS";
// Whatever ....
public void startB(int rating) {
Intent toStart = new Intent(this, B.class);
toStart.putExtra(B.EXTRA_RATING, rating);
startActivityForResult(toStart, 0);
}
public void onActivityResult(int requestCode /* 0 in our case */, int resultCode, Intent data) {
if (resultCode == RESULT_OK ) {
String returnedStatus = data.getStringExtra(RESULT_STATUS);
// Whatever ....
}
}
class B extends Activity {
public static final String EXTRA_RATING = "EXTRA_RATING";
public void onCreate(Bundle b) {
// Whatever ....
int rating = getIntent().getIntExtra(EXTRA_RATING,0);
}
// Whatever ....
public void returnDataAndFinish(String status) {
Intent result = new Intent();
result.putExtra(A.RESULT_STATUS, status);
setResult(RESULT_OK, result);
finish();
}
}
Following an example from Professional Android 2 Application Development I set up a pref class as follows:
//Preferences.java
public class Preferences extends PreferenceActivity{
public static final String PREF_SPEED_UNIT ="PREF_SPEED_UNIT";
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.userpreferences);
}
}
In my activity class:
// main.java
private static final int SHOW_PREFERENCES = 1;
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == SHOW_PREFERENCES)
updateFromPreferences();
if (resultCode == Activity.RESULT_OK) {
}
}
private void updateFromPreferences() {
Log.d(TAG, "updateFromPreferences()");
Context context = getApplicationContext();
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(context);
// Set the SpeedMode string using object reference to custom view
mSpeedMode = prefs.getString(Preferences.PREF_SPEED_UNIT, "MPH");
speedview.SpeedMode = mSpeedMode;
}
// Using have a Button view that pops the options for testing
private OnClickListener optionbuttonCL = new OnClickListener() {
public void onClick(View v) {
Context context = getApplicationContext();
Intent i = new Intent(context, Preferences.class);
startActivityForResult(i, SHOW_PREFERENCES);
}
};
The issue is here:
// SpeedView.java
if (SpeedMode == "MPH"){
// set speed in miles/hour
}
if (SpeedMode == "KPH"){
//set speed in kilometers/hour
}
It works, however if I switch speed modes to KPH (default is MPH), the display no longer updates.
The bewildering thing is even if SpeedMode is shown to be "MPH" or "KPH" using the Eclipse debugger, the if statements will not execute.
Here is the rest of the code:
//userpreferences.xml
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference android:key="PREF_SPEED_UNIT"
android:title="Speed Unit"
android:summary="Choose between MPH or KPH"
android:entries="#array/speed_options"
android:entryValues="#array/speed_values"
android:dialogTitle="Speed Unitz"
android:defaultValue="MPH" />
</PreferenceScreen>
// arrays.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="speed_options">
<item>MPH</item>
<item>KPH</item>
</string-array>
<string-array name="speed_values">
<item>MPH</item>
<item>KPH</item>
</string-array>
Thanks
What is speedview.SpeedMode? Where is it declared. I'll bet your problem is
SpeedMode == "MPH"
Change it to
Speedmode.equals("MPH");
Also, by convention in java and languages that use camelCase, variables should be lowercase.
By variables being lowercase, I mean the first letter of the variable. So if you had a class MyClass. You would declare it
MyClass myClass;
That way you know you're not trying to access class methods instead of instance methods.
This is a good explanation on why you need to use .equals() instead of ==
http://leepoint.net/notes-java/data/expressions/22compareobjects.html