3

メインメニューに2つのボタンがあります。1番目のボタンを押すとカメラを呼び出します。ここでは問題は発生しませんでした。カメラが正常に動作しています。写真を撮った後、メインメニューに戻り、もう一度1番目のボタンを押します。ここで問題が発生しました。カメラが適切に呼び出されます。しかし、私は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

エラーの検索中にこのリンクをたどった可能性があります。

私はそのような問題を抱えたことはありませんでしたが、インターネットで読んだ後、これは私が理解していることです:

説明 :

ANRまたはApplicationNotRespondingエラーは、メインスレッドのプロセスに時間がかかりすぎる(5秒を超えるなど)場合に発生します。Androidは、デバイスのリソースを節約するために、そのプロセスと関連するすべてのプロセスを強制終了します。

解決策は、別のスレッドでリソースを消費するタスクを実行し、それに応じてメインスレッドを投稿または更新することです。

これを参照してください:Android ANR keyDispatchingTimedOut

したがって、あなたの場合、長時間実行し続けるスレッドとは異なる2つのスレッドが競合し、Androidがそれらを強制終了する可能性があります。次の関連コードも影響を受けます。

したがって、コードをより適切に分類し、新しいタスクをそれぞれ異なる方法で記述Thread,Handlerし、UIタスクを実行している場合は、を使用しますrunOnUIThreadAsync Taskとても便利です。

もう1つのことは、他のコードへの依存関係を削除しようとすることです。いくつかのデフォルト値を記述し、それが適切に行われなかった場合、そこからユーザーを最初のタスクに戻すことができます。

エラーはコーディングスタイルによるものであり、コードの特定のエラーによるものではないと思います。

効率的に実行するには、その特定のコードを改善する必要があります。そのためには、次の2つのリンクを参照してください。

  1. 応答性のための設計
  2. 痛みのない糸脱毛

編集:

これをどこかで読んで効果的だと思ったのは、

ANRを調査する方法は?

まず、コードを調べて、脆弱な場所と長時間実行される操作を探します。例としては、イベントスレッド内からのソケット、ロック、スレッドスリープ、およびその他のブロック操作の使用が含まれる場合があります。これらがすべて別々のスレッドで発生することを確認する必要があります。問題がない場合は、DDMSを使用してスレッドビューを有効にします。これにより、アプリケーション内のすべてのスレッドが、トレースと同様に表示されます。ANRを再現し、同時にメインスレッドを更新します。これにより、ANRの時点で何が起こっているかが正確に示されます。

また、スレッドが原因でANRが発生した場合はどうなりますか?

そのためにServiceを使用できるため、アプリはservice.onStart()内で時間のかかるタスクを実行し、サービスの開始に使用されるインテントでデータ(たとえば)を渡すことができます。

ただし、サービスはメインアプリケーションスレッドで実行されます。別のスレッドが必要な場合は、onStart()内のサービスで作成できます。

これを行う組み込みクラスがすでにあります:IntentService

また、1つの役立つライブラリアプリケーション SalomonBrys/ANR-WatchDogが見つかりました

于 2011-12-19T10:32:45.010 に答える
6

Android applications normally run entirely on a single (i.e. main) thread。これは、アプリケーションがメインスレッドで実行していることをすべて実行すると、アプリケーションがまたはIを処理する機会を与えていないため、long timeトリガーされる可能性があることを意味します。その場合、このような長時間実行される可能性のある操作を見つけるのに役立ちます。誤ってメインスレッドを実行している可能性のあるネットワークまたはデータベース操作として。問題があると思われる違反を見つけた場合は、それらを解決するのに役立つさまざまなツールがあります:、、、、など。ANR dialoginput eventntent broadcastStrictModethreadsHandlerAsyncTaskIntentServiceAPI 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では、アプリケーションの応答性は、アクティビティマネージャーとウィンドウマネージャーのシステムサービスによって監視されます。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

メインスレッド自体でメディアレコーダーを初期化して起動する場合があります。メインスレッドでカメラを起動する代わりに、別の方法でOncreate()写真を撮るためのカメラを起動します。メインUIスレッドの子のように機能します。Onresume()Handler

あなたを使用Handlerすると時間が短縮され、ANRは発生しません。

于 2011-12-19T10:06:12.650 に答える
1

カメラリソースが解放されていないため、ANRが発生しているようです。

コードは少し厄介に見えます。カメラプレビューのAPIの例を見ることができます。

実装onPauseonResume、それが確実に機能するためには、実装する必要があります。

于 2011-12-24T14:54:56.707 に答える