Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

Android, SharedPreferences small bit of help?

Options
  • 25-02-2013 1:55pm
    #1
    Registered Users Posts: 3,515 ✭✭✭


    ey, so I've been searching around, and thinking for past two hours, but seems like I am just too retarded for this, anyway:

    Here is a class that is supposed to generate random values, assign a currency sign from sharedpreferences (selected on different activity/class), then stored in variables.
    Seems fine. But..

    package com.example.droid;

    import java.text.DecimalFormat;

    import android.app.Activity;
    import android.content.Context;
    import android.content.SharedPreferences;

    public class ObtainCurrentMon extends Activity{
    boolean loggedIn;
    double inc;
    double exp;
    DecimalFormat curency = new DecimalFormat("###.##");
    public static final String PREFS_NAME = "Sets";


    //Temporary values:
    public String GetCurrentExpense(){
    this.exp = Math.random()*100;
    SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
    return settings.getString("SelectedCur", "€")+curency.format(exp);
    }
    public String GetCurrentIncome(){
    this.inc = Math.random()*100;
    if( exp > inc){
    this.inc = Math.random()*100;
    }
    SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
    return settings.getString("SelectedCur", "€").toString()+curency.format(inc);
    }


    }


    In different class, it's supposed to take those variables and assign them to label/textview.
    It has exception throwing ERROR #2 if something goes wrong.

    try{
    SetTexter(ocm.GetCurrentExpense(), R.id.CurMonth_Exp);
    SetTexter(ocm.GetCurrentIncome(), R.id.CurMonth_Inc);
    }
    catch(Exception e){
    SetTexter("ERROR #2", R.id.CurMonth_Exp);
    SetTexter("ERROR #2", R.id.CurMonth_Inc);
    }

    So when I use: return settings.getString("SelectedCur", "€")+curency.format(exp);
    It throws ERROR #2
    but when I use just:
    "€"+curency.format(exp); it works fine, generates values and then also outputs them no problem.
    As far as I am aware, if it doesn't get sharedpref it should return € right? but it doesn't I think.

    Help?


Comments

  • Registered Users Posts: 18,272 ✭✭✭✭Atomic Pineapple


    When you don't catch the exception what is the exception thrown in the stack trace? Or print the exception when you catch it.

    Have you tried:
    settings.getString("SelectedCur", "€")+[B]([/B]curency.format(inc)[B])[/B];
    

    ?


  • Registered Users Posts: 3,515 ✭✭✭arleitiss


    draffodx wrote: »
    When you don't catch the exception what is the exception thrown in the stack trace? Or print the exception when you catch it.

    Have you tried:
    settings.getString("SelectedCur", "€")+[B]([/B]curency.format(inc)[B])[/B];
    
    ?
    Didn't work,
    Check the exception thrown for more info?
    All it gives me is:
    "
    02-25 14:13:52.169: E/AndroidRuntime(30194): FATAL EXCEPTION: main
    02-25 14:13:52.169: E/AndroidRuntime(30194): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.droid/com.example.droid.MainActivity}: java.lang.NullPointerException
    02-25 14:13:52.169: E/AndroidRuntime(30194): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1573)
    02-25 14:13:52.169: E/AndroidRuntime(30194): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
    02-25 14:13:52.169: E/AndroidRuntime(30194): at android.app.ActivityThread.access$1500(ActivityThread.java:117)
    02-25 14:13:52.169: E/AndroidRuntime(30194): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
    02-25 14:13:52.169: E/AndroidRuntime(30194): at android.os.Handler.dispatchMessage(Handler.java:99)
    02-25 14:13:52.169: E/AndroidRuntime(30194): at android.os.Looper.loop(Looper.java:130)
    02-25 14:13:52.169: E/AndroidRuntime(30194): at android.app.ActivityThread.main(ActivityThread.java:3687)
    02-25 14:13:52.169: E/AndroidRuntime(30194): at java.lang.reflect.Method.invokeNative(Native Method)
    02-25 14:13:52.169: E/AndroidRuntime(30194): at java.lang.reflect.Method.invoke(Method.java:507)
    02-25 14:13:52.169: E/AndroidRuntime(30194): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
    02-25 14:13:52.169: E/AndroidRuntime(30194): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
    02-25 14:13:52.169: E/AndroidRuntime(30194): at dalvik.system.NativeStart.main(Native Method)
    02-25 14:13:52.169: E/AndroidRuntime(30194): Caused by: java.lang.NullPointerException
    02-25 14:13:52.169: E/AndroidRuntime(30194): at android.content.ContextWrapper.getSharedPreferences(ContextWrapper.java:146)
    02-25 14:13:52.169: E/AndroidRuntime(30194): at com.example.droid.ObtainCurrentMon.<init>(ObtainCurrentMon.java:15)
    02-25 14:13:52.169: E/AndroidRuntime(30194): at com.example.droid.MainActivity.<init>(MainActivity.java:24)
    02-25 14:13:52.169: E/AndroidRuntime(30194): at java.lang.Class.newInstanceImpl(Native Method)
    02-25 14:13:52.169: E/AndroidRuntime(30194): at java.lang.Class.newInstance(Class.java:1409)
    02-25 14:13:52.169: E/AndroidRuntime(30194): at android.app.Instrumentation.newActivity(Instrumentation.java:1021)
    02-25 14:13:52.169: E/AndroidRuntime(30194): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1565)
    02-25 14:13:52.169: E/AndroidRuntime(30194): ... 11 more
    "


  • Registered Users Posts: 51 ✭✭GavinFlud


    Is the try/catch block in the second class called inside the onCreate() method or after that method has been overridden? I seem to remember having an issue with SharedPreferences because I was trying to access them in the constructor before the onCreate() method was ever called.


  • Registered Users Posts: 3,515 ✭✭✭arleitiss


    GavinFlud wrote: »
    Is the try/catch block in the second class called inside the onCreate() method or after that method has been overridden? I seem to remember having an issue with SharedPreferences because I was trying to access them in the constructor before the onCreate() method was ever called.

    Yes it's in onCreate block.


  • Registered Users Posts: 3,515 ✭✭✭arleitiss


    For some reason I feel it has something to do with:
    public class ObtainCurrentMon extends Activity{
    and
    SharedPreferences.

    I tried also declaring this class as Activity in manifest but that didn't change anything.


  • Advertisement
  • Registered Users Posts: 51 ✭✭GavinFlud


    Is ObtainCurrentMon actually an activity or is it just an object with helper methods like GetCurrentExpense()? If it doesn't need to be an activity then there's no need to extend the Activity class.


  • Registered Users Posts: 3,515 ✭✭✭arleitiss


    GavinFlud wrote: »
    Is ObtainCurrentMon actually an activity or is it just an object with helper methods like GetCurrentExpense()? If it doesn't need to be an activity then there's no need to extend the Activity class.

    Okay, it's just a helper class with functions shared across 9 activities.
    However:
    If I don't type extend Activity I cannot use SharedPreferences then as it needs it to be activity which fails.

    So I don't know a workaround - not that this way works anyway.


  • Registered Users Posts: 51 ✭✭GavinFlud


    You need a context to use SharedPreferences. You could simply pass the context of the second class to the constructor of ObtainCurrentMon and then call context.getSharedPreferences(PREFS_NAME, 0).

    See here for a more thorough explanation of what I mean.


  • Registered Users Posts: 3,515 ✭✭✭arleitiss


    GavinFlud wrote: »
    You need a context to use SharedPreferences. You could simply pass the context of the second class to the constructor of ObtainCurrentMon and then call context.getSharedPreferences(PREFS_NAME, 0).

    See here for a more thorough explanation of what I mean.

    So wait,
    does this
    private static final String PREFERENCES = "tourist_guide_preferences"; private SharedPreferences settings; private SharedPreferences.Editor editor; private Context context; public Persistence(Context context) { this.context = context; settings = context.getSharedPreferences(PREFERENCES, 0); editor = settings.edit(); }

    go to main class/activity or the ObtainCurmonth?


  • Registered Users Posts: 51 ✭✭GavinFlud


    arleitiss wrote: »
    So wait,
    does this
    private static final String PREFERENCES = "tourist_guide_preferences"; private SharedPreferences settings; private SharedPreferences.Editor editor; private Context context; public Persistence(Context context) { this.context = context; settings = context.getSharedPreferences(PREFERENCES, 0); editor = settings.edit(); }

    go to main class/activity or the ObtainCurmonth?

    You can keep your ObtainCurMonth class practically the same. Just don't extend Activity and call context.getSharedPreferences (where "context" is the context you pass to the ObtainCurMonth constructor when you initialize that object from your second class.


  • Advertisement
  • Registered Users Posts: 3,515 ✭✭✭arleitiss


    damn been more than hour and I still don't get it...


  • Registered Users Posts: 51 ✭✭GavinFlud


    Change your "ObtainCurMonth" class to something like the following:
    public class ObtainCurrentMon {    
      boolean loggedIn;
      double inc;
      double exp;
      DecimalFormat curency = new DecimalFormat("###.##");
      public static final String PREFS_NAME = "Sets";
      Context context;
    
      public ObtainCurrentMon(Context context) {
        this.context = context;
      }
        
      public String GetCurrentExpense() {
        this.exp = Math.random()*100;
        SharedPreferences settings = context.getSharedPreferences(PREFS_NAME, 0);
        return settings.getString("SelectedCur", "&#8364;")+curency.format(exp);
      }
    
      public String GetCurrentIncome() {
        this.inc = Math.random()*100;
        if (exp > inc) {
          this.inc = Math.random()*100;
        }
        SharedPreferences settings = context.getSharedPreferences(PREFS_NAME, 0);
        return settings.getString("SelectedCur", "&#8364;").toString()+curency.format(inc);
      }
    }
    
    and your second class should look something like the following:
    public class SecondClass extends Activity {
      @Override
      public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ObtainCurrentMon ocm = new ObtainCurrentMon(getApplicationContext());
        try {
          SetTexter(ocm.GetCurrentExpense(), R.id.CurMonth_Exp);
          SetTexter(ocm.GetCurrentIncome(), R.id.CurMonth_Inc);
        } catch (Exception e) {
          SetTexter("ERROR #2", R.id.CurMonth_Exp);
          SetTexter("ERROR #2", R.id.CurMonth_Inc);
        }
      }
    }
    
    Obviously these classes might change based on what else you have in them, but you should be able to get the gist of it.


  • Registered Users Posts: 6,465 ✭✭✭MOH


    From the stack trace, you're getting a null pointer exception at the getSharedPreferences call, which means the activity context isn't set.
    Just get rid of the activity and change it to a class, and pass in the context of the activity you're calling it from (as GavinFlud demonstrated).

    You should also initialise exp either in the declaration or constructor, you're going to have a problem if GetCurrentIncome is called before GetCurrentExp.


    You've a potential problem initialising inc. If exp is 99.99999 etc it's going to loop forever looking for a higher value.
    Probably better initialising exp to say
    Math.random()*90
    
    (to ensure you can get a higher value for inc).
    Then set inc to
    exp + Math.random()*(100-exp)
    
    which will still give you a random value between exp and 100, but without having to generate the number repeatedly.

    Also, you don't need the extra .toString in the return statement of GetCurrentIncomehaving to generate the number repeatedly.

    (BTW, code's a lot easier to read if you wrap it in [ code ] tags)


  • Registered Users Posts: 3,515 ✭✭✭arleitiss


    This has been solved, the math.random is just temporary until I set up databases where to get the real values.
    Thanks everyone.


Advertisement