Xamarin.AndroidでCamera2APIを使用した際、写真撮影2回目にImage is already closedが発生する
- 評価
- クリップ 0
- VIEW 203
前提・実現したいこと
Xamarin初心者です。よろしくお願いいたします。
Xamarin.Androidを用いて、写真撮影を行うアプリケーションを作成しています。
3画面構成で、
メイン画面→写真撮影画面→写真撮影結果表示画面→メイン画面…
に遷移します。
写真撮影結果表示画面からメイン画面に遷移する際は
写真撮影結果表示画面・写真撮影画面には戻れないよう、
intent.AddFlags(ActivityFlags.ClearTop);
intent.AddFlags(ActivityFlags.SingleTop);
を行い遷移します。
Camera2Basicを参考に、Camera2BasicFragment.csをActivityに移植し、
インカメラを用いて写真撮影をする機能を実装しましたが、
ImageAvailableListener.csの
ByteBuffer buffer = mImage.GetPlanes()[0].Buffer;
にブレークポイントを設定すると、1回目のブレークヒットでは例外が発生せず、
2回目にブレークヒットした際に以下のエラーメッセージが発生しました。
また、上記箇所にブレークポイントを設定せずに実機に配置すると、
問題なく、2回目以降の写真の撮影が行えます。
発生している問題・エラーメッセージ
Java.Lang.IllegalStateException
Message=Image is already closed
例外が発生する理由、例外を解消する方法がわかりません。
Camera2Basicでは同様の挙動にならないため、自身の実装箇所によるものです。
しかし、原因がわからないため、上記例外に対して対応ができていません。
該当のソースコード
using Android.Media;
using Java.IO;
using Java.Lang;
using Java.Nio;
using System;
namespace WorkTimeInputTabletApp.Listeners
{
public class ImageAvailableListener : Java.Lang.Object, ImageReader.IOnImageAvailableListener
{
private readonly EmployeeNumInput owner;
public ImageAvailableListener(EmployeeNumInput owner)
{
if (owner == null)
throw new System.ArgumentNullException("owner");
this.owner = owner;
}
//public File File { get; private set; }
//public Camera2BasicFragment Owner { get; private set; }
public void OnImageAvailable(ImageReader reader)
{
owner.mBackgroundHandler.Post(new ImageSaver(reader.AcquireNextImage(), owner));
}
// Saves a JPEG {@link Image} into the specified {@link File}.
private class ImageSaver : Java.Lang.Object, IRunnable
{
// The JPEG image
private Image mImage;
// The file we save the image into.
private File mFile;
private EmployeeNumInput mOwner;
public ImageSaver(Image image, EmployeeNumInput owner)
{
if (image == null)
throw new System.ArgumentNullException("image");
if (owner == null)
throw new System.ArgumentNullException("owner");
mImage = image;
mOwner = owner;
}
public void Run()
{
ByteBuffer buffer = mImage.GetPlanes()[0].Buffer;
byte[] bytes = new byte[buffer.Remaining()];
buffer.Get(bytes);
try
{
//フォーマット
var dateFormat = "yyyy年MM月dd日";
var timeFormat = "HH:mm:ss";
var workDate = DateTime.ParseExact(mOwner.Work.WorkDate, dateFormat, null);
var workTime = DateTime.ParseExact(mOwner.Work.WorkTime, timeFormat, null);
string fileName = mOwner.EmployeeNum.Text + "_" + workDate.ToString("MMdd") + workTime.ToString("HHmm") + ".jpg";
mFile = new File(mOwner.GetExternalFilesDir(Android.OS.Environment.DirectoryPictures), fileName);
}
catch (System.Exception)
{
DisplayAlert("==DBG==", "ImageAvailableListener ファイル名生成時に例外発生");
}
using (var output = new FileOutputStream(mFile))
{
try
{
output.Write(bytes);
}
catch (IOException e)
{
e.PrintStackTrace();
}
finally
{
mImage.Close();
}
}
}
private void DisplayAlert(string v1, string v2)
{
throw new NotImplementedException();
}
}
}
}
試したこと
Message=Image is already closed
なので、初期化処理などが行えていないかと思い、
写真撮影処理(TakePicture())に遷移する前に
Thread.Sleep(3000);
を追加するなどしましたが、
Java.Lang.IllegalStateException
Message=Image is not initialized
という別の例外が発生します。
補足情報(FW/ツールのバージョンなど)
試している実機デバイス HUAWEI P10 lite
Androidバージョン 8.0-API26
Microsoft Visual Studio Community 2019 Version 16.8.2
Xamarin 16.8.000.255
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
まだ回答がついていません
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.34%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる