我在主菜单中有两个按钮。我按下第一个按钮时调用相机。在这里,我没有遇到任何问题。相机正常工作。拍完照片后,我回到主菜单,再次按下第一个按钮。我在这里得到了这个问题。相机正确调用。但是我在拍照的时候得到了ANR error (Reason: keyDispatchingTimedOut)
。如何解决这个问题?
修改::
我正在使用以下代码,
按钮监听器,
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();
}
}
答案 0 :(得分:9)
搜索错误时,您可能已经通过了this link。
虽然我从未遇到过这样的问题,但在互联网上阅读后,这就是我的理解:
描述:
进程时出现ANR或应用程序无响应错误 在主线程上花费太长时间(类似于> 5秒)。 Android的 通过设计杀死该过程和任何相关的设备以备用该设备 资源。
解决方案是在另一个线程上运行资源昂贵的任务,并且 然后发布,或相应地更新主线程。
请参阅: Android ANR keyDispatchingTimedOut
因此,在您的情况下,您可能与长时间运行并且Android杀死它们的冲突两个不同的线程。下一个相关代码也会受到影响。
因此,请更好地对代码进行分类,在不同的Thread,Handler
中编写每个新任务,如果您正在执行UI任务,请使用runOnUIThread
。 Async Task
也非常方便。
另一件事是尝试删除其他代码的依赖性。写一些默认值,如果没有正确完成,你可以将用户送回第一个任务。
我认为错误来自您的编码样式,而不是因为您的代码中存在任何特定错误。
您需要改进您的特定代码才能有效执行,并且请参阅以下两个链接:
修改强>
我在某处读到并发现有效,
如何调查ANR?
首先,查看代码并查找可用的点和长时间运行的操作。示例可以包括在事件线程内使用套接字,锁,线程休眠和其他阻塞操作。你应该确保这些都发生在不同的线程中。如果没有任何问题,请使用DDMS并启用线程视图。这会显示应用程序中的所有线程与您拥有的跟踪类似。重现ANR,同时刷新主线程。这应该向你展示ANR时正在发生的事情
如果由于线程导致ANR?
你可以为此用户服务, 所以你的应用程序可以在service.onStart()中执行耗时的任务, 在用于启动服务的意图中传递数据(例如)。
但是,Services在主应用程序线程上执行。如果单独的 需要线程,它可以由onStart()内的服务创建。
已有一个内置类可以执行此操作:IntentService
还找到了一个有用的库应用程序 SalomonBrys/ANR-WatchDog
答案 1 :(得分:6)
Android applications normally run entirely on a single (i.e. main) thread
。这意味着您的应用程序在完成long time
的主线程中执行的任何操作都可以触发ANR dialog
因为您的应用程序没有给自己处理input event
或{{{ {1}}。因此,在这种情况下,您可以使用StrictMode
来帮助查找可能长时间运行的操作,例如您可能意外执行主线程的网络或数据库操作。如果您发现您认为有问题的违规行为,可以使用各种工具来解决这些问题:ntent broadcast
,threads
,Handler
,AsyncTask
等。另外请记住它来自IntentService
要在API Level 9
,Application
或其他应用程序组件Activity
方法的早期启用的示例代码:
onCreate()
答案 2 :(得分:5)
我想你已经知道了,
单线程模型会在不考虑其影响的Android应用程序中产生较差的性能。由于所有操作都发生在执行长操作的单个线程上,例如网络访问或数据库查询,因此该线程将阻止整个用户界面。 无法发送任何事件,包括绘制事件,而长时间的操作正在进行中。 * 从用户的角度来看,应用程序显示为挂起 * 。 更糟糕的是,如果UI线程被阻止超过几秒钟(当前大约5秒),则会向用户显示臭名昭着的“应用程序无响应”(ANR)对话框。
当在“主”线程中发生一些长操作时,会发生ANR。这是事件循环线程,如果它很忙,Android无法处理应用程序中的任何进一步的GUI事件,从而抛出一个ANR对话框。
什么触发ANR?
在Android中,应用程序响应性由活动管理器和Window Manager系统服务监视。当Android检测到以下某种情况时,它将显示特定应用程序的ANR对话框:
* No response to an input event (e.g. key press, screen touch) within 5 seconds
* A BroadcastReceiver hasn't finished executing within 10 seconds
如何解决,请查看Designing for Responsiveness
修改强>
所以,尝试使用其他单独的工作线程,处理程序,AsyncTask或UIThread为您的相机(媒体记录器)而不是活动的主线程。
1)。请"adb shell cat /data/anr/traces.txt"
查看您的应用正忙着做什么
在那时候。这是您需要采取的第一步:理解
您的应用正在做什么导致ANR。
当ANR发生时,所有进程的堆栈都写入此文件, 该流程首先被指控为ANR。这一切都是 转储文件,以便您可以查看它。所以你只想看看它 在ANR之后的时间,在另一个ANR发生之前。
2)。如果没有任何问题,请使用DDMS并启用线程视图。这显示了所有 应用程序中的线程与您拥有的跟踪类似。重现ANR,和 同时刷新主线程。那应该会告诉你到底发生了什么 在ANR的时候。
更多信息请点击此http://android-developers.blogspot.com/2009/05/painless-threading.html
答案 3 :(得分:1)
您可以在Oncreate()
或Onresume()
中的主线程中初始化并启动媒体录制器,而不是在主线程中启动相机使用separeate Handler
来启动相机拍照,它会像主UI线程的孩子一样。
使用Handler
可以缩短时间并且不会发生ANR。
答案 4 :(得分:1)