lockCanvas()の戻り値がnullになってしまう

3,031 views
Skip to first unread message

ajishio

unread,
Apr 2, 2012, 4:02:21 PM4/2/12
to 日本Androidの会
はじめまして、ajishioと申します。
つい先ほど入会させていただきました。
どうぞよろしくお願いいたします。

Androidアプリを作りたくて、Javaを始めて1週間の初心者です。
経験としては、アセンブラ、C、VBを経験しており、一応、コンピューターの仕組みもある程度理解していると思います。

参考本やネット検索の模倣+これまでの経験で、なんとなく動くアプリが出来てきて、eclipseの使い方も少しだけ身についてきたところです。

これまでに行き当たったいくつかの壁はなんとか乗り越えられたのですが、主題の件で行き詰っております。

Cameraクラスを使って、SurfaceViewにカメラのプレビュー画面を表示し、タップされたらグラフィック描画をしようとしております。
以下に、ソースコードの抜粋を記載します。

~ 前半略 ~

public void initSurface(){
holder = this.getHolder();
holder.addCallback(this);
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
try {
camera.setPreviewDisplay(holder);
} catch (IOException exception) {
exception.printStackTrace();
camera.release();
camera = null;
}
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
camera.stopPreview();
camera.setDisplayOrientation(90);
Camera.Parameters parameters = camera.getParameters();
List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
Camera.Size size = sizes.get(0);
parameters.setPreviewSize(size.width, size.height);
camera.setParameters(parameters);
camera.startPreview();
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera = null;
}

@Override
public boolean onTouchEvent(MotionEvent event) {

if (event.getAction() == MotionEvent.ACTION_DOWN) {
camera.takePicture(null,null,new Camera.PictureCallback(){
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Bitmap img = BitmapFactory.decodeByteArray(data, 0, data.length,
null);
int width = img.getWidth();
int height = img.getHeight();
int pixels[] = new int[width * height];

img.getPixels(pixels, 0, width, 0, 0, width, height);

~ 関連する前処理はここまで ~

この後、グラフィックを使いたくて、

Canvas canvas = holder.lockCanvas();
canvas.drawColor(Color.BLACK);

と記述しているのですが、いくらループで待っていてもcanvasがnull以外になりません。

別に作ったアプリでは、問題なく描画できております。
違いはカメラのプレビュー画面の表示があるか/ないかだけなので、これが関連しているとは思うのですが・・・

先輩方のお知恵を拝借いたしたく、投稿させていただきました。
よろしくお願いいたします。

MORIHIRO

unread,
Apr 3, 2012, 9:24:18 AM4/3/12
to android-g...@googlegroups.com
setPreviewDisplay()で設定したSurfaceViewはCameraのPreview専用になりますので、
Overlayでグラフィックを描画したいのであれば、透明なViewを上に重ねる必要があります。

2012年4月3日火曜日5時02分21秒 UTC+9 ajishio:

ajishio

unread,
Apr 3, 2012, 5:20:58 PM4/3/12
to 日本Androidの会
MORIHIRO様、ご助言、大変ありがとうございました!
プレビュー専用のSurfaceViewになっていたのですね。。orz

ちなみに、タップした後、もうプレビュー画面は不要なのですが、プレビュー用としては
リリースして、そのままグラフィック描画に流用することはできるのでしょうか?
(逆に、プレビュー画面は消去したいのです)

素人的な質問で申し訳ありません!
(自分でも並行してリファレンスとか調べてみます)

ajishio

unread,
Apr 3, 2012, 7:30:03 PM4/3/12
to 日本Androidの会
中間報告@ajishioです。
あの後、リファレンスを見てみましたところ、setPreviewDisplay(null)でpreview surfaceを
取り除けるとあったので、

camera.stopPreview();
try {
       camera.setPreviewDisplay(null);
} catch (IOException exception) {
       exception.printStackTrace();
camera.release();
camera = null;
}
if(camera != null) {
camera.release();
camera = null;
Canvas canvas = holder.lockCanvas();
canvas.drawColor(Color.BLACK);
paint.setColor(Color.RED);
canvas.drawRect(100, 100, 200, 200, paint);
}

というコードを試してみたのですが、結果は同じでした。
(ちなみにストップしたプレビュー画面は消えません)

やはりもう1枚、SurfaceViewを作り、背景色を付けて重ね描きするしか
ないのでしょうか。。

MORIHIRO

unread,
Apr 3, 2012, 7:37:52 PM4/3/12
to android-g...@googlegroups.com
未確認ですが、camera.setPreviewDisplay(null) を実行すればリリースできると思います。

2012年4月4日水曜日6時20分58秒 UTC+9 ajishio:

たろサ

unread,
Apr 3, 2012, 11:29:58 PM4/3/12
to android-g...@googlegroups.com
 たろサです。

Canvas canvas = holder.lockCanvas();
canvas.drawColor(Color.BLACK);
paint.setColor(Color.RED);
canvas.drawRect(100, 100, 200, 200, paint);

holder.unlockCanvasAndPost(canvas);
 ↑
 ロックを解除し忘れているとか、そんな話しではないのかな?

--
山本三七男 (Minao Yamamoto) ---------------- ハンドル:たろサ -----
E-Mail: taro...@gmail.com

ajishio

unread,
Apr 4, 2012, 9:22:37 AM4/4/12
to 日本Androidの会
ajishioです。

新たなご助言、感謝至極です!!

確かに今朝ほどアップしたコードはロック解除が抜けていたのですが、
lock.Canvas()がnullを返すという現象は変わりなく、exceptionが発生
してしまいます。

気になるのは、リリースするところで、すごく時間がかかるんですよね。
10秒くらいですかね。。
この辺りで、なにかやらかしているうような気がします。
> E-Mail: taros...@gmail.com

MORIHIRO

unread,
Apr 4, 2012, 11:08:57 AM4/4/12
to android-g...@googlegroups.com
端末(Android Version?)により違いがあるようです。
 NexusOne → 失敗
 GalaxyNexus → 成功

何となく面倒な話になりそうですので、技術調査ではなくアプリ開発を
メインにしているのであれば、普通に別のSurfaceViewを使う方をお勧めします。
(カメラのOverlayサンプルはネット上にたくさんありますので)

以上、首を突っ込んでみたものの、力不足でスイマセン。。。

2012年4月4日水曜日22時22分37秒 UTC+9 ajishio:

ajishio

unread,
Apr 4, 2012, 4:55:41 PM4/4/12
to 日本Androidの会
MORIHIRO様

わざわざ調べていただき、ありがとうございました。

実は、私の端末はGalaxyNexusでして、私も面倒な話になりそうな気がして
きました。(機種依存やバージョン依存の話を詰めても仕方ないですもんね)

ご助言の通り、別のSurfaceViewを作ってみます。
どうもありがとうございました。

ajishio

unread,
Apr 10, 2012, 7:27:34 AM4/10/12
to 日本Androidの会
ajishioです。

少し判ったことがあります。
よくよく調べ直してみたところ、今までに訪れていたサイトに解があったのですが、
撮影後の処理にある程度、時間がかかり、それを待たないとexceptioが発生するようです。
(当然といえば当然ですが・・・)

色々と行き詰って、デバッガで追っていたら、なぜかもうひとつのSurfaceViewを引き継ぐことが
できたので、そこに気づきました。

ですので、waitを入れることで、一旦、解決したかに見えたのですが、最終的には原因不明の
exceptionが発生し、後続処理ができておりません。

他のサイト情報と同じコーディングをしているのですが、うまくいかないのでOSのバージョン等に
よるものかもしれません。
(私の技術不足が最大の原因だと思いますが。。まだデバッガもうまく使えないですし)

とにかく、ちょっとだけ糸口が掴めましたので、ご報告いたしました。
Reply all
Reply to author
Forward
0 new messages