How to resolve the ANR error while invoking the Ca

2019-01-20 13:54发布

问题:

I have two button's in the main menu. I invoking the camera when I press the 1st button. Here I didn't get any issue. Camera working properly. After taking the picture, I come back in to main menu and again I press the 1st button. Here I got the issue. Camera invoking properly. But I got ANR error (Reason: keyDispatchingTimedOut) while i'm taking the picture. How to resolve this issue?

Edit::

I'm using following code,

Button Listener,

Button imageButton = (Button) findViewById(R.id.button1);
imageButton.setOnClickListener(new  View.OnClickListener() {

    public void onClick(View arg0) {
    Intent intent = new Intent();
    intent.setClass(activity, ImageActivity.class);
    startActivity(intent);
    }
});

ImageActivity.java

public class ImageActivity extends Activity implements SurfaceHolder.Callback {
    private Camera camera = null;
    private SurfaceHolder surfaceHolder = null;
    private boolean previewRunning = false;
    private Button btnDone, btnCapture, btnRetake;
    private Bitmap mBitmap;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().setFormat(PixelFormat.TRANSLUCENT);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.surface_screen);
        SurfaceView surfaceView = (SurfaceView) findViewById(R.id.camerapreview);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        surfaceHolder.setFixedSize(getWindow().getWindowManager()
                .getDefaultDisplay().getWidth(), getWindow().getWindowManager()
                .getDefaultDisplay().getHeight());
        LayoutInflater  controlInflater = LayoutInflater.from(getBaseContext());

        final View viewControl = controlInflater.inflate(R.layout.control, null);
        LayoutParams layoutParamsControl = new LayoutParams(
                LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
        activity.addContentView(viewControl, layoutParamsControl);

        btnCapture = (Button) findViewById(R.id.takepicture);

        btnDone = (Button) findViewById(R.id.send);

        btnCapture.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                camera.takePicture(null, picCalBac, picCalBac);
            }
        });


    Camera.PictureCallback picCalBac = new PictureCallback() {

        public void onPictureTaken(byte[] data, Camera camera) {
            if (data != null) {
                mBitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
            }
        }
    };

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        if (previewRunning) {
            camera.stopPreview();
        }
        try {
            camera.setPreviewDisplay(surfaceHolder);
        } catch (IOException e) {
            Log.d("IOException", e.getMessage());
        }
        camera.startPreview();
        previewRunning = true;
    }

    public void surfaceCreated(SurfaceHolder arg0) {
        camera = Camera.open(0);
    }

    public void surfaceDestroyed(SurfaceHolder arg0) {
        camera.stopPreview();
        previewRunning = false;
        camera.release();
    }
}

回答1:

You might have gone through this link while searching for the error.

Though I never had such issue, after reading on the Internet, this is what I understand:

Description :

ANR or Application Not Responding error occurs when a process on the main thread takes too long (something like > 5 seconds). Android kills that process and any related by design to spare the device's resources.

The solution is to run resource-expensive tasks on another thread, and then post, or update the main thread accordingly.

See This : Android ANR keyDispatchingTimedOut

So in your case you may be conflicting two different threads from the one that keeps running for long time and Android kills them. The next related code also gets affected.

So better classify your code, write each new task in different Thread,Handler and if you're doing a UI task, use runOnUIThread. Async Task is also very Handy.

Another thing is to try to remove dependency of code on other. Write some default values and from that you can send user back to first task if it's not done properly.

I believe the error is from your coding Style, not because of any specific error in your code.

You need to improve your that particular code to perform efficiently and for that see these 2 links:

  1. Design for Responsiveness
  2. Painless Threading

EDIT:

This I read somewhere and found effective is,

How to investigate ANR ?

First, go over your code and look for vunerable spots and long running operations. Examples may include using sockets, locks, thread sleeps, and other blocking operations from within the event thread. You should make sure these all happen in separate threads. If nothing seems the problem, use DDMS and enable the thread view. This shows all the threads in your application similar to the trace you have. Reproduce the ANR, and refresh the main thread at the same time. That should show you precisely whats going on at the time of the ANR

Also If ANR is caused because of Threads ?

you can user Service for that, So your app can do the time consuming tasks inside service.onStart(), passing data (for example) in the intent used to start the service.

However, Services execute on the main application thread. If a separate thread is needed, it can be created by the service inside onStart().

There is already a built-in class that does this: IntentService

Also found one helpful library application SalomonBrys/ANR-WatchDog



回答2:

Android applications normally run entirely on a single (i.e. main) thread. This means that anything your application is doing in the main thread that takes a long time to complete can trigger the ANR dialog because your application is not giving itself a chance to handle the input event or Intent broadcast.So in that case you can use StrictMode to help find potentially long running operations such as network or database operations that you might accidentally be doing your main thread. If you find violations that you feel are problematic, there are a variety of tools to help solve them: threads, Handler, AsyncTask, IntentService, etc.Also remember that it came from API Level 9

Example code to enable from early in your Application, Activity, or other application component's onCreate() method:

 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                 .detectDiskReads()
                 .detectDiskWrites()
                 .detectNetwork()   // or .detectAll() for all detectable problems
                 .penaltyLog()
                 .build());
         StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                 .detectLeakedSqlLiteObjects()
                 .detectLeakedClosableObjects()
                 .penaltyLog()
                 .penaltyDeath()
                 .build());


回答3:

I think you already know about this,

The single thread model can yield poor performance in Android applications that do not consider the implications. Since everything happens on a single thread performing long operations, like network access or database queries, on this thread will block the whole user interface. No event can be dispatched, including drawing events, while the long operation is underway. *From the user's perspective, the application appears hung*. Even worse, if the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with the infamous "application not responding" (ANR) dialog.

An ANR happens when some long operation takes place in the "main" thread. This is the event loop thread, and if it is busy, Android cannot process any further GUI events in the application, and thus throws up an ANR dialog.

What Triggers ANR?

In Android, application responsiveness is monitored by the Activity Manager and Window Manager system services. Android will display the ANR dialog for a particular application when it detects one of the following conditions:

* No response to an input event (e.g. key press, screen touch) within 5 seconds
* A BroadcastReceiver hasn't finished executing within 10 seconds

How to resolve it please look at Designing for Responsiveness

EDIT:

So, Try to use other separate worker thread, handler, AsyncTask or UIThread for your camera stuff (media recorder) instead of main thread of activity..

1). Do "adb shell cat /data/anr/traces.txt" to see what your app was busy doing at that point. This is the very first step you need to take: understand what your app is doing that is causing the ANR.

When the ANR happens all of the process's stacks are written to this file, with the process being accused of the ANR first. All this is doing is dumping the file so you can look at it. So you just want to look at it some time after the ANR, before another ANR happens.

2). If nothing seems the problem, use DDMS and enable the thread view. This shows all the threads in your application similar to the trace you have. Reproduce the ANR, and refresh the main thread at the same time. That should show you precisely whats going on at the time of the ANR.

Fore more just go through this http://android-developers.blogspot.com/2009/05/painless-threading.html



回答4:

May be you initialize and launch the media recorder in main thread itself either in Oncreate() or in Onresume(), instead of launching camera in main thread use separeate Handler to launch a camera for taking photos, it will act like child of main UI thread .

Using Handler you reduce the time and ANR will not be occur.



回答5:

It seems that the camera resource is not being release, thus causing the ANR.

The code looks a bit messy. You can take a look at the api example for camera preview:

You will have to implement onPause and onResume for it to work reliably.