android camera classic API: writing a blocking (synchronous) 'takePicture()' - android

I'm writing an Android app and I need to take photos. I got it mostly working very quickly using the standard tutorial. But I need to write a blocking version of "takePicture()". I've trying reworking my design so that everything is done asynchronously, but the code just ends up as spaghetti code because so many tasks are dependent on the previous task completing. And I had expected that taking a photo would take less than a second. So I think it's a reasonable goal to have a blocking (synchronous) "takePicture()".
So I created a camera in the UI thread (I'm an Android newbie but I presume that 'onCreate()' et al are called in the UI thread). I also open the camera and release it in the UI thread. I also call "takePicture()" in the UI thread. I tried polling for a "volatile byte[] jpeg;" field to become non-null, with a "while (jpeg != null) sleep(1000);" but it never gets assigned. To my surprise, my callback doesn't get called until I pass out of the "onClick()" function - 'takePicture()' doesn't seem to trigger anything, it merely queues something, as far as I can figure out.
My next attempt involved doing all the camera work (open, takePicture, release) in a "ExecutorService.newSingleThreadExecutor()" but that was also unsuccessful. Even when I did it this way (see below), the callback wasn't called until the app finished the 'onClick()'.
public byte[] takePhoto()
{
if (camera == null)
return null;
cameraThreadService.submit(new Runnable() {
#Override
public void run() {
Camera.PictureCallback mPicture = new Camera.PictureCallback() {
#Override
public void onPictureTaken(byte[] data, Camera camera) {
jpeg = data;
}
};
camera.takePicture(null, null, mPicture);
}
});
int n = 0;
while (jpeg == null) {
sleep(1000);
if (n++ > 5)
break;
}
return jpeg;
}
Can anyone tell me how to write a blocking (synchronous) 'camera.takePicture()'?

To my surprise, my callback doesn't get called until I pass out of the "onClick()" function - 'takePicture()' doesn't seem to trigger anything, it merely queues something, as far as I can figure out.
Your onPictureTaken() is called on the main application thread. The main application thread cannot do two things at once. onPictureTaken() cannot be called until after you return from onClick().
Can anyone tell me how to write a blocking (synchronous) 'camera.takePicture()'?
That is not possible, sorry.

Related

Java - Android : Thread being called (run) twice

I would like some help regarding Java - Android MultiThreading
While learning to develop my app in a multi-threading way in order to take advantage of the ever-growing multi-core devices market share (most devices are quad core now, some even octo-core), I ran in a situation where my threads are either being calling twice or running twice.
I just don't why and how.
[EDIT 3]
Alright, I narrowed down the issue : I called the AsyncTask from the onResume() method. Although my app did not lost focus (which would mean a call to onPause() then back to onResume() upon return of focus in which case my threads would be run twice) during the tests, I solved the issue by moving away the call to FetchFriendsList to another place.
So far so good, but since in my tests the app did not loose focus or perhaps it did but I could not witness it (!), I think there is another reason behind so I'd say my problem is not entirely solved ... at least for the moment. It does work though. Perhaps I did solve the issue but I do not know how :(
[end of EDIT 3]
I am implementing last Facebook SDK and I am using it to fetch the end-user friends list, which seems to do the work.
Since I am running this operation in an AsyncTask, I am not using request.executeAsync().
Instead I am using request.executeAndWait(). Facebook JavaDoc does state that this method must only be used if I am not in a the Main UI Thread which is my case otherwise I would get a NetworkOnMainThreadException.
Anyway, this is where the weird behavior is happening.
private final ArrayList<GraphUser> userFriendsList = new ArrayList<GraphUser>();
public final void fetchFriendsList() {
if (this.session != null && this.session.isOpened()) {
final Request requestUserFriendsList = Request.newMyFriendsRequest(
this.session, new Request.GraphUserListCallback()
public final void onCompleted(final List<GraphUser> users, final Response response) {
if (users != null && users.size() > 0) {
Log.v("Retrieved Friends List -> ", String.valueOf(users.size()));
userFriendsList.addAll(users);
}
}
}
);
if (this.asyncFlag)
requestUserFriendsList.executeAsync();
else
requestUserFriendsList.executeAndWait();
}
}
In my case, asyncFlag is set to false because I need to do stuff synchronously in that specific order :
Fetch User Friends List (not on the Main (UI) Thread)
Save friends list on device (separate new thread)
Save friends list on a server (separate new thread)
Following this pattern, the line userFriendsList.addAll(users); is called twice.
In the logcat, the Log.vis showed twice as well, and finally looking with the debugger, the content of the user friends list is made of duplicates.
But that's not all ... step 2 and 3 are indeed two separate threads which are both created and spawned within the same method : public final void asyncSaveFacebookFriendsList().
And guess what, this method is even called twice !
just why ?
At the beginning I was calling the method for step 2 and 3 like this :
[...]
userFriendsList.addAll(users);
asyncSaveFacebookFriendsList(); // it was private before
[...]
This is where the issue started as both line were running twice.
So I thought, alright, I'll call it later like this :
[...]
fetchFriendsList();
asyncSaveFacebookFriendsList(); // it is now public
[...]
But the issue remains still.
If I don't call public final void asyncSaveFacebookFriendsList(), then nothing is run twice.
Why does this issue happen ? Is there something I did not get in Java Threads ?
I do not think this is somehow related to the Facebook SDK because following the same pattern (and doing it also at the same time), I have the same issues when fetching and storing the end-user Twitter friends list.
So I do believe I am doing something wrong. Does someone have any idea in what possible case a thread is called twice ?
Note : all threads are started this way : thread.start(). I am not using any ThreadPool nor the ExecutorService.
In case you need more background context :
Content of AsyncTask : (no need to wonder why Void and Long, I remove the irrelevant code related to it)
private final class FetchFriendsLists extends AsyncTask<Long, Integer, Void> {
protected final Void doInBackground(final Long... params) {
if (params[0] != Long.valueOf(-1)) {
[...]
twitterAPI.fetchUserFriendsList();
publishProgress(1, -1);
}
if (params[1] == Long.valueOf(0)) {
[...]
facebookAPI.fetchFriendsList();
publishProgress(-1, 0);
}
return null;
}
protected final void onProgressUpdate(Integer... flags) {
super.onProgressUpdate(flags);
if (flags[0] != -1)
twitterAPI.asyncSaveFacebookFriendsList();
if (flags[1] == 0)
facebookAPI.asyncSaveFacebookFriendsList();
}
}
As you can see, I start step 2 and 3 in onPublishProgress() which runs on the Main UI Thread. Brefore it was in the doInBackground() method : the issue happens in both cases!
[EDIT]
After further test, it would seem any kind of code is in fact running twice.
I created a simple method called test in which in print a counter. The counter incremente twice as well !
Why you use onProgressUpdate?¿?
onProgressUpdate(Progress...), [...]. This method is used to display any form of progress in the
user interface while the background computation is still executing.
For instance, it can be used to animate a progress bar or show logs in
a text field.
This is used not at the finish of the petition, but when progress increased.
Read this:
http://developer.android.com/reference/android/os/AsyncTask.html
You need to use:
protected void onPostExecute(Long result) {

Android dynamic UI update from AsynchTask/Handler and Thread priorities

I am using an AsynchTask to host a simulator that runs indefinelly and posts the results after each simulation step.
Limiting the simulation loop in background at a maximum of 25Hz, and only calling a javascript function with the results, it works "fine".
Apart from updating a webgl model in a browser, what looks fast enough, I have two more things to update from the Android UI: the FPS indicator and the panel with TextViews representing some of the values. If we forget about the FPS:
The onProgressUpdate() function is already limited to be called at 25Hz, to refresh the model. Now I use another time variable to limit, inside this method, the call to another method that updates the UI panel textViews. It is limited to 1Hz, less than what I actually wanted but fast enough for the kind of information. The method is as clean as possible, all the views are previously loaded to a variable that I keep to not load them every time.
What is the effect: looks like updating 5 textViews takes like one second where all the UI freezes, the touch moves are very very laggy...
I decreased the priority of the background task with:
#Override
protected Boolean doInBackground(ModelSimulation... params) {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
...
And used Thread.yield() at the end of the doInBackground method. This improves the behavior to what I explained, without these commands, the behavior is even worst.
My questions are:
-Can I reduce even more the priority if instead of using a background task I use a handler and my own Thread?
-Will a service improve the behavior of the UI?
-Why updating 5 textViews takes so long compared with calling a javascript function that finally will have to use the gpu to change the webgl model?
-Is Android not prepared in any sens to do dynamic applications? How applications like the ones to test sensors update so fast the UI? because there are not standar components like the textViews? (like browser going faster than a textView)
Note: even reducing the refreshing limitations, it produce a laggy effect every time the HUD is updated. In fact I talk about 5 textViews but only updating the FPS indicator produces the same pause. Looks like the only fact of having to switch to the UI thread already consumes this time.
Edit 1:
#Override
protected Boolean doInBackground(ModelSimulation... params) {
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
if(simulator.getSimulatorStatus().equals(SimulatorStatus.Connected)){
try {
while (true){
//TODO Propagate
long dur = (System.nanoTime()-time_tmp_data);
if(dur<Parameters.Simulator.min_hud_model_refreshing_interval_ns){
try {
long sleep_dur = (Parameters.Simulator.min_hud_model_refreshing_interval_ns-(System.nanoTime()-time_tmp_data))/1000000;
if(sleep_dur>0){
Thread.sleep(sleep_dur);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
time_tmp_data = System.nanoTime();
SpacecraftState sstate = propagate();
int progress = (int)((extrapDate.durationFrom(finalDate)/mission.sim_duration)*100);
if(sstate!=null){
SimResults results = new SimResults(sstate, progress);
simulator.getSimulationResults().updateSimulation(results.spacecraftState, results.sim_progress);
publishProgress();
}
if(isCancelled())
break;
Thread.yield();
}
} catch (OrekitException e) {
// TODO Auto-generated catch block
e.printStackTrace();
simulator.showMessage(simulator.getContext().getString(R.string.sim_orekit_prop_error)+": "+e.getMessage());
}
}
return true;
}
#Override
protected void onProgressUpdate(Void... values) {
//Update model by push
simulator.getSimulationResults().pushSimulationModel();
//Update GUI HUD
if(time_tmp_gui==0 || (System.nanoTime()-time_tmp_gui)>Parameters.Simulator.min_hud_panel_refreshing_interval_ns){
time_tmp_gui = System.nanoTime();
simulator.getSimulationResults().updateHUD();
}
}
If I comment the line simulator.getSimulationResults().updateHUD(); or directly the contents of the method, it works "fine". And this method is only changing some textviews text:
public synchronized void updateHUD(){
//Log.d("Sim",System.currentTimeMillis()+": "+"pre update gui 1");
activity.runOnUiThread( new Runnable() {
#SuppressLint("ResourceAsColor")
public void run() {
if(view != null){
if(panel_time != null)
panel_time.setText(info.time.replace("T", " "));
if(panel_progress != null)
panel_progress.setProgress(info.progress);
if(panel_vel != null){
panel_vel.setText("Vel. "+String.format("%.2f", info.velocity)+" Km/s");
if(info.velocity>config.limit_velocity)
panel_vel.setTextColor(activity.getResources().getColor(R.color.panel_limit));
else
panel_vel.setTextColor(activity.getResources().getColor(R.color.panel_value));
}
if(panel_accel != null){
panel_accel.setText("Accel. "+String.format("%.2f", info.acceleration)+" Km/s2");
if(info.acceleration>config.limit_acceleration)
panel_accel.setTextColor(activity.getResources().getColor(R.color.panel_limit));
else
panel_accel.setTextColor(activity.getResources().getColor(R.color.panel_value));
}
if(panel_radium != null)
panel_radium.setText("Orbit radium: "+String.format("%.1f", info.orbit_radium)+" Km");
if(panel_mass != null)
panel_mass.setText("Mass: "+String.format("%.1f", info.mass)+" Kg");
if(panel_roll != null)
panel_roll.setText("Rol: "+String.format("%.1f", (180*info.roll/Math.PI))+"º");
if(panel_pitch != null)
panel_pitch.setText("Pitch: "+String.format("%.1f", (180*info.pitch/Math.PI))+"º");
if(panel_yaw != null)
panel_yaw.setText("Yaw: "+String.format("%.1f", (180*info.yaw/Math.PI))+"º");
}
}
});
//Log.d("Sim",System.currentTimeMillis()+": "+"post update gui 1");
}
Edit 2: I can actually remove the runOnUiThread since it is already at that thread, but the effect is the same, this is not the problem.
Edit 3: I tried to comment all the lines of the method updateHUD() and leave only these two:
if(panel_time != null)
panel_time.setText(info.time.replace("T", " "));
The effect is almost the same, if I touch any textView, the animation goes by steps like periodically freezing
Edit 4:
I noticed that the process inside the AsyncTask was taking longer than the available step time so it was never sleeping. I established a safe guard time of 10ms that is slept even if the simulation step is longer than the available time. So, I have minimum 10ms free of each 100ms. The efect stills the same. I am updating at 25Hz the browser and 1Hz a single textview text. If I disable the textview update, the webgl model animates smoothly. On the other hand, if I enable the textview update too, every time the text is updated, there are some miliseconds where the browser animation and its response to touches are blocked. This effect gets worst if I increase the task priority. I tried setting a huge guard of 500ms but the freezing effect stills appearing. I am using XWalkView, can it be something blocking the interaction of this view when UI Thread is acting?
I can't understand why a 4 core 2 RAMgb device needs way more time to compute the same simulation than in Linux or windows desktop PC. I have 25Hz-->40ms of available time and the steps take almost 70ms. In a PC I could keep the simulation at 25Hz in real time. Is there so much shit running in background in Android compared to other OS?
There must be another issue with your code. Try posting your AsyncTask in here.
You could also try something very basic like:
Create a new Thread that loops every 25Hz and update your UI by using the post() method of your UI elements or the runInUiThread() of your Activity. See if there's any code still running inside the UI Thread, that could do heavy work, that can be done outside the UI Thread.
I tried literally everything except for the most logic thing, trying the application without the debugger connected.
The reason to have slower simulation than in a PC, to freese UI events... all because the debugger takes a lot of resources from the device. So, I guess that from this point and avobe I will have to test the application without debugger, what forces me to reboot the phone each time to avoid the "waiting for debugger to connect".
Thank to all who tried.
I could be wrong, but I think that yours problem in synchronization on simulator.getSimulationResults() object. I can't see the realization of the simulator class and realization of the object returned by getSimulationResults(), but I suppose that getSimulationResults() returns the same object every time? If so, then it can be looks like this:
In the AsyncTaks call simulator.getSimulationResults().updateSimulation(...). If this method is synchronized, then this call will be lock the SimulationResults object for AsyncTaks thread.
updateSimulation(...) returns, and publishProgress() is called, but publishProgress() is only schedule the onProgressUpdate(Void... values) in the UI thread.
The new iteration in the AsyncTaks thread can be started befor the UI thread gets the control and executes onProgressUpdate(Void... values). So, AsyncTaks thread goes to the first step.
The UI thread gets the control and executes the onProgressUpdate(Void... values) and synchronized void updateHUD() methods, but updateHUD() can't be executed, because SimulationResults object is locked by the AsyncTaks thread in the updateSimulation(...) method. So the UI thread returns the control to the OS. This may occur many times.
So, onProgressUpdate(Void... values) method and all events in the UI thread can be executed only if the UI thread gets the control in the right moment when updateSimulation(...) method is not called in the AsyncTask thread.
You can check this idea by replacing the public synchronized void update HUD() on the public void update HUD(), and write something randomly in the TextView.
In any case, the use of AsyncTask in this case is not the best idea. AsyncTask's are executed in the TheadPool, but in the Android system this pool can consist from only one thread. So, all AsyncTask's will be executed one by one in the one thread.

How to avoid queueEvent at GLSurfaceView in the case of the same thread

I am writing the program which processes Android OpenGL at other thread. But it freezes in case of this code. For example, it processes a method directly without calling task.get(), if it's the same thread. Does such a way exist?
public void onSurfaceCreated(GL10 arg0, EGLConfig arg1)
{
Thread t = new Thread(new Runnable(){
#Override
public void run()
{
FutureTask<Object> task = new FutureTask<Object>(new Callable<Object>() {
#Override
public Object call() {
return null;
}
});
gv.queueEvent(task);
try{
task.get();
}catch(Exception e){
}
Log.i("MainActivity", "Done"); // <- Work
}
});
t.start();
FutureTask<Object> task = new FutureTask<Object>(new Callable<Object>() {
#Override
public Object call() {
return null;
}
});
gv.queueEvent(task);
try{ task.get(); }catch(Exception e){} // <- Freeze
Log.i("MainActivity", "Done");
If I interpret your question correctly, there is some code you would like to run in the OpenGL thread without using a FutureTask, Runnable or other asynchronous solution.
First of all, does this code (and any of its data) depend on other threads? Does it need to be synchronized with other code/data? If yes, then you should use queueEvent() from a different thread. Since you want to stay within the OpenGL thread completely, I assume that your code to be executed does not have any relationship with other (non-GL) threads.
Moreover, never call FutureTask.get() from the same thread as the one which is supposed to perform the FutureTask code -- who will perform the job if your thread is waiting for itself? And if you want to send code to the GL thread from another thread, don't use FutureTask; just use the simple Runnable for it (as an argument to queueEvent()).
Back to the main question: to run something from the GL thread without queueEvent(), you should decide how exactly you want to perform that job, i.e. when (where) exactly it should be called. Do you want to get it called each time onDrawFrame() is called? Or each time onSurfaceChanged() or onSurfaceCreated() is called?
Since you used queueEvent(), I assume you want your code to run before the next upcoming onDrawFrame() call. In the Android GL thread, internally, the order of calls is as follows:
Android processes all your queued events (I simplified this a bit, but the main point is OK)
If needed, Android calls onSurfaceCreated()
If needed, Android calls onSurfaceChanged()
Android calls onDrawFrame()
So, to put it simple, the code you add with queueEvent() will get executed before the next render cycle (onDrawFrame()). If you want to run this code on the GL thread in onDrawFrame(), you can add it to the beginning of onDrawFrame(), for example:
#Override
public void onDrawFrame(GL10 gl) {
if (mDoJob) {
mDoJob = false;
// perform code
}
...
}
Here, mDoJob is a volatile variable. You can set it to true from another thread. However, please be warned that this assumes you don't need any additional synchronization with the other thread that uses the mDoJob signal, i.e. all the code that will run in the mDoJob condition block will be fine without any further synchronization with anything else.
Basically, what I presented above is just a simplified (non-synchronized) solution to replace queueEvent(), which assumes you don't need synchronization (including up-to-date variables as well) with other threads.
If you don't need any signalling (any dependence with other threads), and the value of mDoJob can be decided inside the OpenGL thread (inside onDrawFrame(), onSurfaceCreated() or onSurfaceChanged()), then mDoJob does not need to be volatile. In such a case, you're staying inside the OpenGL thread, so there is no need for an asynchronous (and thus synchronized) solution.
To sum up, specifically, if you want to decide in onSurfaceCreated() whether a code should run in onDrawFrame(), just use a (non-volatile) boolean variable, which you set in onSurfaceCreated(), and then check it in onDrawFrame() (as in my code example above).

Android Camera won't take picture depending on what is after it in code

I have the following code with which I'm trying to take a picture and save some of the photo's information into a database. The database portion has been thoroughly tested and works fine in all other circumstances. Unfortunately, if I uncomment the commented code below, my code times out. For some reason, if there is code following the this.camera.takePicture() method, takePicture() won't call the overridden onPictureTaken method at all (the first thing it's supposed to do is print out a line of text, but it doesn't even do that). If no code follows it, it works fine.
Before installing the latch, I would get an error because ph.getPhoto() was returning null (ph's .photo member variable wasn't yet set by onPictureTaken(), because it hadn't yet been called). After installing the latch, it will wait until timeout (or forever, if no timeout value is specified).
Can someone please tell me what I'm missing?
public void takePicture(View view) throws Exception {
CountDownLatch latch = new CountDownLatch(1);
System.out.println("Taking Photo!");
PhotoHandler photoHandler = new PhotoHandler(getApplicationContext(),latch);
this.camera.takePicture(null, null, photoHandler);
/* PhotoHandler has an overridden "onPictureTaken()" method which releases the latch as its final
* action; however, its first instruction is to print a confirmation that it has been accessed.
* Unfortunately, for some reason, onPictureTaken() is not called if the following code is
* uncommented; it deadlocks for the five seconds before timing out. However, with out the following,
* the camera.takePicture method invokes onPictureTaken() and it works just fine. */
// latch.await(5,TimeUnit.SECONDS);
// DatabaseHandler db = new DatabaseHandler(this);
// Photo p = photoHandler.getPhoto();
// db.addPhoto(p);
// List<Photo> photos = new ArrayList<Photo>();
// photos.add(p);
// this.addPhotosToMap(photos);
}
onPictureTaken() is (afaik) executed on the main / UI thread. If your takePicture method is also exectued there than it must happen simply because a thread cannot wait for itself.
Besides, you must not block the mainthread or your Activity will ANR.
If you move the commented code (minus that latch) to onPictureTaken() then everything should be fine. Those onSomethingHappened callbacks are made exactly for that task
Put all of your post-processing (i.e., the code you have commented out) into the appropriate callback, not after takePicture. And put slow actions such as file system access into a background thread (e.g., AsyncTask).

How to resolve the ANR error while invoking the Camera?

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();
}
}
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:
Design for Responsiveness
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
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());
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
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.
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.

Categories

Resources