null pointer exception when I refer to my custom class? - android

Because my log command kicks out a "4" I am guessing it is:
word.getnewword();
that is returning the null pointer exception, but why?
The aim of the code is to have a class that will hold different letters in a word for me to then animate each letter in the word separately then change the word to a random new one from a list in the class. I am using char for each letter instead of a string for the word or each letter, is that ok also?
package com.xyz.letters;
import ......abreviated
public class letters extends Activity {
private Animals word;
boolean gameover = false;
private AdView adView;
TextView tva;
TextView tvb;
TextView tvc;
TextView tvd;
TextView tve;
TextView tvf;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.letters);
Log.e("main", "xml loaded fine");
tva = (TextView) findViewById(R.id.texta);
tvb = (TextView) findViewById(R.id.textb);
tvc = (TextView) findViewById(R.id.textc);
tvd = (TextView) findViewById(R.id.textd);
tve = (TextView) findViewById(R.id.texte);
tvf = (TextView) findViewById(R.id.textf);
Log.e("main", "textview pre-setup complete");
Log.e("main", "4");
word.getnewword();
Log.e("main", "gotword " + word.getwordchosennumber());
setletters();
Log.e("main", "set letters ok");
......etc
My class:-
package com.xyz.letters;
import java.util.Random;
import android.util.Log;
public class Animals {
private int wordchosen;
private int length;
private char l1;
private char l2;
private char l3;
private char l4;
private char l5;
private char l6;
public Animals() {
this.wordchosen = 0;
this.length = 3;
this.l1 = 'a';
this.l2 = 'b';
this.l3 = 'c';
this.l4 = 'a';
this.l5 = 'b';
this.l6 = 'c';
}
public void getnewword() {
Log.e("animals", "0");
Random ran = new Random();
Log.e("animals", "1");
wordchosen = ran.nextInt(2);
Log.e("animals", "2");
switch (wordchosen) {
case 0:
length = 3;
l1 = 'a';
l2 = 'n';
l3 = 't';
break;
case 1:
length = 4;
l1 = 'b';
l2 = 'a';
l3 = 'l';
l4 = 'l';
break;
case 2:
length = 3;
l1 = 'b';
l2 = 'a';
l3 = 't';
break;
default:
length = 0;
break;
}
}
public int getwordchosennumber()
{
return this.wordchosen;
}
public int getlength()
{
return this.length;
}
public int getl1()
{
return this.l1;
}
public int getl2()
{
return this.l2;
}
public int getl3()
{
return this.l3;
}
public int getl4()
{
return this.l4;
}
public int getl5()
{
return this.l5;
}
public int getl6()
{
return this.l6;
}
}

Because, word has null value. The exception null pointer exception itself specify its meaning that, you want to access some object, which has null reference.
Declared here
private Animals word;
Initially, it has null reference, until you won't do something like
word = new Animals(); // assign Animals reference

You never initialize word. On the line before the error (or in the initial declaration), use new:
word = new Animals(); // The line to insert.
word.getnewword();
On future questions, when you get an exception or force close, please post the full LogCat stack trace (red text in your log output), to help us find the problem quicker.

In the OnCreate after
Log.e("main", "textview pre-setup complete");
add
word = new Animals();

You should create the object of the class like
word = new Animals();
now, use this object to access the public methods and variable of Animals class.
word.getnewword();

You're getting a NullPointerException because the variable "word" wasn't initialized. Android is a little bit strange when it comes to working with variables. If you don't initialize the variable in the onCreate method (or some method that is called from the onCreate method) before you call the variable then you will get a NullPointerException because the JVM doesn't know what the value of that variable is. It's kind of like regular java code that has a main method - if you call a variable that hasn't been inialized in the main method you'll get a NullPointerException.
To fix your code simply put this in the onCreateMethod before you make any calls to the variable:
word = new Animals();
After that you can do what you need with the variable.

Related

use shuffelArray as global variable

We are trying to use this array of integers in other methods. Setting the final shuffled Array to a global variable has become next to impossible. We have set other variable as global. The goal here is to have a new int [] fix array every time a button is clicked. We have been able to generate a random int [] ar but can not utilize the array in other methods. So our questions after making the random int [] ar how can we use it in the onClickBtnOne method? Code with comments below
public class MainActivity extends AppCompatActivity {
Button btn1,btn2,btn3,btn4,btn5,btn6;
String T1,T2,T3,T4,T5,T6;
int test[] = new int[7];
int count = 0;
int v1,v2,v3,v4,v5,v6;
int[] fix = {3,2,1,4,6,5};
// Trying to not use above values
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn1 = findViewById(R.id.btn1);
btn2 = findViewById(R.id.btn2);
btn3 = findViewById(R.id.btn3);
btn4 = findViewById(R.id.btn4);
btn5 = findViewById(R.id.btn5);
btn6 = findViewById(R.id.btn6);
main(null);
}
// end onCeate
public static void main(String args[]) {
int [] fix = {1,2,3,4,5,6};
shuffleArray(fix);
// Want to USE this fix shuffleArray
//==================================
for (int i = 0; i < fix.length; i++) {
System.out.print(fix[i] + ",");
}
System.out.println();
}
// Implementing Fisher–Yates shuffle
static void shuffleArray(int [] ar) {
// If running on Java 6 or older, use `new Random()` on RHS here
Random rnd = ThreadLocalRandom.current();
for (int i = ar.length - 1; i > 0; i--) {
int index = rnd.nextInt(i + 1);
// Simple swap
int a = ar[index];
ar[index] = ar[i];
ar[i] = a;
}
}
public void onClickBtnOne(View view){
btn1.setBackgroundColor(getColor(R.color.color_Red));
btn1.setEnabled(false);
count = count + 1;
v1 = count;
test[v1] = count;
if(fix[0] == test[v1]){
// Need a global fix[] here
// =========================
T1 = "true";
if(T1.matches("true")){
btn1.setBackgroundColor(getColor(R.color.color_Yellow));
}
}else {
T1 = "false";
}
}
The array you are trying to use does not have an add method you need to put the values in from another variable like this ar[i] = a; So if you use this type of Array declaration List value = new ArrayList<>(); where you declared the other global variable life will be much easier. Modified code below
This will do the shuffle NOTICE value.clear() without this the List will grow each time it is initialized
public void shf(View view){
value.clear();
for (int i = 1; i <= 6; i++) {
value.add(i);
}
Collections.shuffle(value);
}
And here is your test method call value.get(index) Arrays are ZERO based
public void on1(View view){
btn1.setBackgroundColor(getColor(R.color.color_Red));
btn1.setEnabled(false);
if(value.get(0) == 1){
T1 = "true";
if(T1.matches("true")){
btn1.setBackgroundColor(getColor(R.color.color_Yellow));
}
}else {
T1 = "false";
}
}

Android: Pass Array to StringBuffer to AlertDialog

What I am trying to accomplish is to take an array, sort it, pull the first 5 results and display them in a small window. It was recommended to me to try to accomplish this using the previously mentioned methods as shown in the below code. I am still quite new to Android and this is my first attempt at utilizing StringBuffer and AlertDialog.
My error is that I have either done something wrong initializing the lastScoreMessage variable or I am passing it around incorrectly. All I know is that even though I am specifically calling it in my onClick switch case, it is giving me an error saying it is never used (in the lastFive method) and Cannot resolve symbol lastScoreMessage in the onClick switch statement where I am attempting to use it.
Any help here is greatly appreciated.
public class EditTextButtons extends AppCompatActivity implements View.OnClickListener {
DBHandler db;
Calendar c = Calendar.getInstance ( );
Date d = c.getTime ( );
EditText etName;
Button btnAdd;
Button btnLastFive;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
setContentView (R.layout.snake_layout_r);
db = new DBHandler (this);
etName = (EditText) findViewById (R.id.etName);
btnAdd = (Button) findViewById (R.id.btnAdd);
btnLastFive = (Button) findViewById (R.id.btnLastFive);
// set listeners
btnAdd.setOnClickListener (this);
btnLastFive.setOnClickListener (this);
}
#Override
public void onClick(View v) {
switch (v.getId ( )) {
case R.id.btnAdd:
insertIntoDB ( );
Intent i = new Intent (getApplicationContext ( ), Snake.class);
startActivity (i);
break;
case R.id.btnLastFive:
lastFive ();
showMessage ("Last 5 Scores", lastScoreMessage);
break;
default:
break;
}
}
protected void insertIntoDB() {
ContentValues cv = new ContentValues ( );
cv.put (db.USERNAME, etName.getText ( ).toString ( ));
}
protected void lastFive() {
int listsize = 5;
List<User> userlist = new ArrayList<User> ( );
userlist = db.convertDatabaseToList ( );
Collections.sort (userlist, User.Comparators._id);
StringBuffer buffer = new StringBuffer();
String lastScoreMessage;
for (int i = 0; i < listsize; i++) {
User temp = userlist.get(i);
String username = temp.getName();
int score = temp.getScore();
buffer.append(username + ": " + score + "\n");
}
lastScoreMessage = buffer.toString();
}
protected void showMessage(String title, String message) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(true);
builder.setTitle(title);
builder.setMessage(message);
builder.show();
}
}
simply create lastScoreMessage in the class instead of method. the problem is the scope of variable is only upto method. first create variable in class. and then store value in method like you did.
You can declare lastScoreMessage as a class variable an the affect it in the lastFive() method or modify the lastFive() method to return the string that you pass to the showMessage() method
String message = lastFive ();
showMessage ("Last 5 Scores", message);
and set the lastFive() method like this
protected String lastFive() {
int listsize = 5;
List<User> userlist = new ArrayList<User> ( );
userlist = db.convertDatabaseToList ( );
Collections.sort (userlist, User.Comparators._id);
StringBuffer buffer = new StringBuffer();
String lastScoreMessage;
for (int i = 0; i < listsize; i++) {
User temp = userlist.get(i);
String username = temp.getName();
int score = temp.getScore();
buffer.append(username + ": " + score + "\n");
}
lastScoreMessage = buffer.toString();
return lastScoreMessage
}

final int variable increment not working

I am using following script to link audio file with a text
TextView link = (TextView) findViewById(R.id.link);
link.setText(buildStringToPlaySound(context, "Play <u>song</u> or <u>poem</u>",new String[] {"http://www.domain.com/song.mp3","http://www.domain.com/poem.mp3"}));
link.setMovementMethod(LinkMovementMethod.getInstance());
public SpannableStringBuilder buildStringToPlaySound(final Context context, String str, final String[] url)
{
CharSequence sequence = Html.fromHtml(str);
SpannableStringBuilder strBuilder = new SpannableStringBuilder(sequence);
UnderlineSpan[] underlines = strBuilder.getSpans(0,strBuilder.length(),UnderlineSpan.class);
//--------------------------------------
int i=0; //line 1
//--------------------------------------
for(UnderlineSpan span : underlines) {
int start = strBuilder.getSpanStart(span);
int end = strBuilder.getSpanEnd(span);
int flags = strBuilder.getSpanFlags(span);
ClickableSpan myActivityLauncher = new ClickableSpan() {
public void onClick(View view) {
try {
//--------------------------------------
playAudio(url[i]); //line 2
//--------------------------------------
} catch (Exception e) {
e.printStackTrace();
}
}
};
strBuilder.setSpan(myActivityLauncher, start, end, flags);
//--------------------------------------
i++; //line 3
//--------------------------------------
}
return strBuilder;
}
Problem is, when I use line 1 as final int i = 0;
Line 3 shows an error
The final local variable i cannot be assigned. It must be blank and not using a compound assignment
But if i use line 1 as int i=0;
Line 2 shows an error
Cannot refer to a non-final variable i inside an inner class defined in a different method
Make variable i as your class instance variable (scope will be through out the class) then it will not alert you to make the variable as final. :)
The variables i is the local variables in the buildStringToPlaySound() method.
When the buildStringToPlaySound() method returns, local variables i will be cleaned up from the stack, so they won't exist anymore after buildStringToPlaySound() returns.
So you can initialize the variable in the anonymous class but in your case make the variable to global so it won't be cleaned from stack.
Getting idea from #Margarita Litkevych's comment
Adding a line final int j=i; inside for loop and replaceing variable i with j inside playAudio(url[j]); working fine.
TextView link = (TextView) findViewById(R.id.link);
link.setText(buildStringToPlaySound(context, "Play <u>song</u> or <u>poem</u>",new String[] {"http://www.domain.com/song.mp3","http://www.domain.com/poem.mp3"}));
link.setMovementMethod(LinkMovementMethod.getInstance());
public SpannableStringBuilder buildStringToPlaySound(final Context context, String str, final String[] url)
{
CharSequence sequence = Html.fromHtml(str);
SpannableStringBuilder strBuilder = new SpannableStringBuilder(sequence);
UnderlineSpan[] underlines = strBuilder.getSpans(0,strBuilder.length(),UnderlineSpan.class);
//--------------------------------------
int i=0; //line 1
//--------------------------------------
for(UnderlineSpan span : underlines) {
//=================================
final int j=i; //added this line
//=================================
int start = strBuilder.getSpanStart(span);
int end = strBuilder.getSpanEnd(span);
int flags = strBuilder.getSpanFlags(span);
ClickableSpan myActivityLauncher = new ClickableSpan() {
public void onClick(View view) {
try {
//------------------------- //==================
playAudio(url[j]); //line 2 //Replaced i with j
//--------------------------//==================
} catch (Exception e) {
e.printStackTrace();
}
}
};
strBuilder.setSpan(myActivityLauncher, start, end, flags);
//--------------------------------------
i++; //line 3
//--------------------------------------
}
return strBuilder;
}

How to Generate Single Random value without Duplicate?

I am doing quize app. In this app questions wont be generate duplicates. so I am using code like int value=random.nextInt(10-1)+1.When i submit the answer random number will generate newly so generating duplicates.How can i compare previous random value with new random values every time ?
Generate from 1 to 10 and store in a list
Shuffle the list of generated numbers
Keep removing from the list
List<Integer> list = new LinkedList<Integer>();
for (int i = 1; i <= 10; i++) {
list.add(i)
}
Collections.shuffle(list);
int value= list.remove(0);
.......
value= list.remove(0);
and so on...
Check this also : Java - generate Random range of specific numbers without duplication of those numbers - how to?
Also storing in a HashMap and checking is a smart way like the other answer says. But this can cause a lot more clashes, since everytime you try to add a duplicate to the HashMap you fail and you have to generate a new one again. But generating all at once and shuffling doesnt cause this. But since the input set is small(10) this collision might not happen too much(depending on the randomness, or maybe it happens too much?) and the O(1) access to the map elements for comparison will help.
Store value in a hashmap and then check if it's already there. If there reroll.
Here is code which i was using at my project. Full source code is
here
package com.banglardin.test_code;
import android.app.*;
import android.content.*;
import android.content.res.*;
import android.os.*;
import android.view.*;
import android.widget.*;
import com.banglardin.test_code.*;
import java.util.*;
public class MainActivity extends Activity {
protected SharedPreferences preference;
protected Questions questionObject;
protected TextView textView;
protected Button buttonView, cleanButton;
protected ArrayList<String> ques_array;
protected final String KEY="Key124";
protected int i=0;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
//intilized Question and preference
questionObject = new Questions();
preference = getSharedPreferences(KEY,Context.MODE_WORLD_WRITEABLE);
// get array from question object
try{
ques_array= questionObject.getQestions(getApplicationContext());
}catch(Exception e){
e.printStackTrace();
}
// intilized views
textView = (TextView)findViewById (R.id.question);
buttonView = (Button) findViewById (R.id.button);
cleanButton = (Button) findViewById (R.id.button_clean);
textView.setTextSize(18.33f);
buttonView.setTextSize(18.00f);
cleanButton.setTextSize(18.00f);
// set onclickListener on button view
buttonView.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
int set = 0;
if(i < 6){
while(set == 0){
String history = getString(KEY); // <0>
Random r = new Random();
int id = r.nextInt(ques_array.size());
String s_id= "<"+ String.valueOf(id) + ">"; // ex : <0>
if( !history.contains(s_id)){
textView.setText(ques_array.get(id));
setString(KEY, (history + s_id)); // ex : <0> + <3> = <0><3>;
set = 67;
i++;
}
}
}
else if(i>=6){
textView.setText(getResources().getString(R.string.e2));
Toast.makeText(MainActivity.this,"Questions are not available any more",2).show();
}
}
}
);
// set onclickListener on button view
cleanButton.setOnClickListener(new View.OnClickListener(){
public void onClick(View v) {
setString(KEY, "<-0>");
}
}
);
}
#Override
public void onBackPressed(){
if(preference != null){
setString(KEY, ("<-0>"));
finish();
}
super.onBackPressed();
}
/** Get String value from preference */
private String getString(String KEY){
if(preference != null){
return preference.getString(KEY,"<-33>");
}
else{
return null;
}
}
/** Put String value to preference */
private void setString(String KEY, String value){
if(preference != null){
SharedPreferences.Editor edit = preference.edit();
edit.putString(KEY, value);
edit.commit();
}
}
/** Class that gives us all questions */
class Questions{
protected ArrayList<String> data;
public ArrayList<String> getQestions(Context c) throws Exception{
data = new ArrayList<String>();
Resources res= c.getResources();
String qes[] ={
res.getString(R.string.q1) , //0
res.getString(R.string.q2) , //1
res.getString(R.string.q3) , //2
res.getString(R.string.q4) , //3
res.getString(R.string.q5) , //4
res.getString(R.string.q6) , //5
res.getString(R.string.q7) , //6
};
// add all the strings one by one
for(String i : qes){
data.add(i);
}
return data;
}
}
}
use 'HashSet' class in the main property of this class is they contain set of different values mean no value is repeated in it......
so u can generate random no. and add it in set like this
Random r = new Random();
int i = r.nextInt(100);
HashSet<int> s = new HashSet<int>();
s.add(i);
generat random number and add it inti hashset and use it....
an in nextInt parameter have to give maximum no. range...
example code as follows:
Random r = new Random();
//declare a hash set
HashSet set = new HashSet();
for(int i=0;i<50;i++)
{
set.add(r.nextInt(100));
}
// create an iterator
Iterator iterator = set.iterator();
// check values
while (iterator.hasNext()){
System.out.println("Value: "+iterator.next() + " ");
}

Trying to set textview

Here is my class it goes in to infinite loop please check where I am going wrong ... I am trying to get id's of image view making it random and then trying to set text view with imageview's description
public class Object {
int ObectIds[];
LinearLayout HUDDisplay;
int HudDisplayText[] = {R.id.HUD_Text_Element1,
R.id.HUD_Text_Element2,
R.id.HUD_Text_Element3,
R.id.HUD_Text_Element4,
R.id.HUD_Text_Element5,
R.id.HUD_Text_Element6,
R.id.HUD_Text_Element7};
TextView[] text;
View v;
Object(Context context,View vs) {
super();
ObectIds = new int[8];
HUDDisplay=(LinearLayout)vs.findViewById(R.id.HUD_Display);
for (int i = 0; i < 8; i++) {
ObectIds[i] = (R.id.imageView1) + i;
Log.d("ImageView", "Image Id's " + ObectIds[i]);
}
randomize(vs);
setTextView();
}
public void setTextView()
{
for(int i=0;i<8;++i)
{
text[i] =(TextView) HUDDisplay.findViewById(HudDisplayText[i]);
text[i].setText(v.getContentDescription());
}
}
public void randomize(View vs) {
for (int i = 0; i < 8; i++) {
while (true) {
shuffleArray(ObectIds);
v = vs.findViewById(ObectIds[i]);
Log.d("Image", "Image Id's " + v.getId());
if (!v.isClickable()) {
v.setClickable(true);
break;
}
}
}
}
static void shuffleArray(int[] ar) {
Random rnd = new Random();
for (int i = ar.length - 1; i >= 0; i--) {
int index = rnd.nextInt(i + 1);
// Simple swap
int a = ar[index];
ar[index] = ar[i];
ar[i] = a;
}
}
}
Hey man I observed your code & found error in code :
Please compare following code with your code... Constructor
for (int i = 0; i < 8; i++) {
ObectIds[i] = **HudDisplayText[i]**;
Log.d("ImageView", "Image Id's " + ObectIds[i]);
}
You have a while(true) loop that you break from only if v is not clickable. What happens if v is clickable? Nothing in your code ever sets v to not clickable, and views by default are not clickable.
I notice you're using the Object class. Object is basically the root of which all classes extend. If you call super() in the constructor, it will call the super class constructor, which is Object as well... That might be the problem.
Try looking for tutorials on how to start with Java/Android, since you are also using variables names that are not recommended. E.g. in Java,:
- a Class starts with a Capital
- a variable, starts with lowercase
- a function starts with lowercase:
public class Captial
{
private int anIntegerStartsWithLowerCase;
private void functionsAreLowerCaseAsWell()
{
}
}
Also take a look at your loop... It looks like it is never ending

Categories

Resources