Observer コールバックで Draw を実行しようとしていますが、キャンバスをロックしようとすると常に null が返されます。SurfaceHolder は問題ないようです。SurfaceHolder コールバックを追加すると、ゲームの早い段階で呼び出されます。
これが私のオブザーバーの更新方法です:
// implements Observer
public void update(Observable observable, Object data) {
Canvas c = null;
Log.i(TAG, "Surface Observer of CbSurfaceState thread: "
+ Thread.currentThread().getName());
try {
synchronized(mCbHolder) {
c = mCbHolder.lockCanvas(null);
if(c == null) {
Log.i(TAG, "lockCanvas returned null");
} else {
doDraw(c);
}
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
mCbHolder.unlockCanvasAndPost(c);
}
}
}
初期化で最初に使用する場所は次のとおりです。
public void initCbSurfaceView(Context context) {
mContext = context;
// register our interest in hearing about changes to our surface
mCbHolder = getHolder();
Log.i(TAG,"got holder");
mCbHolder.addCallback(cbSurfaceHolderCallback);
Log.i(TAG,"added callback");
// initially in preview mode
mCbHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// previewHolder.(SurfaceHolder); Don't know how to replace, but it
// won't work without the above.
...
mCbSurfaceState.addObserver(this);
Log.i(TAG, "Creation of CbSurfaceState thread: "
+ Thread.currentThread().getName());
}
サーフェスが作成されたときに再度設定することさえあります(念のために最近追加しました)
SurfaceHolder.Callback cbSurfaceHolderCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
Log.i(TAG, "In surfaceCreated callback");
mCbHolder = holder;
}
...
};
ここにいくつかのログがあります。最初は非同期スレッドから開始されていたので、スレッドを印刷しましたが、それを回避することができました。
02-24 20:31:10.380: I/CbSurfaceView(4013): In surfaceCreated callback
02-24 20:31:10.380: I/CbSurfaceView(4013): SurfaceChanged 854X404
02-24 20:31:10.380: I/CbSurfaceView(4013): initPreview width 854 height 404
...
02-24 20:31:25.974: I/CbTouchListener(4013): onTouch Down x 665.7714 y 194.92023
02-24 20:31:25.974: I/CbSurfaceView(4013): Surface Observer of CbSurfaceState thread: main
02-24 20:31:25.981: I/CbSurfaceView(4013): lockCanvas returned null
02-24 20:31:26.005: I/CbSurfaceView(4013): Surface Observer of CbSurfaceState thread: main
02-24 20:31:26.075: I/CbSurfaceView(4013): lockCanvas returned null
私は一体何を間違っているのでしょうか?私のdoDrawは、ビットマップを描画しようとするまで機能していました。次に、lockCanvas から null をチェックすることを考えました。
ここで答えを見つけましたAndroidのカメラで使用されるSurfaceViewにオーバーレイを描画する方法は? プレビュー上では描画できないようです。PUSH_BUFFER タイプのサーフェスに関する例外が発生していたので、文句を言わないように NORMAL にリセットしました。プレビューのサーフェスをロックできず、NORMAL でない場合は例外がスローされました。どうやら、サーフェス タイプを動的に変更することはできません。それがおそらく廃止された理由ですが、カメラのプレビューは PUSH_BUFFER に設定しないと機能しません。撮影した写真を描画およびレンダリングするために、別の非サーフェス ビューを上に追加します。
ご覧いただきありがとうございます。これが誰かの役に立てば幸いです。