Android 应用在屏幕旋转后停止工作
Android app stop working after screen rotation
目前我正在使用 Google Mobile Vision API 进行人脸检测。假设屏幕旋转后,activity会重新启动,所有变量都会重新初始化。但是,我不知道为什么该应用程序停止工作并显示 NullPointerException。这是我的代码。
public class MainActivity extends AppCompatActivity {
private ImageView mIvDetected;
private Bitmap mImage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIvDetected = (ImageView) findViewById(R.id.iv_detected);
//Load an image
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inMutable = true;
mImage = BitmapFactory.decodeResource(getResources(), R.drawable.face2);
//Configure FaceDetector
FaceDetector detector = new FaceDetector.Builder(this)
.setMode(FaceDetector.ACCURATE_MODE)
.setLandmarkType(FaceDetector.ALL_LANDMARKS)
.setClassificationType(FaceDetector.ALL_CLASSIFICATIONS)
.setTrackingEnabled(false)
.build();
if(false == detector.isOperational()){
Toast.makeText(this, "Face detection service is not ready", Toast.LENGTH_SHORT).show();
return;
}
//Add the image on a Frame object
Frame frame = new Frame.Builder().setBitmap(mImage).build();
//Detect all faces from Frame object
SparseArray<Face> faceArray = detector.detect(frame);
//Do some drawing on faces
**Bitmap outBitmap = drawOnFace(faceArray);**
mIvDetected.setImageBitmap(outBitmap);
//Releasing the detector object
detector.release();
}
/** Method to do some drawing on faces */
private Bitmap drawOnFace(SparseArray<Face> faceArray){
Paint mIdPaint = new Paint();
mIdPaint.setColor(Color.RED);
mIdPaint.setTextSize(40.f);
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
Paint mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setDither(true);
mTextPaint.setTextSize(20);
mTextPaint.setColor(Color.GREEN);
mTextPaint.setStyle(Paint.Style.FILL);
// Create a blank bitmap same size with the source image
Bitmap outBitmap = Bitmap.createBitmap(mImage.getWidth(), mImage.getHeight(), Bitmap.Config.RGB_565);
// Put the bitmap on canvas for drawing
Canvas canvas = new Canvas(outBitmap);
canvas.drawBitmap(mImage, 0, 0, null);
for(int i=0; i < faceArray.size(); i++){
Face face = faceArray.get(i);
//Drawing rectangle on each face
**drawRectangle(canvas, face.getPosition(), face.getWidth(), face.getHeight());**
//Drawing a point on each face features
for(Landmark landmark : face.getLandmarks()) {
switch (landmark.getType()){
case Landmark.LEFT_EYE:
drawPoint(canvas, landmark.getPosition());
canvas.drawText("Left eye: " + face.getIsLeftEyeOpenProbability(), landmark.getPosition().x, landmark.getPosition().y - 30, mTextPaint);
break;
case Landmark.RIGHT_EYE:
drawPoint(canvas, landmark.getPosition());
canvas.drawText("Right eye: " + face.getIsRightEyeOpenProbability(), landmark.getPosition().x, landmark.getPosition().y - 30, mTextPaint);
break;
case Landmark.BOTTOM_MOUTH:
drawPoint(canvas, landmark.getPosition());
canvas.drawText("Smile: " + face.getIsSmilingProbability(), landmark.getPosition().x, landmark.getPosition().y + 40, mTextPaint);
break;
case Landmark.LEFT_MOUTH:
drawPoint(canvas, landmark.getPosition());
break;
case Landmark.RIGHT_MOUTH:
drawPoint(canvas, landmark.getPosition());
break;
case Landmark.NOSE_BASE:
drawPoint(canvas, landmark.getPosition());
break;
case Landmark.LEFT_CHEEK:
drawPoint(canvas, landmark.getPosition());
break;
case Landmark.RIGHT_CHEEK:
drawPoint(canvas, landmark.getPosition());
break;
case Landmark.LEFT_EAR:
drawPoint(canvas, landmark.getPosition());
break;
case Landmark.LEFT_EAR_TIP:
drawPoint(canvas, landmark.getPosition());
break;
case Landmark.RIGHT_EAR:
drawPoint(canvas, landmark.getPosition());
break;
case Landmark.RIGHT_EAR_TIP:
drawPoint(canvas, landmark.getPosition());
break;
}
}
/** Other useful details that may be of your interest */
Log.d("", "FaceDetection- FaceId:" + face.getId()
+ " Smiling:" + face.getIsSmilingProbability()
+ " LeftEyeOpen:" + face.getIsLeftEyeOpenProbability()
+ " RightEyeOpen:" + face.getIsRightEyeOpenProbability());
}
return outBitmap;
}
/** This method draws a rectangle */
private void drawRectangle(Canvas canvas, PointF point, float width, float height){
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
float x1 = point.x;
float y1 = point.y;
float x2 = x1 + width;
float y2 = y1 + height;
RectF rect = new RectF(x1, y1, x2, y2);
canvas.drawRect(rect, paint);
}
/** This method draws a point with hole */
private void drawPoint(Canvas canvas, PointF point){
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(48);
paint.setStyle(Paint.Style.STROKE);
float x = point.x;
float y = point.y;
canvas.drawCircle(x, y, 1, paint);
}
}
这是我的错误。
04-24 12:59:50.231 2865-2865/com.example.andy318.cameraone E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.andy318.cameraone, PID: 2865
java.lang.RuntimeException: Unable to resume activity {com.example.andy318.cameraone/com.example.andy318.cameraone.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.graphics.PointF com.google.android.gms.vision.face.Face.getPosition()' on a null object reference
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3103)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3134)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2481)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4077)
at android.app.ActivityThread.-wrap15(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1350)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.graphics.PointF com.google.android.gms.vision.face.Face.getPosition()' on a null object reference
at com.example.andy318.cameraone.MainActivity.drawOnFace(MainActivity.java:106)
at com.example.andy318.cameraone.MainActivity.onResume(MainActivity.java:69)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1258)
at android.app.Activity.performResume(Activity.java:6312)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3092)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3134)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2481)
at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4077)
at android.app.ActivityThread.-wrap15(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1350)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
错误发生在
Bitmap outBitmap = drawOnFace(faceArray);
和
drawRectangle(canvas, face.getPosition(), face.getWidth(), face.getHeight());
我在编码中放了**。
我知道我的错误在哪里,但我不知道如何解决。屏幕旋转后,SparseArray faceArray 有空值。我尝试使用 if 来检查 null 条件,但它不会显示检测结果。 (只显示原图)
java.lang.NullPointerException: 尝试在空对象引用
上调用虚拟方法'Face.getPosition()'
你的脸变量为空!
http://developer.android.com/reference/android/media/FaceDetector.html
你从哪里得到 detect() ? nvm,发现它:
https://developers.google.com/android/reference/com/google/android/gms/vision/face/FaceDetector.html#public-methods
也许您需要使 SparseArray 成为最终的或所有面在里面或类似的东西?
你得到的只是密钥,不是对象:
使用此代码:
for(int i = 0; i < faceArray.size(); i++) {
int key = faceArray.keyAt(i);
// get the object by the key.
Face face = faceArray.get(key);
}
目前我正在使用 Google Mobile Vision API 进行人脸检测。假设屏幕旋转后,activity会重新启动,所有变量都会重新初始化。但是,我不知道为什么该应用程序停止工作并显示 NullPointerException。这是我的代码。
public class MainActivity extends AppCompatActivity {
private ImageView mIvDetected;
private Bitmap mImage;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIvDetected = (ImageView) findViewById(R.id.iv_detected);
//Load an image
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inMutable = true;
mImage = BitmapFactory.decodeResource(getResources(), R.drawable.face2);
//Configure FaceDetector
FaceDetector detector = new FaceDetector.Builder(this)
.setMode(FaceDetector.ACCURATE_MODE)
.setLandmarkType(FaceDetector.ALL_LANDMARKS)
.setClassificationType(FaceDetector.ALL_CLASSIFICATIONS)
.setTrackingEnabled(false)
.build();
if(false == detector.isOperational()){
Toast.makeText(this, "Face detection service is not ready", Toast.LENGTH_SHORT).show();
return;
}
//Add the image on a Frame object
Frame frame = new Frame.Builder().setBitmap(mImage).build();
//Detect all faces from Frame object
SparseArray<Face> faceArray = detector.detect(frame);
//Do some drawing on faces
**Bitmap outBitmap = drawOnFace(faceArray);**
mIvDetected.setImageBitmap(outBitmap);
//Releasing the detector object
detector.release();
}
/** Method to do some drawing on faces */
private Bitmap drawOnFace(SparseArray<Face> faceArray){
Paint mIdPaint = new Paint();
mIdPaint.setColor(Color.RED);
mIdPaint.setTextSize(40.f);
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
Paint mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setDither(true);
mTextPaint.setTextSize(20);
mTextPaint.setColor(Color.GREEN);
mTextPaint.setStyle(Paint.Style.FILL);
// Create a blank bitmap same size with the source image
Bitmap outBitmap = Bitmap.createBitmap(mImage.getWidth(), mImage.getHeight(), Bitmap.Config.RGB_565);
// Put the bitmap on canvas for drawing
Canvas canvas = new Canvas(outBitmap);
canvas.drawBitmap(mImage, 0, 0, null);
for(int i=0; i < faceArray.size(); i++){
Face face = faceArray.get(i);
//Drawing rectangle on each face
**drawRectangle(canvas, face.getPosition(), face.getWidth(), face.getHeight());**
//Drawing a point on each face features
for(Landmark landmark : face.getLandmarks()) {
switch (landmark.getType()){
case Landmark.LEFT_EYE:
drawPoint(canvas, landmark.getPosition());
canvas.drawText("Left eye: " + face.getIsLeftEyeOpenProbability(), landmark.getPosition().x, landmark.getPosition().y - 30, mTextPaint);
break;
case Landmark.RIGHT_EYE:
drawPoint(canvas, landmark.getPosition());
canvas.drawText("Right eye: " + face.getIsRightEyeOpenProbability(), landmark.getPosition().x, landmark.getPosition().y - 30, mTextPaint);
break;
case Landmark.BOTTOM_MOUTH:
drawPoint(canvas, landmark.getPosition());
canvas.drawText("Smile: " + face.getIsSmilingProbability(), landmark.getPosition().x, landmark.getPosition().y + 40, mTextPaint);
break;
case Landmark.LEFT_MOUTH:
drawPoint(canvas, landmark.getPosition());
break;
case Landmark.RIGHT_MOUTH:
drawPoint(canvas, landmark.getPosition());
break;
case Landmark.NOSE_BASE:
drawPoint(canvas, landmark.getPosition());
break;
case Landmark.LEFT_CHEEK:
drawPoint(canvas, landmark.getPosition());
break;
case Landmark.RIGHT_CHEEK:
drawPoint(canvas, landmark.getPosition());
break;
case Landmark.LEFT_EAR:
drawPoint(canvas, landmark.getPosition());
break;
case Landmark.LEFT_EAR_TIP:
drawPoint(canvas, landmark.getPosition());
break;
case Landmark.RIGHT_EAR:
drawPoint(canvas, landmark.getPosition());
break;
case Landmark.RIGHT_EAR_TIP:
drawPoint(canvas, landmark.getPosition());
break;
}
}
/** Other useful details that may be of your interest */
Log.d("", "FaceDetection- FaceId:" + face.getId()
+ " Smiling:" + face.getIsSmilingProbability()
+ " LeftEyeOpen:" + face.getIsLeftEyeOpenProbability()
+ " RightEyeOpen:" + face.getIsRightEyeOpenProbability());
}
return outBitmap;
}
/** This method draws a rectangle */
private void drawRectangle(Canvas canvas, PointF point, float width, float height){
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.STROKE);
float x1 = point.x;
float y1 = point.y;
float x2 = x1 + width;
float y2 = y1 + height;
RectF rect = new RectF(x1, y1, x2, y2);
canvas.drawRect(rect, paint);
}
/** This method draws a point with hole */
private void drawPoint(Canvas canvas, PointF point){
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(48);
paint.setStyle(Paint.Style.STROKE);
float x = point.x;
float y = point.y;
canvas.drawCircle(x, y, 1, paint);
}
}
这是我的错误。
04-24 12:59:50.231 2865-2865/com.example.andy318.cameraone E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.andy318.cameraone, PID: 2865 java.lang.RuntimeException: Unable to resume activity {com.example.andy318.cameraone/com.example.andy318.cameraone.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.graphics.PointF com.google.android.gms.vision.face.Face.getPosition()' on a null object reference at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3103) at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3134) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2481) at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4077) at android.app.ActivityThread.-wrap15(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1350) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.graphics.PointF com.google.android.gms.vision.face.Face.getPosition()' on a null object reference at com.example.andy318.cameraone.MainActivity.drawOnFace(MainActivity.java:106) at com.example.andy318.cameraone.MainActivity.onResume(MainActivity.java:69) at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1258) at android.app.Activity.performResume(Activity.java:6312) at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3092) at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3134) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2481) at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4077) at android.app.ActivityThread.-wrap15(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1350) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
错误发生在
Bitmap outBitmap = drawOnFace(faceArray);
和
drawRectangle(canvas, face.getPosition(), face.getWidth(), face.getHeight());
我在编码中放了**。
我知道我的错误在哪里,但我不知道如何解决。屏幕旋转后,SparseArray faceArray 有空值。我尝试使用 if 来检查 null 条件,但它不会显示检测结果。 (只显示原图)
java.lang.NullPointerException: 尝试在空对象引用
上调用虚拟方法'Face.getPosition()'你的脸变量为空!
http://developer.android.com/reference/android/media/FaceDetector.html
你从哪里得到 detect() ? nvm,发现它: https://developers.google.com/android/reference/com/google/android/gms/vision/face/FaceDetector.html#public-methods
也许您需要使 SparseArray 成为最终的或所有面在里面或类似的东西?
你得到的只是密钥,不是对象:
使用此代码:
for(int i = 0; i < faceArray.size(); i++) {
int key = faceArray.keyAt(i);
// get the object by the key.
Face face = faceArray.get(key);
}