0

My English is not so good, but I will try..
I am having a problem with my android app (obesity measurement app).
In AVD (android virtual device), my app works well.
But, on my smartphone (Galaxy S7) my app causes an error.

Error massage is " BMI calcu keeps stopping " .

('BMI calcu' is the name of App.)

What should I do?
Please give me a hand...

<<<< Layout file >>>>

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="comp.whcomp.whteam.bmicalcu.MainActivity"
android:orientation="vertical">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal">

<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:text="BMI calculator"
android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="4"
android:orientation="vertical">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal">

<TextView
android:id="@+id/textView2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="height : " />

<EditText
android:id="@+id/heightEditText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:inputType="number|numberDecimal"
android:maxLength="5" />

<TextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="cm" />

</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal">

<TextView
android:id="@+id/textView3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="weight : " />

<EditText
android:id="@+id/weightEditText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:inputType="number|numberDecimal"
android:maxLength="5" />

<TextView
android:id="@+id/textView4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="kg" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal">

<TextView
android:id="@+id/textView5"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="BMI : " />

<TextView
android:id="@+id/bmiTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ems="10"
android:inputType="textPersonName" />

<TextView
android:id="@+id/textView6"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>

</LinearLayout>

<comp.whcomp.whteam.bmicalcu.BmiView
android:id="@+id/BmiView2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="5" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="6"
android:orientation="horizontal"></LinearLayout>

</LinearLayout>

Main code is as following:

MainActivity.java

public class MainActivity extends Activity {
EditText mWeightEditText;
EditText mHeightEditText;
TextView mBmiTextView;
float floatWeight;
float floatHeight;
static float floatBmi = 0f;
String strBmi;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

mWeightEditText = (EditText)findViewById(R.id.weightEditText);
mHeightEditText = (EditText)findViewById(R.id.heightEditText);
mBmiTextView = (TextView)findViewById(R.id.bmiTextView);

mWeightEditText.addTextChangedListener(mWatcher);
mHeightEditText.addTextChangedListener(mWatcher);
} // end of onCreate()

TextWatcher mWatcher = new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence,int i,int i1,int i2){}

@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2){
  if((mWeightEditText.getText().toString().length()>0) && 
            (mHeightEditText.getText().toString().length()>0)) { 
    if(mHeightEditText.getText().toString().equals("0")){ 

    } else { 
      floatWeight=Float.parseFloat(mWeightEditText.getText().toString());
      floatHeight=Float.parseFloat(mHeightEditText.getText().toString());

      floatBmi=(floatWeight/(floatHeight/100f)) / (floatHeight/100f);
      strBmi = String.format("%.1f", floatBmi);

      mBmiTextView.setText(strBmi);
    }
  } else {
    mBmiTextView.setText("");
    floatBmi = 0f;
  }
} // end of onTextchange()

@Override
public void afterTextChanged(Editable editable) {}
}; // end of TextWatcher
}

BmiView.java

public class BmiView extends SurfaceView implements SurfaceHolder.Callback {
Context mContext;
private BmiThread mThread; 

int screenWidth;
int screenHeight;
int radius;
int xOfCenterOfCircle;
int yOfCenterOfCircle;
int tOfRectOfArc;
int bOfRectOfArc;
int lOfRectOfArc;
int rOfRectOfArc;
int xOfNeedleEnd = 0;
int yOfNeedleEnd = 0;
int intBmi;

RectF rect;

private Paint mPaintGreen;
private Paint mPaintBlack;
private Paint mPaintNeedle;

// constructor
public BmiView(Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(this); 
mContext = context;
mPaintGreen = new Paint();
mPaintBlack = new Paint();
mPaintNeedle = new Paint();
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
screenWidth = w;
screenHeight = h;

if ( h > w/2 ) {
  radius = w*4/10;
} else {
  radius = h*4/5;
}
xOfCenterOfCircle = w/2;
yOfCenterOfCircle = h*4/5;

tOfRectOfArc = yOfCenterOfCircle - radius;
bOfRectOfArc = yOfCenterOfCircle + radius;
lOfRectOfArc = xOfCenterOfCircle - radius;
rOfRectOfArc = xOfCenterOfCircle + radius;

mPaintGreen.setColor(Color.GREEN);
mPaintBlack.setColor(Color.BLACK);
mPaintNeedle.setColor(Color.RED);
mPaintNeedle.setStrokeWidth(10);

rect = new RectF();
}

@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
mThread = new BmiThread(surfaceHolder); 
mThread.setRunning(true); 
mThread.start();
}

@Override
public void surfaceChanged(SurfaceHolder surfaceHolder,int i,int i1,int i2){}

@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
boolean retry = true;
mThread.setRunning(false); // terminate mThread

while (retry) {
  try {      
    mThread.join(); // wait for mThread to finish 
    retry = false;  
  }
  catch (InterruptedException e) {}
}
}

class BmiThread extends Thread {
private SurfaceHolder surfaceHolder; 
private boolean threadIsRunning = true; // running by default

public BmiThread(SurfaceHolder holder) { 
  surfaceHolder = holder; 
}

public void setRunning (boolean running) { 
  threadIsRunning = running;            
}

public void run() {
  Canvas canvas = null;   
  while (threadIsRunning) { 
    try {
      canvas = surfaceHolder.lockCanvas(); 
      synchronized (surfaceHolder) {   
        canvas.drawColor(Color.WHITE);
        rect.set(lOfRectOfArc, tOfRectOfArc, rOfRectOfArc, bOfRectOfArc);
        canvas.drawArc(rect, 180, 180, false, mPaintGreen);

        intBmi = (int)MainActivity.floatBmi;
        if(intBmi > 40) {
          intBmi = 40;
        }

        double deg = 180*(intBmi/40d), rad;
        rad = Math.toRadians(deg);

        xOfNeedleEnd = xOfCenterOfCircle - (int)((  Math.cos(rad) )*radius);
        yOfNeedleEnd = yOfCenterOfCircle - (int)((  Math.sin(rad) )*radius);

        canvas.drawLine(xOfCenterOfCircle, yOfCenterOfCircle, xOfNeedleEnd,
                           yOfNeedleEnd, mPaintNeedle);
        canvas.drawCircle(xOfCenterOfCircle, yOfCenterOfCircle, 10, 
                                                          mPaintBlack);
      }
    } finally {
      if (canvas != null) 
        surfaceHolder.unlockCanvasAndPost(canvas); 
    }
  } // end of while()
} // end of run()
} // end of thread.
}

<<<< Logcat message >>>>

08-02 16:00:18.127 3086-3213/comp.whcomp.whteam.bmicalcu E/AndroidRuntime: FATAL EXCEPTION: Thread-7
Process: comp.whcomp.whteam.bmicalcu, PID: 3086
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.graphics.Canvas.drawColor(int)' on a null object reference
    at comp.whcomp.whteam.bmicalcu.BmiView$BmiThread.run(BmiView.java:123)
pfx
  • 20,323
  • 43
  • 37
  • 57
Luke
  • 11
  • 1
  • The line `canvas = surfaceHolder.lockCanvas();` is returning a null value for `lockCanvas()`. You need to do a null check and handle the error accordingly. – Michael Dodd Aug 02 '18 at 09:16
  • Thanks a lot. But, I do not have the ability to solve this problem. Please, be more specific. ^^ – Luke Aug 03 '18 at 05:16

2 Answers2

0

Check that you are creating an instance before trying to set the colour. It is complaining because the object you're trying to set the colour for doesn't exist at the time you're trying to set it.

Spectre
  • 56
  • 3
0

Hmm. For the first glance, your code seems correct. Maybe is because your BmiView has a height of 0dp? - see the layout

Alex Shevelev
  • 681
  • 7
  • 14