Good day everyone, can somebody help me on how will I make this process? I'm just trying to test this on one button. Suppose that:
After click the btnEasy1, it will go to the ButtonFunctions class and set the necessary setting for the GameActivity class.
PS. I am try this for now on one button(btnEasy1) only for now
PPS. The error says that I am trying to invoke virtual method on a null object reference.
ImageButton btnEasy1, btnEasy2, btnEasy3, btnEasy4, btnEasy5, btnEasy6, btnEasy7, btnEasy8, btnEasy9, btnEasy10, btnBack;
int row = 0 , column = 0 , stage = 0;
ButtonFunctions btnFunc;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_level__easy);
this.btnEasy1 = findViewById(R.id.btnEasy1);
this.btnEasy2 = findViewById(R.id.btnEasy2);
this.btnEasy3 = findViewById(R.id.btnEasy3);
this.btnEasy4 = findViewById(R.id.btnEasy4);
this.btnEasy5 = findViewById(R.id.btnEasy5);
this.btnEasy6 = findViewById(R.id.btnEasy6);
this.btnEasy7 = findViewById(R.id.btnEasy7);
this.btnEasy8 = findViewById(R.id.btnEasy8);
this.btnEasy9 = findViewById(R.id.btnEasy9);
this.btnEasy10 = findViewById(R.id.btnEasy10);
this.btnBack = findViewById(R.id.btnBack);
//Easy Level intents
Intent easyLevelIntent = new Intent(getApplicationContext(), GameActivity.class);
btnBack.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getApplicationContext(), Level_Selection.class);
startActivity(intent);
finish();
}
});
btnEasy1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
btnFunc =new ButtonFunctions();
btnFunc.functions("easy1");
finish();
}
});
public class ButtonFunctions extends AppCompatActivity {
int row, column, stage;
public void functions(String diffStage){
Intent easyLevelIntent = new Intent(getApplicationContext(), GameActivity.class);
if(diffStage.equals("easy1")){
stage = 1 ;row = 2; column = 2 ;
setRowCol(easyLevelIntent);
startActivity(easyLevelIntent);
}
}
private void setRowCol(Intent easyLevelIntent) {
easyLevelIntent.putExtra("easyStageCount", stage);
easyLevelIntent.putExtra("rowCount", row);
easyLevelIntent.putExtra("colCount", column);
easyLevelIntent.putExtra("difficulty", 1);
}
Process: com.flip, PID: 10543
java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.content.Context.getApplicationContext()' on a null object reference
at android.content.ContextWrapper.getApplicationContext(ContextWrapper.java:106)
at com.flip.Functions.ButtonFunctions.functions(ButtonFunctions.java:14)
at com.flip.StageSelection.Level_Easy$2.onClick(Level_Easy.java:54)
at android.view.View.performClick(View.java:5680)
at android.view.View$PerformClick.run(View.java:22650)
at android.os.Handler.handleCallback(Handler.java:836)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:203)
at android.app.ActivityThread.main(ActivityThread.java:6364)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1076)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:937)
You have declared ButtonFunctions as extending AppCompatActivity. But this class is not an Activity, it is just a utility class. You are getting this NullPointerException because you have created an Activity using the new keyword. This is not allowed. Only the Android framework can correctly create new instances of Android components (Activity, Service, Provider).
You should remove the extends AppCompatActivity from the ButtonFunctions class declaration and add a Context parameter to any of the methods that need one. For example, this one:
public void functions(Context context, String diffStage){
Intent easyLevelIntent = new Intent(context, GameActivity.class);
if(diffStage.equals("easy1")){
stage = 1 ;row = 2; column = 2 ;
setRowCol(easyLevelIntent);
context.startActivity(easyLevelIntent);
}
}
Another approach would be to move all the methods from ButtonFunctions into your Activity, since they seem to be very dependent on it. But this is an architectural choice that you need to make.
Related
I am trying to build a very simple App in Android Studio to practice using Intents to send data from one activity to another. On my Main Activity I have a "Total" TextView and a button. When I click the button, it takes me to a AddNumber Activity where I can type in an integer and press a button. This then takes me back to the Main Activity and adds that integer to the total, updating the TextView. I want to be able to do this multiple times while I've got the app open so the total keeps going up.
I have tried using a ViewModel to store the information so it doesn't get reset every time the Main Activity onCreate method is run. However, every time I do this, it works once (e.g. if I add a 7 in my AddNumber Activity, the Main Activity total goes to 7). However, when I try again, the ViewModel seems to get reset so doesn't remember the 7 that I put in initially, so if I put in an 8, the total on the MainActivity just gets set to 8, rather than 15. Am I making a mistake somewhere that is causing the ViewModel to reset? I understood that ViewModels were a way of storing data while the app is open, but I can't seem to make it work.
Thanks so much!
MainActivity.java code:
public class MainActivity extends AppCompatActivity {
TextView totalTextView;
MainActivityViewModel viewModel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
totalTextView = (TextView) findViewById(R.id.totalTextView);
viewModel = new ViewModelProvider(this).get(MainActivityViewModel.class);
totalTextView.setText(Integer.toString(viewModel.total));
getSetIncomingIntent();
}
public void addNumber(View view){
Intent intent = new Intent(this, AddNumber.class);
startActivity(intent);
}
public void getSetIncomingIntent() {
Intent incomingIntent = getIntent();
if (incomingIntent.hasExtra("value")) {
viewModel.newValue = incomingIntent.getIntExtra("value",0);
viewModel.addNumber();
totalTextView.setText(Integer.toString(viewModel.total));
}
}
}
MainActivityViewModel.java code:
public class MainActivityViewModel extends ViewModel {
int total = 0;
int newValue;
public void addNumber() {
total = total + newValue;
}
}
AddNumber.java code:
public class AddNumber extends AppCompatActivity {
EditText numberEditText;
int value;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_number);
numberEditText = (EditText) findViewById(R.id.numberEditText);
}
public void addNumber(View view){
value = Integer.parseInt(numberEditText.getText().toString());
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("value", value);
startActivity(intent);
}
}
When I click the button, it takes me to a AddNumber Activity where I can type in an integer and press a button. This then takes me back to the Main Activity and adds that integer to the total, updating the TextView.
This is not what is happening. First you create a new AddNumber activity.
public void addNumber(View view){
Intent intent = new Intent(this, AddNumber.class);
startActivity(intent); // This launches a new AddNumber Activity
}
And then here you are creating a new MainActivity instance.
public void addNumber(View view){
value = Integer.parseInt(numberEditText.getText().toString());
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("value", value);
startActivity(intent); // This launches a new MainActivity
}
So you're basically building a giant stack of MainActivity / AddNumber instances.
You need to start AddNumber with startActivityForResult and then handle that in MainActivity. Then you will be working with the original MainActivity and the original ViewModel and you will be able to update it.
Please refer to the documentation on starting an Activity for result.
Hope that helps!
Here is my situation:
I have an OnCreate code like the following:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bunz = Bunz.getInstance(); //getting instance of bunz
bunz.setBunz(50);
bunz.setMoney(0);
bunz.setIncrement(1);
Button upgradeButton = (Button) findViewById(R.id.upgradeButton);
upgradeButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
Intent startIntent = new Intent(getApplicationContext(), UpgradeMenu.class);
startActivity(startIntent);
}
});
moneyCount = (TextView) findViewById(R.id.moneyCount);
bunzCount = (TextView) findViewById(R.id.bunzCount);
ImageButton bun = (ImageButton) findViewById(R.id.bun);
}
Notice how in my OnCreate code, I do 2 things; first, I initialize all the values I need:
bunz.setBunz(50);
bunz.setMoney(0);
bunz.setIncrement(1);
and then I display these values on TextViews and set up some Buttons and intents:
Button upgradeButton = (Button) findViewById(R.id.upgradeButton);
upgradeButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
Intent startIntent = new Intent(getApplicationContext(), UpgradeMenu.class);
startActivity(startIntent);
}
});
moneyCount = (TextView) findViewById(R.id.moneyCount);
bunzCount = (TextView) findViewById(R.id.bunzCount);
ImageButton bun = (ImageButton) findViewById(R.id.bun);
I'm new to Android studio, and here is the problem I'm having. I want to use onResume() to update these values in the TextView (I update them in another activity) every time I go back to this activity. However, if I move all the code in onCreate into onResume, then every time I go back to this activity, the values will be set to 50,0, and 1. I understand I could use a boolean, so that onCreate() triggers the first time the app is launched, but onResume() doesn't trigger, and then onResume() triggers after that, and simply copy and paste the second half of the onCreate code into onResume(), but that seems inefficient, and isn't how Android studio is designed to work. Can I somehow initialize the values in another location?
I have a global Bunz class that looks like the following:
public class Bunz {
private int bunz;
private int money;
private int increment;
//singleton code
private static Bunz instance;
private Bunz(){
}
public static Bunz getInstance(){
if (instance == null){
instance = new Bunz();
}
return instance;
}
public int getBunz() {
return bunz;
}
public void setBunz(int num){
bunz = num;
}
public int getMoney(){
return money;
}
public void setMoney(int num){
money = num;
}
public int getIncrement(){
return increment;
}
public void setIncrement(int num){
increment = num;
}
}
so maybe I could initialize these values here somehow?
Thanks!
here's one thing you could alternatively do:
public static Bunz getInstance(){
if (instance == null){
instance = new Bunz();
instance.setBunz(50);
instance.setMoney(0);
}
return instance;
}
in your instance creation here, try setting the values you want here, instead of in onCreate of the app.
you could just be making the changes in the constructor as well.
While your code uses statics, which I believe is unnecessary. Statics are not your average goto solution, they come with a hefty price of an object not eligible for GC.
You can get the result from the second activity via onActivityResult method.
First, start second activity using startAtivityForResult() //This takes in a request code(Int), it can be whatever you set.
First activity
Intent intent = new Intent(this, SecondActivity.class);
startActivityForResult(intent , 100);
Second Activity
//Do you work in the second activity, generate new data
Intent returnIntent = new Intent();
returnIntent.putExtra("bunz", 100);
returnIntent.putExtra("money", 200);
returnIntent.putExtra("increment", 2);
setResult(Activity.RESULT_OK, returnIntent);
finish();
Capture Second Activity Result
This code is supposed to be written in your first activity.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 100) { //Remember the code we set in startActivityForResult? This is where we identify our work
if(resultCode == Activity.RESULT_OK){ //Code to check if data is passed
Int bunz =data.getIntExtra("bunz")
bunz.setBunz(bunz)
.....
}
}
}
I'm a noobie making a quiz in Android Studio and i'm trying to pass an integer between activities to add to the amount of questions they got correct for the end but in the second activity it isn't changing when I answer the first question correct.
Question1 activity:
public class Question1 extends AppCompatActivity {
public int correctAnswers = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_question1);
Intent intent = new Intent(Question1.this, Question2.class);
Intent i = getIntent();
Intent answersCorrect = new Intent(Question1.this, Question2.class);
answersCorrect.putExtra("correctAnswers", correctAnswers);
}
public void submitQuestion1(View view) {
EditText question1TextInput = (EditText) findViewById(R.id.question1TextInput);
if (question1TextInput.getText().toString().length() >= 1) {
startActivity(new Intent(Question1.this, Question2.class));
if (question1TextInput.getText().toString().toUpperCase().contentEquals("FATHER")) {
correctAnswers += 1;
Intent answersCorrect = new Intent(Question1.this, Question2.class);
answersCorrect.putExtra("correctAnswers", correctAnswers);
}
}
}
}
Question2 Activity:
public class Question2 extends AppCompatActivity {
public int correctAnswers;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_question2);
Intent intent = getIntent();
int number = intent.getIntExtra("correctAnswers", 0);
TextView myAwesomeTextView = (TextView)findViewById(R.id.text);
myAwesomeTextView.setText(String.valueOf(number));
}
}
you duplicate your intent here:
Intent intent = new Intent(Question1.this, Question2.class);
Intent i = getIntent();
Intent answersCorrect = new Intent(Question1.this, Question2.class);
answersCorrect.putExtra("correctAnswers", correctAnswers);
replace it to:
Intent intent = new Intent(Question1.this, Question2.class);
intent.putExtra("correctAnswers", correctAnswers);
startActivity(intent);
in your second Activity:
int correctAnswers;
correctAnswers = (int) getIntent().getIntExtra("correctAnswers", 0);
So basically, when you have one activity and want to open a second activity, an Intent is the most important thing to have. It's responsible for communcation between your system and your application.
Intent is responsible for starting an activity, starting a service, and delivering a broadcast.
Note that there are two different types of intent: Explicit and Implicit.
Explicit Intent is used in this manner:
You have Activity_1 and you KNOW that you want to start Acticity_2 FROM Activity_1.
Implicit Intent is used when you DON'T know the name of the activity that you want to start.
Now, I know you probably understand what the StartActivity() method DOES, but StartActivity always requires an intent to go into the parenthesis. StartActivity(Activity_2); will not work.
So, when using Explicit Intent:
Intent i = new Intent(Activity_1.this, Activity_2.class);
StartActivity(i);
You start with making a reference - i - and, inside the parameters, the first being the activity from which you are calling the second activity, and the second being the activity which you want to call.
Here's a video on Intents as well: https://youtu.be/FH1Ym1KjJNc
Hope this helped.
Move the intent to a field. You only need it once.
Then, the issue is that you start the other activity too soon, without setting any value. You started the other activity with an empty, new Intent
public class Question1 extends AppCompatActivity {
public int correctAnswers = 0;
final Intent answersIntent = new Intent(Question1.this, Question2.class);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_question1);
}
public void submitQuestion1(View view) {
EditText question1TextInput = (EditText) findViewById(R.id.question1TextInput);
String answer = question1TextInput.getText().toString();
// No need to check for length if directly checking another string
if (answer.toUpperCase().contentEquals("FATHER")) {
answersIntent.putExtra("correctAnswers", ++correctAnswers);
startActivity(answersIntent);
}
}
If you plan on sharing that value over many questions, try SharedPreferences.
FWIW, make a generic View for any question that has the question text and possible answer fields. Try not to make one activity per question.
(I'm unsure if I am doing this correctly.)
I am creating a simple timetable app which has a main timetable activity with five buttons to five different days. When a button is clicked I want to start an activity that uses a base activity that takes in two int arrays which are just the codes of lessons to pass to a data class. How do I use this base class to create multiple different activities using intents when a button is clicked?
Timetable Activity (Simplified)-intent code not working.
public class TimetableActivity extends Activity {
private Button monABut;
int[] monAlessons = {5,2,6,5,5};
int[] monAteachers = {0,2,7,1,0};
public DayAOneActivity mondayA = new DayAOneActivity(monAlessons,monAteachers);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_timetable);
monABut = (Button) findViewById(R.id.monAButton);
monABut.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(getApplicationContext(),mondayA);
startActivity(i);
}
});
}}
Day activity constructor
public class DayAOneActivity extends Activity {
int[] lessonCodes;
int[] teacherCodes;
public DayAOneActivity(int[] lessonCode, int[] teacherCode){
this.lessonCodes = lessonCode;
this.teacherCodes = teacherCode;
}
The correct way to start activity is to use it's class:
Intent i = new Intent(TimetableActivity.this, DayAOneActivity.class);
startActivity(i);
Activity object itself is created by Android framework automatically
I am working on an android app that launches two activities using the on click listener everything in my code checks out fine except where the public void onClick(View v) begins I have multiple errors starting on that line and I am unable to run the code? I would kindly appreciate any help as I am fairly new to this. My code is as follows
public class Safaricom extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.safaricom);
Button button1 = (Button)findViewById(R.id.button1);
Button button2 = (Button)findViewById(R.id.button2);
button1.setOnClickListener(buttonClickListener);
button2.setOnClickListener(buttonClickListener);
}
private OnClickListener buttonClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = null;
switch(v.getId()){
case R.id.button1:
intent = new Intent(this, Second.class);
break;
case R.id.button2:
intent = new Intent(this, SignUp.class);
break;
}
if (intent != null)
this.startActivity(intent);
}
};
}
The Errors are at two points.
First where it says public void on click view ( The Error is - Multiple Markers at this line - implements android.view.View.OnClickListener.onClick- The method onClick(View) of type new View.OnClickListener(){} must override a superclass )
Second where it says this.startActivity(intent); (The Error is -The method startActivity(Intent) is undefined for the type new View.OnClickListener(){})
Instead of this use v.getContext() or YOUR_ACTIVITY.this
Actually If you read the Docs carefully, you will know that Intent parameters contain Activity so when you are using this it means that you are giving a parameter of type new View.OnClickListener
Well, I can see right off a couple of errors. To make it clearer since it apparently was not clear by simply looking at the code and learning. I added Safaricom.this in each of the new Intent statements. This is because the Intent constructor needs a Context as the first argument and an OnClickListener is not a Context, you need to ge the enclosing Activity which is a context. One other edit, I missed, the startActivity also needs to have Safaricom prepended.
public class Safaricom extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.safaricom);
Button button1 = (Button)findViewById(R.id.button1);
Button button2 = (Button)findViewById(R.id.button2);
button1.setOnClickListener(buttonClickListener);
button2.setOnClickListener(buttonClickListener);
}
private OnClickListener buttonClickListener = new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = null;
switch(v.getId()){
case R.id.button1:
intent = new Intent(Safaricom.this, Second.class);
break;
case R.id.button2:
intent = new Intent(Safaricom.this, SignUp.class);
break;
}
if (intent != null)
Safaricom.this.startActivity(intent);
}
};
}
For the first error
The Error is - Multiple Markers at this line - implements android.view.View.OnClickListener.onClick- The method onClick(View) of type new View.OnClickListener(){} must override a superclass )
Try removing the #override
If that doesn't remove the second error then let us know if there is a different issue arising.