I've created some getters setters in my Application class as so:
public class myApp extends Application{
//"Global" variables
private Boolean musicEnabled = true; //Music on or off?
private Boolean soundEnabled = true; //Sound effects on or off?
#Override
public void onCreate() {
// TODO Auto-generated method stub
musicEnabled = true; //Default value for music
soundEnabled = true; //Default value for sound effects
super.onCreate();
}
//Getter and setter for musicEnabled
public Boolean getMusicOption(){
return musicEnabled; //Getter
}
public void setMusicOption(Boolean value){ //Setter
musicEnabled = value;
}
//Getter and setter for soundEnabled
public Boolean getSoundOption(){
return soundEnabled;
}
public void setMusicOptions(Boolean value){
soundEnabled = value;
}
}
I then get the values in my Activity class as so:
myApp myAppSettings = (myApp)getApplicationContext();
musicEnabled = myAppSettings.getMusicOption();
soundEnabled = myAppSettings.getSoundOption();
This is fine but what I can't figure out is how I can get to them and use them from my corresponding surfaceView class? i.e. the class that starts:
public class mySView extends SurfaceView implements
SurfaceHolder.Callback {
The only way I've manages to do this so far is pass them into my surfaceview class by creating a method like:
public void initialise(Boolean Sound, Boolean Music){
}
And then passing these in from my Activity class like so:
myView.initialise(musicEnabled, soundEnabled).
This works, however it seems a bit messy, I mean I am going to need to use the setters from my 'myView' class to set these value so........ is there anyway I can access them directly from my 'myView' class or do I have to do this from the Activity class?
Thanks all
You can create some method, e.g. init() and call it from all of constructors of your mySView.
In init method you can do the same, as in the Activity:
private void init() {
myApp myAppSettings = (myApp)getContext().getApplicationContext();
musicEnabled = myAppSettings.getMusicOption();
soundEnabled = myAppSettings.getSoundOption();
}
You should just be able to call getContext().getApplicationContext() from inside your custom SurfaceView, and typecast it like you would in your above example. See View.getContext().
Another option would be to save your settings in the SharedPreferences which is accessable anywhere in the App where you have the Context.
This way any changes from the last use of your App will automatically be persisted as can be loaded during next launch without having to return the values to default every launch.
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
Related
I have two classes where I want to access the value of a unique variable. In the first class I want to set the value of a 'isToogleflagon= true'. In the second class I want to get the value of 'IsToogleflagon'.
Here is where I set and get 'IsToogleFlagon'
public class Toogleflag{
private String _isToogleflagon;
public Toogleflag(){}
public Toogleflag(String isToogleflagon) {
this._isToogleflagon=isToogleflagon;
}
public String get_isToogleflagon(){
return _isToogleflagon;
}
public void set_isToogleflagon(String isToogleflagon) {
this._isToogleflagon = isToogleflagon;
}
I want to set the value of isToogleflagon="true" in my main class. Below is part of my main class where I do this.
public class MainActivity extends AppCompatActivity {
Toogleflag toogleflag1 = new Toogleflag();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
toogleflag1.set_isToogleflagon(GlobalVariables.TRUE);
...
Global.values(True)
public class GlobalVariables
{
public static String TRUE = "true";
public static String FALSE = "false";
}
Here's my second class where I want to get the value of isToogleflagon, in this case "true"
public class secondclass {
Toogleflag toogleflag2 = new Toogleflag();
public void test{
String test=toogleflag2.get_isToogleflagon();
}
When I run Class Secondclass the value of 'string test' does not get assigned a value. I want it to be assigned the value of "true". Any advise on how to fix this is greatly appreciated.
thanks,
Jim
This is happening because you are making a new object with default/ no argument constructor. When you make an object with default constructor, all the instance variable gets initialzes with their default values. For example,
1) int variable gets 0
2) boolean variable gets false
3) String variable gets null
That is happening in your case. As in your code it is mentioned that in main class when are you are setting value with String constructor to the variable named isToogleflagon it gets set as your constructor passed value, but when you are accessing the value of that variable again via calling no argument constructor, the variable isToogleflagon gets initiaze with defualt values as well. To get the value consistant across over all the app you need to make that class object as Singleton. It will be solving your problem. Hope you got my point. Below is the sample code for your reference to make singleton
public class Singleton {
private static Singleton singleton = new Singleton( );
/* A private Constructor prevents any other
* class from instantiating.
*/
private Singleton() { }
/* Static 'instance' method */
public static Singleton getInstance( ) {
return singleton;
}
/* Other methods protected by singleton-ness */
protected static void demoMethod( ) {
System.out.println("demoMethod for singleton");
}
}
I have just one class where I need to access SharedPreferences:
public class MyUtils {
public static String packageMe(Object input){
// do stuff here
// need SharedPreferences here
}
public static Object unpackageMe(String input){
// do stuff here
// need SharedPreferences here
}
}
I tried this:
public class MyUtils extends Activity
But, as you know, I cannot access SharedPreferences from a static method.
I thought about passing in the context to the static methods, but that extends the number of classes out to four that I will need to modify, and the classes are already extending AsyncTask:
public class SomeClass01 extends AsyncTask {
#Override
protected Object doInBackground(Object[] params){
MyUtils.packageMe(abc_123_object);
// do stuff here
}
}
So, I thought that maybe I could pass the context into those four classes. However, there are a couple dozen classes that I would need to modify that use those four classes, that in turn use that single class.
public class SomeTopClass extends FragmentActivity implements x, y, z {
new SomeClass01.execute(abc_123_object);
// do stuff here
}
I don't know if I want to be passing a context reference that deep into my code.
I saw here on StackOverflow about putting a reference to the SharedPreferences in my abc_123_object model, but there are quite a few objects I use (other than abc_123_object) and I don't want to have to jerry-rig so many classes.
So, is there a way for me to do this without modifying dozens of classes and passing context references all around my code, or am I stuck?
Thanks
Create static variable in your Application class.
public class MyApp extends Application{
public static Context context;
#Override
public void onCreate() {
context = this;
}
}
Then use it when you need.
public static String packageMe(Object input){
// do stuff here
// need SharedPreferences here
// context = MyApp.context
}
As Dusan mentioned, using an application class is an easy way to do this:
In your application class:
private static MyApplication sInstance = null;
private SharedPreferences mPrefs
public static MyApplication getApp()
{
return sInstance;
}
public SharedPreferences getSharePreferences()
{
return mPrefs;
}
in onCreate():
sInstance = this;
mPrefs = getSharedPreferences(PREF_FILE, MODE_PRIVATE);
Then in your code simply do:
MyApplication.getApp().getSharePreferences();
Your Application's onCreate() is guaranteed to be executed before any activity is created, so unless you are doing something really weird, it should be safe.
I tried to create custom class to fetch some values from SharedPreferences.
My aim is to reach to that values from any class.
I am getting null Pointer exception on
SharedPreferences prefs = getApplicationContext().getSharedPreferences("UserFile", MODE_PRIVATE);
My code is as below;
public class UserInfo extends Application {
private String token;
private String SAVED_USERNAME;
public UserInfo() {
SharedPreferences prefs = getApplicationContext().getSharedPreferences("UserFile", MODE_PRIVATE);
token = prefs.getString("Token", null);
}
public String getToken() {
return token;
}
}
What might be the wrong?
Usually Android components are initialized during their lifecycle. In this particular case you can't access application Context and SharedPreferences because they're not initialized yet.
Second problem might be (thanks to my crystall ball) that you did not added your Application to AndroidManifest
So, your first thought might be to move initialization code from constructor to onCreate. This would solve this particular problem.
However, it's a bad practice to do what you're doing. Because there can be only 1 Application component per application. This will limit you to 1 such singleton per app. Consider using Application to provide application Context as singleton and create another singleton for providing UserInfo.
No examples, please exercise yourself.
Just have this method in a util class. No need to extend application.
public static String getToken(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context).getString("Token", null);
}
There is a rule in android - don't use constructor of app component: Activity/Fragment/Application/Service... there is onCreate() method, because in your constructor context will be null. So move your code to onCreate(). Also you need set your UserInfo as application in Manifest.
You don't create constructor of Application class instead, use the code in onCreate():
#Override
public void onCreate() {
super.onCreate();
SharedPreferences prefs = getApplicationContext().getSharedPreferences("UserFile", MODE_PRIVATE);
token = prefs.getString("Token", null);
}
and use it from any activity:
UserInfo userInfo = (UserInfo)getApplication();
String token = userInfo.getToken();
public class MyApp extends Application {
private static MyApp _instance;
#Override
public void onCreate() {
super.onCreate();
_instance = this;
}
public static MyApp getInstance(){
return _instance;
}
public String getToken() {
return getSharedPreferences("UserFile", MODE_PRIVATE).getString("Token", null);
}
}
In your manifest:
<application
android:name="your.package.MyApp"
>
If you whant use :
String token = MyApp.getInstance().getToken();
Make sure you have registered this class in your AndroidManifest.XML file.
<application android:name=".UserInfo"
...
/>
Note: Your way for accessing shared preferences does not seem good. I rather myself declare a class named PreferencesHelper and put all preferences stuff there.
public class PreferencesHelper{
private SharedPreferences mPrefs;
public PreferencesHelper(Context context){
this.mPrefs = context.getSharedPreferences("name", Context.MODE_PRIVATE);
}
public getToken() {
return mPrefs.getString("Token", null);
}
public String setToken(String token) {
mPrefs.edit().putString("Token", token).apply();
}
}
I have a variable in my class , I want when that variable changed , I do an action in another class .
in fact I want a listener for changing variable in android (my variable may change every minute)
public class Connect {
public static boolean myBoolean;
//some actions do and myBoolean change
}
public class Selection extends Activity implements OnMenuItemClickListener{
//I want a thing like listener here ,when myboolean changed I do an action (myboolean may change every minute)
}
It's not possible directly. However, you can make your field private, add getters and setters, and create a method of adding listeners (this is called the Observer pattern):
interface ConnectionBooleanChangedListener {
public void OnMyBooleanChanged();
}
public class Connect {
private static boolean myBoolean;
private static List<ConnectionBooleanChangedListener> listeners = new ArrayList<ConnectionBooleanChangedListener>();
public static boolean getMyBoolean() { return myBoolean; }
public static void setMyBoolean(boolean value) {
myBoolean = value;
for (ConnectionBooleanChangedListener l : listeners) {
l.OnMyBooleanChanged();
}
}
public static void addMyBooleanListener(ConnectionBooleanChangedListener l) {
listeners.add(l);
}
}
Then, wherever you want to listen to changes of the boolean, you can register a listener:
Connect.addMyBooleanListener(new ConnectionBooleanChangedListener() {
#Override
public void OnMyBooleanChanged() {
// do something
}
});
Adding a method to remove listeners is left as an exercise. Obviously, for this to work, you need to make sure that myBoolean is only changed via setMyBoolean, even inside of Connect.
I need to pass name of a variable created in Class A to the Class B, so I can put a value in that variable (in Class B).
But, in Class B I do not know the name of that variable.
The code is something like this:
Class A
public class A {
int valore; // this is the variable, in Class b, I don't know this name!
public void callClassB(){
ClassB.Method(what shoudld i put here?)
}
}
This is the Class B
public class B {
public void Method(the_Name_Of_TheVariable_I_get){
the_Name_Of_TheVariable_I_get = 5; // i need to do this
}
}
Why do you need the variable name? Simply pass the variable itself. In class B create a method
public int getValore(){
return valore;
}
Then in Class A use modify the code as
public void callClassB(){
ClassB.Method(getValore())
}
I do not really understand what you are trying to achieve here?
You can also use the following appraoch:
interface ValueSetter {
void setValue(int value);
}
Class A
public class A implements ValueSetter{
int valore;
public void callClassB(){
ClassB.Method(this)
}
void setValue(int value){
valore = value;
}
}
This is the class B
public class B{
public void Method(ValueSetter valueSetter){
ValueSetter.setValue(5);
}
}
This is more inline with OOPS..
You will need to use reflection for this.
Here is a tutorial from Oracle: http://docs.oracle.com/javase/tutorial/reflect/index.html
You cant get the name of variable at runtime though. But assuming you have the name of the field the code would look something like this:
this.getClass().getDeclaredField(the_Name_Of_TheVariable_I_get).set(this, 5);
you can pass the name of the variable "valore", then you need reflection to assign it in your method :
a = new A();
Field f = a.getClass().getDeclaredField(varName);
f.set(a, 5);
a can be a parameter too. (it is necessary to give the instance that possesses the member).
However, this is not a recommended way of treating your issue, as it is unreliable in the sense that the compiler will not be able to check you are accessing items that actually exist.
It would be better to use an interface, for instance :
public interface Settable {
public void set(int value);
}
and then:
public class A implements Settable {
private int valore;
public void set(int value) {
valore = value;
}
public void callClassB(){
ClassB.Method(this);
}
}
and in B:
public class B{
public void Method(Settable settable){
settable.set(5);
}
}