24

I've really been struggling through this. New to Java/Android. I'm writing my first app and this is the first thing that has taken me longer than a couple days of searching to figure out. Here's the setup: It's a BAC calculator / drink counter:

alt text

A formula is used to calculate the BAC. Here's the forumla:

Bac = ((StandardDrinks / 2) * (GenderConstant / Weight)) - (0.017 * Hours);

So as you can see, being able to modify the gender and weight will produce more accurate and personalized results. So I have them as doubles:

double GenderConstant = 7.5; //9 for female
double Weight = 180;

To change these variables I would like the person to be able to go into the settings and choose different values. I have these things set up, but not linked to the variables shown above because I cannot for the life of me figure out how. Here they are:

alt text

I press the menu button and this pops up. Great. I'll click Settings.

alt text

Now the preferences pops up. Here is my preferences.xml:

<?xml version="1.0" encoding="utf-8"?>
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

 <PreferenceCategory android:title="Personal Settings">


 <ListPreference
 android:title="Gender"
 android:summary="Verify or deny the presence of a Y chromosome."
 android:key="genderPref"
 android:defaultValue="male"
 android:entries="@array/genderArray"
 android:entryValues="@array/genderValues" />

 <ListPreference
 android:title="Weight"
 android:summary="How much the planet pulls on you, in pounds."
 android:key="weightPref"
 android:defaultValue="180"
 android:entries="@array/weightArray"
 android:entryValues="@array/weightValues" />

 </PreferenceCategory>

<PreferenceCategory android:title="Drink Settings">

 <ListPreference
 android:title="Beer Size"
 android:summary="The volume of your beer, in ounces."
 android:key="beerPref"
 android:defaultValue="12"
 android:entries="@array/beerArray"
 android:entryValues="@array/beerValues" />

 <ListPreference
 android:title="Shot Size"
 android:summary="The volume of your shot, in ounces."
 android:key="shotPref"
 android:defaultValue="1.5"
 android:entries="@array/shotArray"
 android:entryValues="@array/shotValues" />

 <ListPreference
 android:title="Wine Size"
 android:summary="The volume of your wine, in ounces."
 android:key="winePref"
 android:defaultValue="5"
 android:entries="@array/wineArray"
 android:entryValues="@array/wineValues" />


 </PreferenceCategory>
 </PreferenceScreen>

Onward to the weight ListPreference:

alt text

And that shows up. The values are stored as string-arrays in res/values/arrays.xml. Here's a sample, of just the weight ones:

<string-array name="weightArray">
<item>120 lbs</item>
<item>150 lbs</item>
<item>180 lbs</item>
<item>210 lbs</item>
<item>240 lbs</item>
<item>270 lbs</item>
 </string-array>
 <string-array name="weightValues">
<item>120</item>
<item>150</item>
<item>180</item>
<item>210</item>
<item>240</item>
<item>270</item>
 </string-array>

This is basically as far as I've gotten. I can click a value, sure, but it doesn't change the formula because it's not linked with the doubles I created in DrinkingBuddy.java. All of the stuff displayed in the settings are just empty shells for now, including the spinner on the main layout (the default time is just set to 1 hour)

I did create a Preferences.java and have tried implementing various combinations of code found in tutorials and resources around the web, but to no avail. Here it is anyway, filled with failed attempts to make beerPref (the settings option to change how many ounces in the beer) correlate with a variable in my main class:

package com.dantoth.drinkingbuddy;


 import android.app.Activity;
 import android.content.SharedPreferences;
 import android.os.Bundle;
 import android.preference.Preference;
 import android.preference.PreferenceActivity;
 import android.preference.Preference.OnPreferenceClickListener;


 public class Preferences extends PreferenceActivity {

public static final String PREF_BEER_SIZE = "PREF_BEER_SIZE";

@Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 addPreferencesFromResource(R.xml.preferences);

 //Get the custom preference



 Preference beerPref = (Preference) findPreference("beerPref");
 beerPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {

 public boolean onPreferenceClick(Preference preference) {

 SharedPreferences customSharedPreference = getSharedPreferences("myCustomSharedPrefs", Activity.MODE_PRIVATE);
 SharedPreferences.Editor editor = customSharedPreference.edit();

 editor.commit();
 return true;
 }}

 );}
 }

A full on tutorial and sample code would be AWESOME as I've yet to find any reliable guides out there.

Michael Petrotta
  • 59,888
  • 27
  • 145
  • 179
Dan T
  • 487
  • 2
  • 4
  • 12
  • it seems like you have code here to save a preference... but is your code for "the formula" *reading* from the place where the preference is saved? – matt b Jun 10 '10 at 04:28
  • Ummm I don't think so. I have 2 .java files: DrinkingBuddy.java and Preferences.java. The latter is the last bit of code shown, while everything else is in DrinkingBuddy.java. Once again, everything below the line that "addsPreferencesFromResource..." is just crap that I threw in there to try to get it to work. – Dan T Jun 10 '10 at 05:12
  • Here are a couple of tutorials that helped me: http://viralpatel.net/blogs/android-preferences-activity-example/ and http://www.brighthub.com/mobile/google-android/articles/116373.aspx – MarkHu Jan 15 '13 at 23:58

3 Answers3

17

I'm still working all this out myself, but (somewhat adapted from my version) I think your Preferences class only needs to do the following:

public class Preferences extends PreferenceActivity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // load the XML preferences file
        addPreferencesFromResource(R.xml.preferences);
    }
}

Then in your main class, you can refer to the preferences:

public class DrinkingBuddy extends Activity 
                           implements OnSharedPreferenceChangeListener {

    private int weight;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);

        // register preference change listener
        prefs.registerOnSharedPreferenceChangeListener(this);

        // and set remembered preferences
        weight = Integer.parseInt((prefs.getString("weightPref", "120")));
        // etc
    }

    // handle updates to preferences
    public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
        if (key.equals("weightValues")) {
            weight = Integer.parseInt((prefs.getString("weightPref", "120")));
        }
        // etc
    }
}

The saving of preference updates is handled for you.

(Not too sure about public/private declarations!)

Liggliluff
  • 706
  • 1
  • 6
  • 22
ChrisV
  • 8,748
  • 3
  • 48
  • 38
  • Hmmm this is very strange. I used BeerOunces so I could test it (I have a toast that says "You added a x oz beer"). Now the thing is... the variable keeps the value that I assign it at the beginning (12), but when it displays in the toast it shows the preference value (24). Even if I change the original to just BeerOunces; (with no value assigned) it just factors into the equation as a zero, while the toast displays 24. WTHell. – Dan T Jun 12 '10 at 06:03
  • I cant really debug your app for you :) but I realise I referred to preference weightValues which I think should have been weightPref (now corrected) – ChrisV Jun 12 '10 at 13:25
  • @ChrisV : +1. Good Answer. Can Shared Preferences's XML file be viewed by someone if they have the phone(like export the XML file like you can expor the DB)? I ask this because, I intend to store the the username and passowrd of the current user in Shared Preference. – Ashwin Sep 04 '12 at 10:37
4

You are requesting probably two different set of preference files.

Make sure you store the ListPreference values in the same files. Start up adb roll to the cd /data/data/com.your.package and look for folders and files of type preferences.

I think the bug is that you specify a different file than the one the setting has been saved too:

Try changing this:

SharedPreferences preferences = getSharedPreferences(PREF_FILE_NAME, MODE_PRIVATE);

to

SharedPreferences preferences = PreferenceManager
                .getDefaultSharedPreferences(context);

Then you will probably have to query only

preferences.getString('weightPref', null);

Also you do not need the Editor. The preferences are saved automatically.

Pentium10
  • 204,586
  • 122
  • 423
  • 502
  • No, I think my problem is much more fundamental. There is no bug, just a lack of knowing how. – Dan T Jun 10 '10 at 18:38
  • 2
    @Dan T Have you checked what I told? It's very important, if you have two different files to store preferences that won't work out well. – Pentium10 Jun 11 '10 at 08:55
  • Yes it's all good there, I just hadn't implemented any of the necessary code. Thanks! – Dan T Jun 11 '10 at 17:59
0

For most apps, it is most convinient to use the default shared preferences. You can get from anywhere in you app them with:

SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);

You can save new variables into it with:

sp.edit().putString("var_name", "var value".apply();
dev4life
  • 10,785
  • 6
  • 60
  • 73