3

I want to use AsyncTask to open the camera as suggested here http://developer.android.com/reference/android/hardware/Camera.html#open%28int%29:

Caution: On some devices, this method may take a long time to complete. It is best to call this method from a worker thread (possibly using AsyncTask) to avoid blocking the main application UI thread.

So something like:

onResume(){
    new AsyncTask(){
        doItInBackground(){
            camera_ref = Camera.open();
        }
    }.execute();
}

then in on Pause() I must release the camera:

onPause(){ if(camera_ref!=null) camera_ref.release(); }

Question: What can I do to be sure that open() will never be called after release()? Putting open() inside a synchronized block with a boolean variable shouldn't be a solution since this would still block the UI thread.

In general this problem applies to every situation where I call camera_ref.something() inside a callback method...since I got to be sure this call happens only between open() and release() while the callback method can be called from the UI thread in every moment.

Probably I'm missing something. I'd like to see the way it should be done.

EDIT: As of now, I think the best solution could be to use an IntentService as described here: http://developer.android.com/guide/components/services.html. In particular:

The IntentService does the following:

- Creates a default worker thread.
- Creates a work queue that passes one intent at a time.

That is what I was looking for. Using AsyncTask.executeOnExector(SINGLE_EXECUTOR) is not viable since the AsyncTasks may be killed before even starting. I'll take a further look at ThreadPoolExecutor to see if it may be a possible alternative.

type-a1pha
  • 1,891
  • 13
  • 19
  • I took a look at the code for the built-in camera application and its all very fuzzy!!! At first creation of the Activity the camera is opened in a Thread, but then at the end of onCreate a join is made on that thread thus possibly still blicking the UIThread. Moreover in the rest of the code the open() method is called directly from the UI Thread. I'll take a further look...maybe I misread...but for now seems like this. – type-a1pha Jul 20 '13 at 07:53

1 Answers1

1

Question: What can I do to be sure that open() will never be called after release()? Putting open() inside a synchronized block with a boolean variable shouldn't be a solution since this would still block the UI thread.

onResume() calls open() asynchronously, and onPause() calls release(), so your concern is that in theory if the Activity opens and closes quickly, it might call release() and then open(). So use [isFinishing]1:

onResume(){
    release = false;
    new AsyncTask(){
        doItInBackground(){
            if (!isFinishing())
                camera_ref = Camera.open();
        }
    }.execute();
}

onPause(){ if(camera_ref!=null) camera_ref.release(); }

Edit: my first answer was wrong :[

Yusuf X
  • 14,513
  • 5
  • 35
  • 47
  • In my scenario where camera.open() is called after camera.release(), the reference camera_ref is always null during onPause()! So it wouldn't change anything. Maybe you have misread...camera.open() is Camera.open() that is a static method...I have edited it, sorry. Neither it would solve the callbacs problem because the test+camera.operation() code part should be inside a synchronized block thus possibly blocking the UI thread. – type-a1pha Jul 12 '13 at 19:03