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.
Related
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.
What I want to do:
I am wanting to use a worker-thread to regularly update a textfield in the UI Thread. Let's say, every 2 seconds for 30 seconds. I need the 30 second countdown to happen even if the app is not on the foreground. For now, I am evaluating the merits of two different approaches (both using worker-threads) in implementing this. I won't post the full code here to simplify things and also because I am not asking to find any problem in my code. Both solutions work fine.
Solution #1 - use Thread.sleep() inside a for loop
for (int i = 30; i > 0; i-=2) {
Message msg = mHandler.obtainMessage(MSG_ID, i, 0);
msg.sendToTarget();
try {
Thread.sleep(2000);
} catch(Throwable t) {
// catch error
}
}
Solution #2 - use CountDownTimer
Looper.prepare()
new CountDownTimer(30000, 2000) {
public void onTick(long millUntilFinish) {
int seconds = (int)(millUntilFinish);
Message msg = mHandler.obtainMessage(MSG_ID, seconds, 0);
msg.sendToTarget();
}
public void onFinish() {
// left blank for now
}
}.start();
Looper.loop();
My Question
While both work, I am wanting to know if there is a "better" or a "preferred" way to do it for whatever reason. I am thinking there may be areas particularly in battery life but also in performance, accuracy or code design where one solution is better than the other.
What I have done so far to answer this question
My own evaluation so far from reading this SO question and CountDownTimer's documentation are that since both are executed on the worker-thread, both have no ANR possibility. Both solutions will also gaurantee that one "update" will happen only after the previous update has finished. Unfortunately, this is all I have and hoping if anyone can help or guide me to an insightful and/or similar SO question I may have overlooked or was unsuccessful in finding.
I write this question a bit cautiously as I don't have a problematic code which requires debugging but I think this falls within SO's category of a "specific programming problem", which hasn't been answered, and not included in the list of off-topic answers.
1.Calling Thread.sleep pauses the thread execution for a while where as countdown timer actually uses callbacks to notify timer expiry events and is asynchronous in nature.
2.If the thread execution pauses, you will not be able to use that specific thread for any other operation until the sleep timeout hence it is not recommended to use Thread.sleep approach. Obviously there is a load on cpu if it has to resume the thread execution and pause it.Where as in the case of countdown timer the thread continue to be in execution/idle state and as when events occur it fires to the respective listeners.
call Thread.sleep() method is not good idea beacuse ii sleep the UI Thread and disadvantage of CountDownTimer is, It Will stop when ur screen is off hence instead of this two try Handler for that like this
Handler handler;
Runnable runnable;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run()
{
if (dataReceived)
{
cancelHandler();
}
}
};
handler.postDelayed(runnable, 100);
}
public void cancelHandler()
{
handler.removeCallbacks(runnable);
}
an Android 4+ app should perform a long running operation. This could be copying a million files from A to B for example. To not block the UI this operation runs in the background using an AsyncTask.
Assume that the operation needs some user feedback in the middle of the process to continue its work, e.g. "File XY already exists. Override, Irgnore or Rename?"
What is the best way to get this feedback from the user? Since the operation is running in a background thread one could not just present an AlertDialog (or something similar) since UI interaction is only possible in the main thread...
So for I came across these solution:
Ask for feeback before background threads starts, e.g. ask how to handle conflicts before starting to copy/move the files in the
background.
Do not handle conflicts but note them to ask the user
how to handle them after the operation is complete in a new
operation.
End the background operation on the first conflict, ask the user for feedback and continue a new background operation
I do not like any of these solutions. In the first case the user is asked for feedback even if there will be no conflict at all. The second solutions is not possible if the steps have to be processed in a specific order. The third solution would result in code that is very difficult to read/understand/maintain.
A good solution would be:
Stop the background thread
Marshal to the UI thread and get feedback from the user
Resume background thread and use feedback to continue the operation
Using GCD in Objectiv-C/iOS or async/await in C# this is not a big problem. But how can this be done in Android using AsyncTask?
Meanwhile I thought, that I found an answer here: Simply run myActivity.runOnUiThread(...) within doInBackground(...) and wait for it. Sounds good, but it does not work. The AsyncTask/background thread does NOT wait for the Runnable to finish:
private void copyFiles() {
CopyTask copyTask = new CopyTask (this);
copyTask.execute();
}
private class CopyTask extends CustomAsyncTask<Void, Void, Void> {
private doCopy;
#Override
protected Boolean doInBackground(Void... params) {
// Custom code, e.g. copy files from A to B and check for conflict
for (File file : allFiles) {
doCopy = true;
if (isConflict(file)) {
// Stop current thread and ask for user feedback on UI Thread
Runnable uiRunnable = new Runnable() {
public void run() {
// Pos 1. --> Execute custom code, e.g. use AlertDialog to ask user if file should be replaced...
doCopy = false;
synchronized (this) {
this.notify();
}
}
});
synchronized(uiRunnable) {
// Execute code on UI thread
activity.runOnUiThread(uiRunnable);
// Wait until runnable finished
try {
uiRunnable.wait();
}
catch (InterruptedException e ) {
e.printStackTrace();
}
}
}
// Pos 2. --> Continue work
if (doCopy)
copyFromAToB(File);
}
return null;
}
}
I would expect, that when a conflict is detected the Runnable is executed and and Pos 1 (code inside Runnable to resolve conflict) is executed BEVOR Pos 2 is reached. This is not the case. The Runnable is executed correctly but the AsyncTask does not wait for it to finish. The execution of doInBackground is continued without any interruption. It seems that doInBackground and the Runnable are executed in parallel (not suprising since they are executed on different threads) but why does doInBackground not wait?
The UI I am creating includes a button, which once pressed, is supposed to find and display values repetitively until the user presses the button again.
This is my button's initialization with the listener:
pollOn = false;
pollButton = (Button) findViewById( R.id.pollButton );
pollButton.setOnClickListener( new OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
Log.i( "POLL BUTTON", "onClick" );
if( !pollOn ) {
Log.i( "POLL BUTTON", "!pollOn" );
pollOn = true;
methodToReadAndDisplayData();
} else {
Log.i( "POLL BUTTON", "else pollOn" );
pollOn = false;
}
}
});
It is not shown here to make things easier to read, but the way I currently have it working is to call the methodToReadAndDisplayData() 5 times in a for loop and then stop.
So when I press the pollButton initially, the UI freezes and Log.i("POLL BUTTON", "onClick") is displayed at the top of LogCat. I then press the pollButton while it appears to be frozen, and after all of the work is done and the UI unfreezes, Log.i("POLL BUTTON", "onClick") is shown at the very end of my LogCat. The way I am interpretting this is that the button click is entered into a queue, and the onClick method is called after all 5 iterations of the for loop have been completed.
Another large part of this problem is that the work being done is mainly in a native library, and is called using the NDK. I am unsure if this has anything to do with the UI freezing, but it definitely increases the processing time needed.
If anything is unclear or confusing please let me know and I will try to clarify things.
Any information on this situation would be greatly appreciated.
Doing some stuff while keeping the UI responsive can achieved by many methods, two of them are very common. Async Task and threads.
AsyncTask:
It's a class which have a few methods which help you to do time consuming work while updating the UI at the same time. For Example: If you want to search a specific word in a big document, do the reading and searching stuff in doInBackground() (a method of AsyncTask class) and you can display a progress bar and notify the user with your progress with onProgressUpdate(). This gives your app more professional feel and at the same time helps you executing time consuming task in background.
Threads:
They are simple runnable threads. You can execute non UI stuff with these threads but you can't perform UI tasks in them (as UI is not thread safe). For dealing with UI in these threads, you will have to use Handlers, which is quite cumbersome for beginners to get a grip and understanding of them.
So depending on your needs and app you can choose the one best suits you.
Because you're running on the main thread the system UI freezes, you'd be better off running in a new thread which would leave your UI running as normal. Below is an example of how to run your method in a new thread.
new Thread(new Runnable() {
#Override
public void run() {
methodToReadAndDisplayData();
}
}).start();
Note that if your method interacts with the UI in any way, you need to do it via the following:
When you want to update your UI:
Handler threadHandler = new Handler();
threadHandler.post(updateRunnable);
Update your UI here:
Runnable updateRunnable = new Runnable() {
public void run() {
example.setText(newValue);
}
};
Try that and see if there's any improvement. I've not worked with the NDK, just the standard SDK so there may be difference I'm unaware of.
Do it on another thread. Use an AsyncTask to call methodToReadAndDisplayData.
I'm trying to get my user interface to react to events (like button presses, thread completions, etc.) in real time in Android (obviously).
I have a button layout, and one of the buttons is used to copy an unknown number of files from a remote computer using FTP. The FTP part of all this is working very well, but I just cannot find a way to let the user know the state of things:
The states, as I see them are:
1) Selected "Download Files" from "normal" menu.
2) Pressed Confirm (the download process may be quite lengthy and perhaps I don't want to select it by mistake -- however now it's a separate thread so may need to re-think that.
3) Downloading
4) Download complete, restore normal menu
One of the things I hoped would work would be to run the FTP code in a separate thread, and by using the thread.isAlive() construction, wait for the thread to complete and change the display accordingly.
The only thing I haven't been able to do is display that files are downloading. Regardless of what I try, the display jumps from the "Confirm Download" view to the "Normal Menu" view. (Please note, these are not Views as Android defines them in any way.)
Code follows:
Btn.setOnClickListener (new View.OnClickListener()
{
#Override
public void onClick (View v)
{
hideTempWidgets();
Btn01.setVisibility (View.GONE);
Btn02.setVisibility (View.GONE);
Btn03.setVisibility (View.GONE);
verfBtn.setVisibility (View.VISIBLE);
verfBtn.setText ("Press to Verify");
verfBtn.setOnClickListener (null);
verfBtn.setOnClickListener (new View.OnClickListener()
{
#Override
public void onClick (View v)
{
runOnUiThread (new Runnable()
{
public void run()
{
verfBtn.setText ("Downloading...");
}
});
Thread temp = new Thread (new Runnable()
{
public void run()
{
try
{
FileTransfer.getFiles (getAddr().trim());
}
catch (SQLException e)
{ }
}
}, "ftp");
temp.start();
while (temp.isAlive());
verfBtn.setVisibility (View.GONE);
Btn01.setVisibility (View.VISIBLE);
Btn02.setVisibility (View.VISIBLE);
Btn03.setVisibility (View.VISIBLE);
alert (true, VIBE_BLIP);
}
});
}
});
Has anybody faced this and come up with a decent solution??
What's not happening is the setText to "Downloading...", or at least, if it does, not when I want it to and too fast to see... Finally, what's especially frustrating is that that command does work properly when I remove the code to run the FTP thread.
Thanks,
R.
This task seems to be perfect for Async Task. Basically Async Task is a Thread with a built in, thread safe component to allow you to publish updates to the UI and notify when the task is complete.
A popular idea is to show a spinner or progress bar, until the AsyncTask is complete, then dismiss it.
For more information about Async Task see: http://developer.android.com/reference/android/os/AsyncTask.html
I think your mistake is here:
temp.start();
while (temp.isAlive());
The code inside onClick() is already running on graphical Thread, so there is no need for a runOnUIThread() method and you should not block it with the while() statement, which in fact is blocking the UI thread till the Thread completes.
My advice: you can start an AsyncTask instead and update the UI accordingly.
Since it is a very long file transfer, I'd suggest you consider a service to do the work. If you use thread, user will be bound to keep your application on top of others. Otherwise your thread can be just killed. Worst of all, there is not much you can do to prevent user from going to home screen or other application (some tricks are possible but user will be pissed).
If you use service, you can always use notification to show progress and go back to your application.