可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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:
- 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
回答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.