Im creating an app that takes your weight, height, gender and all that medical stuff and calculates values like IMC, calories... It has 3 activities, the first is the Main, here i ask for all the values that i said. Second one just show some results, and the last one calculates how many kgs will lose eating x value of calories per month (set by the user). The problem here is that i need two values of the second activity, the weight and the TMB (metabolism) to calculate how many kg will lose. Im passing that values with an intent, i put them as an extra with a tag and then i get them in the last activity, i put them as an String, but they are decimals and i need them as decimals, so, when i get them as an extra and i parse them to double, i get an IlegalStateException.
Code of the first activity (java)
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//AÑADIR GENERO A DATOS TRANSFERIBLES --> DONE
// METER TMB, CALORIAS PARA VOLUMEN, DEFINICIÓN Y MANTENIMIENTO --> DONE
// HACER SECCIÓN ESPECIAL PARA VOLUMEN Y DEFINICION (INDICANDO KILOS A GANAR/PERDER EN X TIEMPO) --> ARREGLAR ERROR CALCULAR DEFINICIÓN **
// ARREGLAR BUGS INICIO (QUE ESTE EL TEXTO AL LADO AL ESCRIBIR...)
RadioGroup radioGroupActividad = findViewById(R.id.radioGroup);
radioGroupActividad.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup radioGroup, int id) {
RadioButton radioButton = findViewById(id);
aN = radioButton.getText().toString();
}
});
}
public void sendData (View v) {
EditText nombreApellidos = findViewById(R.id.NombreApellidos);
EditText edad = findViewById(R.id.Edad);
EditText altura = findViewById(R.id.altura);
EditText peso = findViewById(R.id.peso);
String gN = "G";
RadioButton rbH = findViewById(R.id.hombre);
RadioButton rbF = findViewById(R.id.mujer);
if (rbH.isChecked() && !rbF.isChecked()) {
gN = "hombre";
}
if (rbF.isChecked() && !rbH.isChecked()) {
gN = "mujer";
}
/*DATOS*/
String name = nombreApellidos.getText().toString().replace("Nombre" , "");
String edadN = edad.getText().toString().replace("Edad","");
String alturaN = altura.getText().toString().replace("Altura","");
String pesoN = peso.getText().toString().replace("Peso","");
Intent i = new Intent(this,SeeResults.class);
String [] info = new String[6];
info [0] = name;
info [1] = edadN;
info [2] = alturaN;
info [3] = pesoN;
info [4] = aN;
info [5] = gN;
i.putExtra("data",info);
startActivity(i);
}
public void onClickElement (View v) {
int idElement = v.getId();
if (idElement == R.id.peso) {
EditText peso = findViewById(R.id.peso);
peso.setText("");
}
if (idElement == R.id.altura) {
EditText altura = findViewById(R.id.altura);
altura.setText("");
}
if (idElement == R.id.NombreApellidos) {
EditText Nombre = findViewById(R.id.NombreApellidos);
Nombre.setText("");
}
if (idElement == R.id.Edad) {
EditText Edad = findViewById(R.id.Edad);
Edad.setText("");
}
}
String aN;
}
Code of the second activity:
public class SeeResults extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_see_results);
dataTransfered = new String[6];
TextView imc = findViewById(R.id.Imc);
Intent i = getIntent();
String [] data = i.getStringArrayExtra("data");
dataTransfered = data;
String actividadF = dataTransfered[4];
String genero = dataTransfered[5];
double actividadFNumero = 0;
switch (actividadF) {
case "Poca":
actividadFNumero = 1.1;
break;
case "Regular":
actividadFNumero = 1.3;
break;
case "Bastante":
actividadFNumero = 1.5;
break;
case "Mucha":
actividadFNumero = 1.7;
break;
}
double peso = Double.parseDouble(dataTransfered[3]);
double altura = Double.parseDouble(dataTransfered[2]) / 100;
int edad = Integer.parseInt(dataTransfered [1]);
double IMC = Math.round (peso / (altura * altura));
double TMB = 0;
if (genero.equals("hombre")) {
TMB = ((10 * peso) + (6.25 * (altura * 100) ) - (5 * edad ) + 5) * actividadFNumero;
}
if (genero.equals("mujer")) {
TMB = ((10 * peso) + (6.25 * (altura * 100) ) - (5 * edad) - 161) * actividadFNumero;
}
Log.d("ActividadFisica",actividadF);
Log.d("ActividadFisicaNumero", String.valueOf(actividadFNumero));
Log.d("Genero",genero);
i.putExtra("TMB",String.valueOf(TMB));
i.putExtra("Peso",String.valueOf(peso));
imc.setText("Tu IMC es : " + IMC + "\n" + "Tu TMB es : " + TMB + "\n" + "\n" + "Calorias definición : " + (TMB - 500) + "\n" + "\n" + "Calorias en volumen: " + (TMB + 500));
}
public void goBack (View v) {
Intent i = new Intent(this,MainActivity.class);
startActivity(i);
}
public void calcularDefinicion (View v) {
i = new Intent(this, CalcularDefinicion.class);
startActivity(i);
}
String [] dataTransfered;
Intent i;
}
Code of the last activity :
public class CalcularDefinicion extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_calcular_definicion);
tiempoDef = (EditText) findViewById(R.id.TiempoDef);
caloriasDef = (EditText) findViewById(R.id.CaloriasDef);
textoInicio = findViewById(R.id.pesoEmpezarDef);
textoAcabar = findViewById(R.id.pesoAcabarDef);
}
public void calcularDef (View v) {
int calorias = Integer.parseInt(caloriasDef.getText().toString().replace("Calorias",""));
int tiempo = Integer.parseInt(tiempoDef.getText().toString().replace("Tiempo",""));
Log.d("caloriasNumero",String.valueOf(calorias));
Log.d("tiempoNumero",String.valueOf(tiempo));
Intent i = getIntent();
double TMB = Double.parseDouble(i.getStringExtra("TMB"));
double peso = Double.parseDouble(i.getStringExtra("Peso"));
Log.d("TMB",String.valueOf(TMB));
Log.d("Peso",String.valueOf(peso));
double pesoPerdido = (TMB - calorias) * (tiempo / 30);
double pesoFinal = peso - pesoPerdido;
textoAcabar.setText(textoAcabar.getText() + " " + pesoFinal);
}
EditText caloriasDef;
EditText tiempoDef;
TextView textoInicio, textoAcabar;
}
STACKTRACE
FATAL EXCEPTION: main
Process: com.example.calculoimc, PID: 32693
java.lang.IllegalStateException: Could not execute method for android:onClick at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:473) at android.view.View.performClick(View.java:7506) at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1211) at android.view.View.performClickInternal(View.java:7483) at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0) at android.view.View$PerformClick.run(View.java:29334) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7872) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Method.invoke(Native Method) at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:468) at android.view.View.performClick(View.java:7506) at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1211) at android.view.View.performClickInternal(View.java:7483) at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0) at android.view.View$PerformClick.run(View.java:29334) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7872) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.String.trim()' on a null object reference at jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1838) at jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110) at java.lang.Double.parseDouble(Double.java:543) at com.example.calculoimc.CalcularDefinicion.calcularDef(CalcularDefinicion.java:31) at java.lang.reflect.Method.invoke(Native Method) at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:468) at android.view.View.performClick(View.java:7506) at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1211) at android.view.View.performClickInternal(View.java:7483) at android.view.View.-$$Nest$mperformClickInternal(Unknown Source:0) at android.view.View$PerformClick.run(View.java:29334) at android.os.Handler.handleCallback(Handler.java:942) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at android.app.ActivityThread.main(ActivityThread.java:7872) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
I checked that it all the values are a DOUBLE and did not have any value like "Calories: 43" and was only 43, thats what i do in this part of the code in the last activity:
int calorias = Integer.parseInt(caloriasDef.getText().toString().replace("Calorias",""));
int tiempo = Integer.parseInt(tiempoDef.getText().toString().replace("Tiempo","");
The TMB and the weight are just numbers, the TMB is calculated and the weight is put just as a number.
Also, the activity is registered in the manifest, i dont think there is the problem but i checked it anyways, i searched and searched around all the internet but i could not figure out what is wrong.
According to the error message, you've set onClick
method of a button in one of your xml file with its default name as onClick
, with the intention of connecting the button click event to the onClickElement
method that you defined in your MainActivity.java.
Either change onClickElement
to onClick
in your activity or onClick
to onClickElement
in your xml so that the declared and defined symbols match.
After your comment, I relooked at the exception message and seems like you are right. The actual problem occurs when getting data in your CalcularDefinicion
's onCreate
method. There you try to get the sent data from the previous activity but you get null because in the previous activitiy you send a new intent that does not have any data.
SeeResults class
@Override
protected void onCreate(Bundle savedInstanceState) {
...
// You get the intent here from the main activity
Intent i = getIntent();
String [] data = i.getStringArrayExtra("data");
...
// After processing values you use the same intent to send data
i.putExtra("TMB",String.valueOf(TMB));
i.putExtra("Peso",String.valueOf(peso));
}
/*
But when you start the CalcularDefinicion activity you create a new intent
and all the data you put in the onCreate method has gone. Now you send
nothing to the CalcularDefinicion activity, hence you obviously will get null.
*/
public void calcularDefinicion (View v) {
i = new Intent(this, CalcularDefinicion.class);
startActivity(i);
}
Here are some solutions for you.
Set the button's onClikListener
within the onCreate
method so that you can get access to the intent that you've set the data for CalcularDefinicion
activity.
public class SeeResults extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
Intent i = getIntent();
String [] data = i.getStringArrayExtra("data");
...
double IMC = Math.round (peso / (altura * altura));
double TMB = 0;
if (genero.equals("hombre")) {
TMB = ((10 * peso) + (6.25 * (altura * 100) ) - (5 * edad ) + 5) * actividadFNumero;
}
if (genero.equals("mujer")) {
TMB = ((10 * peso) + (6.25 * (altura * 100) ) - (5 * edad) - 161) * actividadFNumero;
}
...
i.putExtra("TMB",String.valueOf(TMB));
i.putExtra("Peso",String.valueOf(peso));
imc.setText("Tu IMC es : " + IMC + "\n" + "Tu TMB es : " + TMB + "\n" + "\n" + "Calorias definición : " + (TMB - 500) + "\n" + "\n" + "Calorias en volumen: " + (TMB + 500));
calcularDefinicionButton.setOnClickListener(() v -> {
startActivity(i);
});
}
}
Leave the onCLick
implementation as is and declare a discrete intent for CalcularDefinicion
activity.
public class SeeResults extends AppCompatActivity {
private final Intent calcularIntent = new Intent(this, CalcularDefinicion.class);
@Override
protected void onCreate(Bundle savedInstanceState) {
...
Intent i = getIntent();
String [] data = i.getStringArrayExtra("data");
...
double IMC = Math.round (peso / (altura * altura));
double TMB = 0;
if (genero.equals("hombre")) {
TMB = ((10 * peso) + (6.25 * (altura * 100) ) - (5 * edad ) + 5) * actividadFNumero;
}
if (genero.equals("mujer")) {
TMB = ((10 * peso) + (6.25 * (altura * 100) ) - (5 * edad) - 161) * actividadFNumero;
...
calcularIntent.putExtra("TMB",String.valueOf(TMB));
calcularIntent.putExtra("Peso",String.valueOf(peso));
imc.setText("Tu IMC es : " + IMC + "\n" + "Tu TMB es : " + TMB + "\n" + "\n" + "Calorias definición : " + (TMB - 500) + "\n" + "\n" + "Calorias en volumen: " + (TMB + 500));
}
public void goBack (View v) {
// Don't hesitate to create new intents for each different cases
Intent backIntent = new Intent(this,MainActivity.class);
startActivity(backIntent);
}
public void calcularDefinicion (View v) {
startActivity(calcularIntent);
}
}
Finally there is one more thing to consider. Things may fail and may not result as expected. That's why you should take your precautions as a programmer to make sure the failable data does exist and wholesome.
public class CalcularDefinicion extends AppCompatActivity {
...
public void calcularDef (View v) {
int calorias = Integer.parseInt(caloriasDef.getText().toString().replace("Calorias",""));
int tiempo = Integer.parseInt(tiempoDef.getText().toString().replace("Tiempo",""));
Log.d("caloriasNumero",String.valueOf(calorias));
Log.d("tiempoNumero",String.valueOf(tiempo));
Intent i = getIntent();
// ATTENTION to this part!
String TMBstring = i.getStringExtra("TMB");
String pesoString = i.getStringExtra("Peso");
// Always check the nullity of the data you get from intent because
// somehow if the data don't exist it will return null by default
if (TMBstring == null || TMBstring.isEmpty()) {
// Can't continue without data, handle this unexpected case
return;
}
if (pesoString == null || pesoString.isEmpty()) {
// Can't continue without data, handle this unexpected case
return;
}
// If the program flow reaches here, then all the data exist and you
// can continue to process further.
double TMB = Double.parseDouble(TMBstring);
double peso = Double.parseDouble(pesoString);
Log.d("TMB",String.valueOf(TMB));
Log.d("Peso",String.valueOf(peso));
double pesoPerdido = (TMB - calorias) * (tiempo / 30);
double pesoFinal = peso - pesoPerdido;
textoAcabar.setText(textoAcabar.getText() + " " + pesoFinal);
}
EditText caloriasDef;
EditText tiempoDef;
TextView textoInicio, textoAcabar;
}