I am creating a simple Flashlight App, but every time I leave the app and reopen it, it crashes. Am I missing something in my code, because I am not sure what, below is an error when it crashes. Please let me know what I need to do in order to fix this resume issue:
package com.example.gkvxm.materiallight;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.Toast;
import com.dd.CircularProgressButton;
import java.io.IOException;
public class FlashLightActivity extends Activity implements SurfaceHolder.Callback {
private boolean isLigtOn = false;
private Camera camera;
@Override
protected void onStart(){
super.onStart();
SurfaceView preview = (SurfaceView)findViewById(R.id.PREVIEW);
SurfaceHolder mHolder = preview.getHolder();
mHolder.addCallback(this);
}
@Override
protected void onStop(){
super.onStop();
if(camera!=null){
camera.release();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flash_light);
Context context = this;
PackageManager pm = context.getPackageManager();
if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Toast.makeText(FlashLightActivity.this, "Your Device is not supported", Toast.LENGTH_SHORT).show();
Log.e("err", "Device is not supported");
return;
}
camera = Camera.open();
final Camera.Parameters p = camera.getParameters();
final CircularProgressButton circularButton1 = (CircularProgressButton) findViewById(R.id.btnWithText);
circularButton1.setIndeterminateProgressMode(true);
circularButton1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isLigtOn) {
turnOffFlash(p);
Toast.makeText(FlashLightActivity.this, "Lights Off!", Toast.LENGTH_SHORT).show();
} else {
turnOnFlash(p);
Toast.makeText(FlashLightActivity.this, "Lights On!", Toast.LENGTH_SHORT).show();
}
if (circularButton1.getProgress() == 0) {
simulateSuccessProgress(circularButton1);
} else {
circularButton1.setProgress(0);
}
}
});
}
private void turnOnFlash(Camera.Parameters p){
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(p);
camera.startPreview();
isLigtOn = true;
}
private void turnOffFlash(Camera.Parameters p){
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(p);
camera.stopPreview();
isLigtOn = false;
}
@Override
public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){
}
@Override
public void surfaceCreated(SurfaceHolder holder){
try{
Log.i("SurfaceHolder","Setting preview");
camera.setPreviewDisplay(holder);
} catch (IOException e){
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder){
Log.i("SurfaceHOlder", "stopping preview");
camera.stopPreview();
holder = null;
}
private void simulateSuccessProgress(final CircularProgressButton button) {
ValueAnimator widthAnimation = ValueAnimator.ofInt(1, 100);
widthAnimation.setDuration(1500);
widthAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
widthAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
button.setProgress(value);
}
});
widthAnimation.start();
}
private void simulateErrorProgress(final CircularProgressButton button) {
ValueAnimator widthAnimation = ValueAnimator.ofInt(1, 99);
widthAnimation.setDuration(1500);
widthAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
widthAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
button.setProgress(value);
if (value == 99) {
button.setProgress(-1);
}
}
});
widthAnimation.start();
}
}
Error :
05-22 03:08:35.646 13909-13909/com.example.gkvxm.materiallight E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.gkvxm.materiallight, PID: 13909
java.lang.RuntimeException: Camera is being used after Camera.release() was called
at android.hardware.Camera._stopPreview(Native Method)
at android.hardware.Camera.stopPreview(Camera.java:732)
at com.example.gkvxm.materiallight.FlashLightActivity.surfaceDestroyed(FlashLightActivity.java:129)
at android.view.SurfaceView.updateWindow(SurfaceView.java:564)
at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:238)
at android.view.View.dispatchWindowVisibilityChanged(View.java:8785)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1164)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1164)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1164)
at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1164)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1318)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5885)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
at android.view.Choreographer.doCallbacks(Choreographer.java:580)
at android.view.Choreographer.doFrame(Choreographer.java:550)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Camera is being used after Camera.release()
was called. So, looking at the activity lifecycle, you need to open the camera in onStart()
or in onRestart()
. So Maybe this code will work fine ...
package com.example.gkvxm.materiallight;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.Toast;
import com.dd.CircularProgressButton;
import java.io.IOException;
public class FlashLightActivity extends Activity implements SurfaceHolder.Callback {
private boolean isLigtOn = false;
private Camera camera;
@Override
protected void onStart(){
super.onStart();
camera = Camera.open();
final Camera.Parameters p = camera.getParameters();
SurfaceView preview = (SurfaceView)findViewById(R.id.PREVIEW);
SurfaceHolder mHolder = preview.getHolder();
mHolder.addCallback(this);
}
@Override
protected void onStop(){
super.onStop();
if(camera!=null){
camera.release();
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flash_light);
Context context = this;
PackageManager pm = context.getPackageManager();
if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Toast.makeText(FlashLightActivity.this, "Your Device is not supported", Toast.LENGTH_SHORT).show();
Log.e("err", "Device is not supported");
return;
}
camera = Camera.open();
final Camera.Parameters p = camera.getParameters();
final CircularProgressButton circularButton1 = (CircularProgressButton) findViewById(R.id.btnWithText);
circularButton1.setIndeterminateProgressMode(true);
circularButton1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isLigtOn) {
turnOffFlash(p);
Toast.makeText(FlashLightActivity.this, "Lights Off!", Toast.LENGTH_SHORT).show();
} else {
turnOnFlash(p);
Toast.makeText(FlashLightActivity.this, "Lights On!", Toast.LENGTH_SHORT).show();
}
if (circularButton1.getProgress() == 0) {
simulateSuccessProgress(circularButton1);
} else {
circularButton1.setProgress(0);
}
}
});
}
private void turnOnFlash(Camera.Parameters p){
p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
camera.setParameters(p);
camera.startPreview();
isLigtOn = true;
}
private void turnOffFlash(Camera.Parameters p){
p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
camera.setParameters(p);
camera.stopPreview();
isLigtOn = false;
}
@Override
public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){
}
@Override
public void surfaceCreated(SurfaceHolder holder){
try{
Log.i("SurfaceHolder","Setting preview");
camera.setPreviewDisplay(holder);
} catch (IOException e){
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder){
Log.i("SurfaceHOlder", "stopping preview");
camera.stopPreview();
holder = null;
}
private void simulateSuccessProgress(final CircularProgressButton button) {
ValueAnimator widthAnimation = ValueAnimator.ofInt(1, 100);
widthAnimation.setDuration(1500);
widthAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
widthAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
button.setProgress(value);
}
});
widthAnimation.start();
}
private void simulateErrorProgress(final CircularProgressButton button) {
ValueAnimator widthAnimation = ValueAnimator.ofInt(1, 99);
widthAnimation.setDuration(1500);
widthAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
widthAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
button.setProgress(value);
if (value == 99) {
button.setProgress(-1);
}
}
});
widthAnimation.start();
}
}