質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

解決済

1回答

126閲覧

android webview fileタグでカメラ起動させて撮った写真を渡そうとするとファイルが見つからない例外が発生するのを解決したいです

toumorokoshi

総合スコア15

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

0クリップ

投稿2024/04/06 06:45

編集2024/04/06 11:28

実現したいこと

android webview fileタグでカメラ起動させて撮った写真を渡そうとするとファイルが見つからない例外が発生するのを解決したいです
画像ファイルを選択した場合は fileタグに渡せている状態で、カメラで撮った写真だけ渡せない状態です。

発生している問題・分からないこと

カメラで撮った画像を一時的にアプリ内のストレージに保存して、その URI を ContentResolver で content:// から始まる URI を取得して、onReceiveValue にセットすると、fileタグの右側にファイル名は表示されますが、実際は当該ファイルが見つからない例外が発生します。
Android 10 以降を対象にしているので uses-permission は android.permission.READ_MEDIA_IMAGES を指定しています。

queries には以下を指定してあります。
android.media.action.IMAGE_CAPTURE
android.intent.action.GET_CONTENT

provider 要素も指定してあります。

該当のソースコード

kotlin

1 private fun getPhotoUri(context: Context, file: File): Uri { 2 return FileProvider.getUriForFile(context, context.packageName + ".provider", file) 3 } 4 private fun createImageFile(): File? { 5 @SuppressLint("SimpleDateFormat") val timeStamp = SimpleDateFormat( 6 "yyyyMMdd_HHmmss" 7 ).format(Date()) 8 val imageFileName = "img_" + timeStamp + "_k" 9 // 外部ストレージのディレクトリを取得し、storageDir変数に格納 10 val storageDir = _context?.getExternalFilesDir(Environment.DIRECTORY_PICTURES) 11 // 一時的なJPEGファイルを作成し、外部ストレージ内の一時ディレクトリに作成 12 var file: File? = null 13 try { 14 file = File.createTempFile(imageFileName, ".jpg", storageDir) 15 } catch (ex: Exception) { 16 Log.d(TAG, "exception:$ex") 17 } 18 return file 19 } 20↑まずこの関数で空のファイルをストレージに出力しています。 21この時のファイル URI を保存しておきます。 22 23 private fun registerContentResolver(context: Context, filePath: String): Uri? { 24 val values = ContentValues() 25 values.put(MediaStore.Images.Media.DISPLAY_NAME, filePath) 26 values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg") 27 28 var uri = context.contentResolver.insert(MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY), values) 29 30 return uri 31 } 32↑この関数でカメラで写真を撮ったあと、registerForActivityResult が呼ばれます。 33AndroidStudio の DeviceExploler で撮った写真の実体が保存されていることを確認しています。 34この時に先ほど保存した URI のパスが、写真の実体になっていることを確認しました。 35この URI を ContentResolver に insert すると、content:// から始まる ID 付きのパスで insert されました。 36このパスを onReceiveValue にセットすると、当該ファイルが見つからない例外発生しました。 37 38撮った画像ファイルの書き込みができているので、参照もできると思いますが、このパス (ID 付きのパス) が参照できない問題を解決したいです。

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

FileProvider.getUriForFile で取得できた結果は
content://パッケージ名.provider/files/storage/emulated/0/Android/data/パッケージ名/files/Pictures/img_20240406_114336_k7044656972246031396.jpg

ContentResolver.insert で作成した URI は
content://media/external_primary/images/media/1000001188
です。
(.jpg ファイル名の数字やメディア ID はスクリーンショットを撮る前のビルドで記録したものなのでスクリーンショットと異なります)

イメージ説明
イメージ説明

補足

特になし


その後ですが、Android 10 だとパーミッションが android.permission.READ_MEDIA_IMAGES ではなく、android.permission.WRITE_EXTERNAL_STORAGE になるのですが、registerForActivityResult の result.data から Intent が取得でき、画像選択時と同じ処理でカメラ画像を fileタグ に渡すことができました。
この場合はフォーム送信時にファイルの実体は送信できていました。(PHP の$_FILES のファイルサイズが 0 ではなかったことで確認)

Android 13 の場合は、result.data が null だったので、空ファイルを作った時のパスから ContentResolver にセットする URI を作成しています。
この URI を作成する元のファイルが添付画像の DeviceExploler の実体はありましたとのパスと一致はしており、そこから content:// スキームから始まるメディア ID の URI に変換できているので、実体があればメディア ID の URI に変換できるのであれば、パス自体は問題ないと思うのですが、InputStream でこの URI を開こうとしても同様にファイルが見つからない例外が発生したので、生成された URI 自体が正しいかを調べてみます。
もし同じような症状を解決した方がいらっしゃれば情報をいただけるとありがたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2024/04/07 17:23 編集

ContentResolver で insert した結果の URI は、対象となった ContentProvider での該当データの管理情報(RDBにおける insert か返す rowid みたいなモノ)です。 「URI に変換」とか書かれていますが、その辺のご理解は大丈夫でしょうか? [Android 画像ファイルを扱う際のFileとUriまとめ] https://qiita.com/wakamesoba98/items/98b79bdfde19612d12b0 [Android開発: ”ContentResolver” とは何者か?] C# http://blog.livedoor.jp/locked_empty_shell/archives/5710241.html
toumorokoshi

2024/04/18 05:56

色々試していたのでご返答が遅くなりました。 結論としてはカメラ撮影用に一時ファイルを作成したのですがその時のパスを渡すことで <form> に渡すことができました。 ContentResolver についての解説がすごくわかりやすくて助かりました。 確かに rowid のようなものでした。 この URI を contentResolver.openInputStream() で開こうとすると not found になる部分は解決できませんでしたが、いい勉強になりました。 遅くなりましたがありがとうございました。
toumorokoshi

2024/04/18 05:58

コメントありがとうございます。 ベストアンサーに選びたいので同じ内容を回答欄に投稿いただけますでしょうか?
jimbe

2024/04/18 06:18 編集

お疲れさまでした。色々試すのは大事ですね。 insert した結果の Uri から openInputStream でデータを得るには、先に「insert した結果から openOutputStream で得る OutputStream」に対してデータを書き込んでおかなければなりません。 つまり、書き込む側は insert で管理情報 Uri を作成し openOutputStream でその管理情報が管理するデータを書き込こむまでが 1 つの処理で、読み込む側は管理情報の Uri から openInputStream でデータを得ることになります。
toumorokoshi

2024/04/22 00:24

Uri は取得できるもののデータの書き込み自体が完了できてるか微妙だったので明示的に書き込んだ後、insert で作成した管理情報 Uri からあらめてデータを得るというところが肝だったのですね。 大変勉強になりました!
guest

回答1

0

ベストアンサー

ContentResolver で insert した結果の URI は、対象となった ContentProvider での該当データの管理情報(RDBにおける insert か返す rowid みたいなモノ)です。
「URI に変換」とか書かれていますが、その辺のご理解は大丈夫でしょうか?

[Android 画像ファイルを扱う際のFileとUriまとめ]
https://qiita.com/wakamesoba98/items/98b79bdfde19612d12b0

[Android開発: ”ContentResolver” とは何者か?] C#
http://blog.livedoor.jp/locked_empty_shell/archives/5710241.html

投稿2024/04/18 06:17

jimbe

総合スコア12659

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

toumorokoshi

2024/04/22 00:26

今回の回答とは別の方法で解決させましたが、ContentResolver の概念がよくわかる説明で大変参考になりました。 今後も ContentResolver とは付き合うことになるので、この情報を参考に実装したいと思います。 貴重は情報大変ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問