3

我在主菜单中有两个按钮。当我按下第一个按钮时,我调用了相机。在这里我没有遇到任何问题。相机工作正常。拍照后,我回到主菜单,再次按下第一个按钮。在这里我得到了问题。相机调用正确。但是我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();
    }
}
4

5 回答 5

9

您可能在搜索错误时浏览了此链接。

虽然我从来没有遇到过这样的问题,但在网上阅读后,我的理解是这样的:

描述 :

当主线程上的进程花费太长时间(例如 > 5 秒)时,会发生 ANR 或 Application Not Responding 错误。Android 会通过设计终止该进程和任何相关进程,以节省设备资源。

解决方案是在另一个线程上运行资源昂贵的任务,然后相应地发布或更新主线程。

看到这个:Android ANR keyDispatchingTimedOut

因此,在您的情况下,您可能会与持续运行很长时间的两个不同线程发生冲突,而 Android 会杀死它们。下一个相关代码也会受到影响。

所以最好对你的代码进行分类,用不同的方式编写每个新任务,Thread,Handler如果你正在执行 UI 任务,请使用runOnUIThread. Async Task也很Handy。

另一件事是尝试消除代码对其他代码的依赖。写一些默认值,如果没有正确完成,您可以将用户发送回第一个任务。

我相信错误来自您的编码风格,而不是因为您的代码中有任何特定错误。

您需要改进您的特定代码以高效执行,为此请参阅以下 2 个链接:

  1. 响应式设计
  2. 无痛穿线

编辑:

这是我在某处读到的,发现有效的是,

如何调查 ANR?

首先,检查您的代码并寻找易受攻击的地方和长时间运行的操作。示例可能包括在事件线程内使用套接字、锁、线程休眠和其他阻塞操作。您应该确保这些都发生在单独的线程中。如果没有问题,请使用 DDMS 并启用线程视图。这将显示应用程序中的所有线程,类似于您拥有的跟踪。重现ANR,同时刷新主线程。这应该准确地向您展示 ANR 时发生的事情

此外,如果 ANR 是由于 Threads 引起的?

您可以为此使用服务,因此您的应用程序可以在 service.onStart() 中执行耗时的任务,在用于启动服务的意图中传递数据(例如)。

但是,服务在主应用程序线程上执行。如果需要单独的线程,可以由 onStart() 中的服务创建。

已经有一个内置类可以做到这一点:IntentService

还发现了一个有用的图书馆应用 SalomonBrys/ANR-WatchDog

于 2011-12-19T10:32:45.010 回答
6

Android applications normally run entirely on a single (i.e. main) thread. 这意味着您的应用程序在主线程中执行的任何需要 along time完成的操作都可以触发,ANR dialog因为您的应用程序没有给自己处理input eventor I的机会ntent broadcast。因此,在这种情况下,您可以使用它StrictMode来帮助查找潜在的长时间运行的操作,例如作为网络或数据库操作,您可能会不小心执行主线程。如果您发现您认为有问题的违规行为,有多种工具可以帮助解决这些问题:threadsHandlerAsyncTaskIntentService等。另外请记住,它来自API Level 9

Application在您的Activity、 或其他应用程序组件的onCreate()方法中从早期启用的示例代码:

 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());
于 2011-12-19T10:25:32.537 回答
5

我想你已经知道了,

单线程模型可能会在不考虑影响的 Android 应用程序中产生较差的性能。由于所有事情都发生在执行长操作(如网络访问或数据库查询)的单个线程上,因此在该线程上将阻塞整个用户界面。长时间操作正在进行时,不能分派任何事件,包括绘图事件。*从用户的角度来看,应用程序似乎挂起*更糟糕的是,如果 UI 线程被阻塞超过几秒(目前大约 5 秒),用户会看到臭名昭著的“应用程序无响应”(ANR)对话框。

当“主”线程中发生一些长时间的操作时,就会发生 ANR。这是事件循环线程,如果它很忙,Android 将无法在应用程序中处理任何进一步的 GUI 事件,从而引发 ANR 对话框。

什么触发 ANR?

在 Android 中,应用程序的响应性由 Activity Manager 和 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

如何解决它,请查看响应性设计

编辑:

因此,请尝试使用其他单独的工作线程、处理程序、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

于 2011-12-17T08:11:40.470 回答
1

似乎相机资源没有被释放,从而导致ANR

代码看起来有点乱。您可以查看相机预览的 api 示例:

您将必须实施onPauseonResume使其可靠地工作。

于 2011-12-24T14:54:56.707 回答
1

可能是您在主线程本身中初始化并启动媒体记录器 inOncreate()或 in Onresume(),而不是在主线程中启动相机使用单独Handler启动相机拍照,它将像主 UI 线程的子线程一样。

使用Handler您减少时间并且不会发生 ANR。

于 2011-12-19T10:06:12.650 回答