I am trying to change the text of a TextView on my Activity. It happens in a method in the same class as the onCreate method. However, it does not work. I've googled it but found nothing.
This is the error I got:
Attempt to invoke virtual method 'android.content.pm.ApplicationInfo android.content.Context.getApplicationInfo()' on a null object reference.
This is the Main Activity, where my TextView is located:
private static TextView welcome;
private static TextView counter;
private static int number;
private static SharedPreferences sharedPreferences;
#Override
protected void onCreate(Bundle savedInstanceState) {
//Shared Preferences getting called to see if the user has set his name
SharedPreferences sharedpreferences = getSharedPreferences("name", Context.MODE_PRIVATE);
//Getting number
this.number = sharedpreferences.getInt("number", 0);
this.sharedPreferences = sharedpreferences;
Boolean continueName = false;
//Checking if name is set
if (!sharedpreferences.getBoolean("nameSet", false)) {
//If name is not set
Intent intent = new Intent(this, Name.class);
startActivity(intent);
} else {
//if name was already set, default activity pops Up
continueName = true;
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//getting counter and setting it
TextView count = (TextView) findViewById(R.id.txtNumber);
this.counter = count;
//Actionlistener to +1 Button
ActionListeners al = new ActionListeners();
Button plusOne = (Button) findViewById(R.id.btnAddOne);
plusOne.setOnClickListener(al.getPlusOneListener());
//Setting Text View Object
this.welcome = (TextView) findViewById(R.id.welcomeUser);
//If the name is set
if (continueName) {
this.welcome.setText(getString(R.string.welcome) + " " + sharedpreferences.getString("usersName", ""));
}
}
public void setNameNew() throws InterruptedException {
TextView welcomeThis = this.welcome;
new Thread(new Runnable() {
public void run() {
//Setting welcome text
SharedPreferences sp = getSharedPreferences("name", Context.MODE_PRIVATE);
welcomeThis.setText(getString(R.string.welcome) + " " + sp.getString("usersName", ""));
}
});
Thread.sleep(500);
this.welcome.setText(welcomeThis.getText());
}
public void changeViewNumber(int number) {
//Setting new number
this.counter.setText(number);
}
}
Weird is, that the setNameNew method is working and can change the text of the TextField. But the changeViewNumber method is not working.
Im on the activity where the TextView is located. I can't figure it out. May you please help me?
You can call setText for a TextView anywhere in the class as long as the TextView is referenced. When you say one function is working and the other isn't, it's because the reference for the counter is incorrect.
Your counter reference
TextView count = (TextView) findViewById(R.id.txtNumber);
this.counter = count;
Your welcome reference
this.welcome = (TextView) findViewById(R.id.welcomeUser);
You should be referencing the view the way you referenced welcome. You'll want to change the counter reference to the following.
this.counter = (TextView)findViewById(R.id.txtNumber)
Your count variable does nothing and should be removed.
I would also like to make additional notes for your code. You are using the keyword this, it isn't necessary for your code.
The this keyword refers to the current object in a method or constructor.
The most common use of the this keyword is to eliminate the confusion between class attributes and parameters with the same name (because a class attribute is shadowed by a method or constructor parameter.
I would also strongly recommend not putting the main thread to sleep, if the thread is sleeping and action is required it will cause your app to crash.
This is useless
TextView count = (TextView) findViewById(R.id.txtNumber);
this.counter = count;
Just do
counter = findViewById(R.id.txtNumber);
This is because you've declared welcome variable globally in class and initialized in onCreate but you forget to initialize counter on the OnCreate method which is why it is throwing a null pointer exception.
this.counter = (TextView) findViewById(R.id.txtNumber);
just initialize your counter variable just like you did on your welcome variable.
The problem was, that I tried to set the text of a TextView with an Integer
The fix was:
String numberString = Integer.toString(number);
counter.setText(numberString);
Related
I am working through a Udemy course and we're building a basic "Higher or Lower" app. My app essentially works, however the random number it chooses for us to guess is always the same no matter how many times I destroy and relaunch the activity.
My MainActivity.java:
//mad import statements here
public class MainActivity extends AppCompatActivity {
int correctNumber;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int correctNumber = generateNum();
}
protected int generateNum(){
Random rand = new Random();
int randNum = rand.nextInt(100);
return randNum;
}
protected void numberEval(View view) {
EditText enteredNumber = (EditText) findViewById(R.id.numberEntry);
String numberString = enteredNumber.getText().toString();
Button pressMe = (Button) findViewById(R.id.button);
int numToEval = Integer.parseInt(numberString);
String result;
TextView showWinLose = (TextView) findViewById(R.id.winLoseText);
if (numToEval > correctNumber) {
result = "Too high!";
} else if (numToEval < correctNumber) {
result = "Too Low!";
}else {
result = "You guessed it!";
}
showWinLose.setText(result);
}
}
Super super basic, yes? Originally, my numberEval() method called generateNum(), but then I realized it was generating a new number to guess every time I pressed the button. So I set it the way it was here, where onCreate() generates correctNumber only once and correctNumber is now a class variable. Now it doesn't generate a new number every button click, but it won't seem to generate a new number at all. It's stuck at 0 no matter how any times I launch, close, relaunch, etc. the app.
How can I fix this? Thanks in advance.
public class MainActivity extends AppCompatActivity {
int correctNumber;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int correctNumber = generateNum();
}
// ...
}
The last line in onCreate() declares a local variable named correctNumber. This hides the class field with the same name and is only available inside onCreate(). To fix the problem, remove int from this line so that you use the class field instead.
I'm trying to create an app for my own use, and I'm trying to save 3 editText boxes to Sharedpref so I can use those values to calculate things later in the app.
Here's the code:
SharedPreferences mSharedPreferences;
private EditText mEditTextBench;
private EditText mEditTextSquat;
private EditText mEditTextDead;
private Button mButton;
public String maxDead = mSharedPreferences.getString("maxDead", "DEFAULT");
Then in the oncreate method I have:
mSharedPreferences= PreferenceManager.getDefaultSharedPreferences(this.getBaseContext());
mButton = (Button) findViewById(R.id.button);
mEditTextBench = (EditText) findViewById(R.id.editTextBench);
mEditTextSquat = (EditText) findViewById(R.id.editTextSquat);
mEditTextDead = (EditText) findViewById(R.id.editTextDead);
and my button onclicklistener:
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putString("maxDead", mEditTextDead.getText().toString());
editor.commit();
If I put the public String maxDead as a final string in the onCreate method, it works, but I want to be able to change the string in the future, using the editText. I don't think I can put it as a final.
The way the code is now, I get this error:
Attempt to invoke interface method 'java.lang.String android.content.SharedPreferences.getString(java.lang.String, java.lang.String)' on a null object reference
your code should be like this.
SharedPreferences mSharedPreferences;
private EditText mEditTextBench;
private EditText mEditTextSquat;
private EditText mEditTextDead;
private Button mButton;
public String maxDead;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout);
mSharedPreferences= PreferenceManager.getDefaultSharedPreferences(this.getBaseContext());
maxDead = mSharedPreferences.getString("maxDead", "DEFAULT");
mButton = (Button) findViewById(R.id.button);
mEditTextBench = (EditText) findViewById(R.id.editTextBench);
mEditTextSquat = (EditText) findViewById(R.id.editTextSquat);
mEditTextDead = (EditText) findViewById(R.id.editTextDead);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putString("maxDead", mEditTextDead.getText().toString());
editor.commit();
}
});
}
EDIT : here I am showing my way of using SharedPreference
SharedPreferences myPreference;
String MY_PREFERENCE = "my_preference";
inside onCreate initialise SharedPreference:
myPreference = getSharedPreferences(MY_PREFERENCE, Context.MODE_PRIVATE);
for getting value
String data = myPreference.getString("maxDead", "")
for editing SharedPreference :
SharedPreferences.Editor editor = myPreference.edit();
editor.putString("maxDead", mEditTextDead.getText().toString());
editor.commit();
I hope this will help.
I am also very new to Android but I'll try to answer. The reason why you are getting the exception is because when the Activity is created there is nothing in the String maxDead, given it is assigned on the top as private String maxDead. You only assign a value to it when you click your button. Where do you want to use this value? I can't comment yet, that's why I am writing this in an answer. :(
This is an example of how I use SharedPreferences:
SharedPreferences spref = getSharedPreferences("MY_PREFS", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = spref.edit();
editor.putString("maxDead", mEditTextDead.getText().toString());
editor.apply;
And then somewhere (another activity/fragment) where you need the value:
String maxDead = spref.getString("maxDead", "");
You're getting the error because of this :
public String maxDead = mSharedPreferences.getString("maxDead", "DEFAULT");
as you've not initialized mSharedPreferences so, its throwing NullPointerException.
change this to :
public String maxDead;
and then initialize maxDead in your onCreate method after you initialize mSharedPreferences :
maxDead = mSharedPreferences.getString("maxDead", "DEFAULT");
UPDATE
You're not getting the updated value of the maxDead inside the onClickListener as the value of the variable maxData is set only once in the onCreate. So the variable is not updated when the value of maxData is updated in the SharedPreferences. So, instead of keeping a variable you should use a method like this to get the latest value from the SharedPreference :
private String getMaxDead(){
if(mSharedPreferences == null)
mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this.getBaseContext());
return mSharedPreferences.getString("maxDead", "DEFAULT");
}
So use : getMaxDead() in your toast and it will work.
I am new to android programming and I created a simple calculator. I want the user to be able to pause the application without losing the numbers entered in the two EditText boxes. I am trying to use shared preferences but for some reason my app keeps crashing. How can I fix this?
package com.example.simplecalculator;
import android.os.Bundle;
import android.app.Activity;
import android.content.SharedPreferences;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import com.example.simplecalculator.*;
public class MainActivity extends Activity {
SharedPreferences mySharedPreferences;
SharedPreferences.Editor editor;
public static final String MYPREFERENCES = "MyPreferences_001";
float answer;
final EditText numberone = (EditText)findViewById(R.id.number1);
final EditText numbertwo = (EditText)findViewById(R.id.number2);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mySharedPreferences = getSharedPreferences(MYPREFERENCES, 0);
String number1 = mySharedPreferences.getString("number1", null);
String number2 = mySharedPreferences.getString("number2", null);
numberone.setText(number1);
numbertwo.setText(number2);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void Addition(View view) {
answer = Float.parseFloat(numberone.getText().toString()) + Float.parseFloat(numbertwo.getText().toString());;
TextView value = (TextView)findViewById(R.id.answer);
value.setText("Your sum is " + answer);
}
public void Subtraction(View view) {
answer = Float.parseFloat(numberone.getText().toString()) - Float.parseFloat(numbertwo.getText().toString());;
TextView value = (TextView)findViewById(R.id.answer);
value.setText("Your difference is " + answer);
}
public void Multiplication(View view) {
answer = Float.parseFloat(numberone.getText().toString()) * Float.parseFloat(numbertwo.getText().toString());;
TextView value = (TextView)findViewById(R.id.answer);
value.setText("Your product is " + answer);
}
public void Division(View view) {
answer = Float.parseFloat(numberone.getText().toString()) / Float.parseFloat(numbertwo.getText().toString());;
TextView value = (TextView)findViewById(R.id.answer);
value.setText("Your quotient is " + answer);
}
public void Power(View view) {
answer = (float) Math.pow(Float.parseFloat(numberone.getText().toString()), Float.parseFloat(numbertwo.getText().toString()));
TextView value = (TextView)findViewById(R.id.answer);
value.setText("Your answer is " + answer);
}
public void Root(View view) {
answer = (float) Math.sqrt(Float.parseFloat(numberone.getText().toString()));
TextView value = (TextView)findViewById(R.id.answer);
value.setText("Your answer is " + answer);
}
public void onPause(){
mySharedPreferences = getSharedPreferences(MYPREFERENCES, Activity.MODE_PRIVATE);
editor = mySharedPreferences.edit();
editor.putString("number1", numberone.getText().toString());
editor.putString("number2", numbertwo.getText().toString());
editor.commit();
}
}
final EditText numberone = (EditText)findViewById(R.id.number1);
final EditText numbertwo = (EditText)findViewById(R.id.number2);
Keep that inside onCreate(), after setContentView()
Also,
What happens the first time, when nothing is stored in sharedPref,
String number1 = mySharedPreferences.getString("number1", null);
String number2 = mySharedPreferences.getString("number2", null);
return some value then instead of "null" .
If using SharedPref pretty often for a Calculator app, i suggest making a function for get and put the sharedPref..
Something like:
public static void saveDataToPreferences(String key,
String value) {
SharedPreferences prefs = context.getSharedPreferences("your package name",
Context.MODE_PRIVATE);
Editor editor = prefs.edit();
editor.putString(key, value);
editor.commit();
}
public static String getDataFromPreferences(String key) {
SharedPreferences prefs = context.getSharedPreferences("your package name",
Context.MODE_PRIVATE);
return prefs.getString(key, Constants.BLANK);
}
If the functions are inside your activity, the context for that activity can be declared globally. Else pass that in the arguments.
Your application is crashing because you are trying to initializing your view before setting any layout to your activity. Now, initialize the as follows...your problem will be solved.
EditText numberone;
EditText numbertwo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
numberone = (EditText)findViewById(R.id.number1);
numbertwo = (EditText)findViewById(R.id.number2);
}
Try this..
You have initilize your EditText before onCreate do that inside onCreate
float answer;
final EditText numberone;
final EditText numbertwo;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
numberone = (EditText)findViewById(R.id.number1);
numbertwo = (EditText)findViewById(R.id.number2);
You are getting NULL Pointer exception most probably. Its because at first when your application sharedprefrences doesn't have any thing, you tend to access it and get a value from it and when its not present you set value of string NULL. When you try to show that value which is NULL on the screen, it crashes.
Do this:
String number1 = mySharedPreferences.getString("number1", "");
String number2 = mySharedPreferences.getString("number2", "");
I think you need to use onSaveInstanceState() and onRestoreInstanceState() for this purpose.
It's used when the Activity is forcefully terminated byactivity is destroyed due to normal app behavior, such as when the user presses the Back button or your activity signals its own destruction by calling finish() or the OS (ex: when your Activity is in the background and another task needs resources) . When this happens, onSaveInstanceState(Bundle outstate) will be called and it's up to your app to add any state data you want to save in outstate.
When the user resumes your Activity, onCreate(Bundle savedInstanceState) gets called and savedInstanceState will be non-null if your Activity was terminated in a scenario described above. Your app can then grab the data from savedInstanceState and regenerate your Activity's state to how it was when the user last saw it.
Basically in onCreate, when savedInstanceState is null, then it means this is a 'fresh' launch of your Activity. And when it's non-null (if your app saved the data in onSaveInstanceState(...), it means the Activity state needs to be recreated.
Here is much more detail about it
when I'm launching my application and the onResume() method is being run, something goes wrong when reading from my SharedPreferences. This is how the code looks.
static double cowCount = 197, income, cowMult = 1;
...
protected void onResume() {
super.onResume();
SharedPreferences sharedPref = getSharedPreferences("com.example.cowcount", Context.MODE_PRIVATE);
cowCount = sharedPref.getFloat("cowCount", 0);
cowMult = sharedPref.getFloat("cowMult", 0);
income = sharedPref.getFloat("income", 0);
}
...
When the code is like this, the application is being frozen. The application consists of a counter, and when I push the button that is supposed to count up, nothing happens.
However, when i comment out the line where i assign a value to the cowMult double from the SharedPreferences, the application doesn't freeze.
cowCount = sharedPref.getFloat("cowCount", 0);
// cowMult = sharedPref.getFloat("cowMult", 0);
income = sharedPref.getFloat("income", 0);
To be clear, the above works fine.
This is the method called when pushing the button (that is supposed to higher the value of cowCount by one):
public void addCow (View view) {
cowCount = cowCount + cowMult;
refresh();
}
...
public void refresh () {
TextView myTextView = (TextView)findViewById(R.id.myText);
myTextView.setText("You Have " + String.valueOf((nf.format(cowCount)) + " Cows!"));
}
Change your code as follows:
static float cowCount, income, cowMult;
...
protected void onResume()
{
super.onResume();
SharedPreferences sharedPref = getSharedPreferences("com.example.cowcount", Context.MODE_PRIVATE);
cowCount = sharedPref.getFloat("cowCount", 197);
cowMult = sharedPref.getFloat("cowMult", 1);
income = sharedPref.getFloat("income", 0);
}
...
The second parameter in SharedPreferences.getFloat() is a default value that the method will return if the key is not found. With the code you've supplied, If you've not saved the values to SharedPreferences properly, those variables will be assigned a value of 0. This is why nothing changes when you press the button; you're adding 0. Check to make sure you are saving to SharedPreferences correctly.
Also, there's no point in initializing the variables when you declare them, as they all get assigned a value in the onResume method, be it a saved value or a default value.
And, as pointed out by Martin, assign your TextView in your onCreate method.
A couple of things are strange with the code you have posted
1 why are you calling
SharedPreferences sharedPref = getSharedPreferences(null, Context.MODE_PRIVATE);
and not
SharedPreferences sharedPref = getSharedPreferences( "com.myname.myapp", Context.MODE_PRIVATE);
2 your onResume should be the following
super.onResume();
SharedPreferences sharedPref = getSharedPreferences(null, Context.MODE_PRIVATE);
cowCount = Double.longBitsToDouble(sharedPref.getLong("cowCount", 0));
cowMult = Double.longBitsToDouble(sharedPref.getLong("cowMult", 0));
income = Double.longBitsToDouble(sharedPref.getLong("income", 0));
calling the super.onResume() first before your code (same with all life cycle methods)
EDIT
3. Why are you not just setting your values to be an int (from what you said above they seem to be) or a float which will give you possibly all the precision then you can just get your values using
getInt(String key, int defValue)
of
getFloat(String key, float defValue)
Seconded Edit
There are a few strange ways you are doing things in the code that I can see. try the following code and let me know if it fixed the problem (though I can't see how the sharedPreferences would be causing it ). i am presuming the addCow method is being called from an onClickListener
//get a reference for your myTextView in the onCreate() method, after declaring your variable
//outside the onCreate method i.e
TextView myTextView;
...
// int onCreate()
myTextView = (TextView)findViewById(R.id.myText);
//you don't need to pass a view parameter, so don't
public void addCow () {
cowCount = cowCount + cowMult;
refresh();
}
...
public void refresh () {
//the way you are getting a string value is also not what I would do either use
//Float.toString(cowCount) or just
myTextView.setText("You Have " + cowCount + " Cows!"));
}
Hope the issue is gone.
I'm a rookie programmer, and I'm trying to setup a function to pass a TextView or an array of TextViews to a function, so it can be called at various points in the activity.
public class ScoreboardActivity extends Activity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scoreboard);
...
final TextView STATVIEW1A = (TextView) findViewById(R.id.place_stat1a); //Team 1
final TextView STATVIEW1B = (TextView) findViewById(R.id.place_stat1b);
final TextView STATVIEW1C = (TextView) findViewById(R.id.place_stat1c);
final TextView STATVIEW1D = (TextView) findViewById(R.id.place_stat1d);
final TextView STATVIEW2A = (TextView) findViewById(R.id.place_stat2a); //Team 2
final TextView STATVIEW2B = (TextView) findViewById(R.id.place_stat2b);
final TextView STATVIEW2C = (TextView) findViewById(R.id.place_stat2c);
final TextView STATVIEW2D = (TextView) findViewById(R.id.place_stat2d);
//final TextView[] STATVIEW = {STATVIEW1A,STATVIEW1B,STATVIEW1C,STATVIEW1D,
// STATVIEW2A,STATVIEW2B,STATVIEW2C,STATVIEW2D};
...
postStats();
... or
postStats(STATVIEW[]);
I want to have a routine to post the (8) TextViews on my activity_scoreobard layout. I have tried just referencing the STATVIEW1A in the function:
public void postStats () {
STATVIEW1AX.setText("#dumps: " + Integer.toString(DUMP1[GAME_NO]));
}
I have also tried referencing each of the TextViews from passing an array of TextViews in the function:
public void postStats (TextView[] VIEWSTAT) {
VIEWSTAT[6].setText("#dumps: "+ Integer.toString(DUMP2[GAME_NO]));
}
While both don't show errors in Eclipse, the program does not like either situation.
Generally it's not a good idea to pass them to function...
but if you want you can try something like this...
TextView[] STATVIEW = new TextView[SIZE];
then to initialize
STATVIEW[0] = (TextView) findViewById(R.id.place_stat1a); //Team 1
STATVIEW[1] = (TextView) findViewById(R.id.place_stat1b);
......
then pass your Array
postStats(STATVIEW);
Alternative would be
create a method and pass the values and set them to TextViews
something like this
public void fillData(String[] data)
{
for (int i=0;i<STATVIEW.length;i++)
{
STATVIEW[i].setText(data[i]);
}
}
It is better to use an array of WeakReference objects to hold the references to your Text views and initialize this array in the OnCreate method of your activity, using this method everytime that system destroy your activity the references to the items can be garbage collected automatically and you won't cause memory leaks. As far as i know the standard way for holding a reference to an ephemeral object like the activity itself or a views on it is to use WeakReference objects.
For understanding what a WeakReference is read the following article on Wikipedia:
http://en.wikipedia.org/wiki/Weak_reference
Also read this page:
https://developer.android.com/reference/java/lang/ref/WeakReference.html
Instead of Overloading postStats() function you can try using postStats(TextView... VIEWSTAT). In this function you can check the number of arguments by VIEWSTAT.length.
ArrayList<TextView> tmpArrayList = new ArrayList<TextView>();
for(int y=0; y<10; y++)
{
tmpArrayList.add(getTextView(txtBoxCount++));
}
this.postStats(tmpArrayList);
private TextView getTextView(int i)
{
int id=0;
try {
id = R.id.class.getField("textview" + i).getInt(0);
}
catch (IllegalArgumentException e) {
e.printStackTrace();
}
catch (SecurityException e) {
e.printStackTrace();
}
catch(IllegalAccessException e) {
e.printStackTrace();
}
catch (NoSuchFieldException e) {
e.printStackTrace();
}
textview = (TextView)findViewById(id);
textview.setTag("0");
return textview;
}
public void postStats (ArrayList<TextView> viewstat) {
//do some work here
}