(解決済み) [Android11] getContentResolver().insert: Requested path doesn't apper under [/storage/emulated/0]
カテゴリー: ぷろぐらみんぐ
2023-10-26
タイトル
Android11
アプリから外部MicorSDカード領域に保存した画像がMediaStoreに登録できません!
getContentResolver().insert
EXTERNAL_CONTENT_URI
なぜ emulated/0 にパスを勝手に変更しているの?
内部のユーザー領域なら正常に実行できる。
外部MicorSDカード領域のパスの場合上記のエラーになる。
フラグは、2種類しかないし INTERNAL_CONTENT_URI は、違うし。
ほかにフラグが増えたとか?
EXTERNAL_CONTENT_URI: The content:// style URI for the "primary" external storage volume.
ほかのアプリ(ファイラーだと)で名称変更でするとMediaStoreに上がってくるので APIレベル指定の違いかな?
古いアンドロイドならOKなのかな?
なにか互換性の設定がいるとか?
よくわからないので別の古い端末で動作確認してみよう。
追記
解決しました
Androidサイトのヘルプにも記述がないから苦労した。
ネットにも情報ないし、みんな迷走してSDCardへの保存が使えないと思い込んでいる模様。
SDカードに画像を保存する場合
Android 11
[ DCIM , Pictures ] フォルダのみ
LPermissions := [FPermissionReadExternalStorage, FPermissionWriteExternalStorage];
すべての フォルダに画像を保存したい場合は、
を取得して、アプリのシステムプロパティの権限で、
許可:ストレージ:すべてのファイル ( すべてのファイル管理を許可 )
にする
if TOSVersion.Check(11,0) then
LPermissions := LPermissions + [FPermissionManageExternalStorage];
その他の設定
プロジェクト オプション:アプリケーション: 使用する権限
も併せて チェックする。
どちらかというとほんの数分の手間で、自前のjavaコードのbuildとjarの参照できるので
Delphiだとコードが長くて、使い勝手がわるいとか定数がないとかではまるので、
最新のこまかいのは javaで書いて その関数とかを 取り込んだほうがいいと思います。
Delphiコードの文献がすくないので、javaで書いたほうが簡単です。
Delphiの素のままだと定数がないとか関数がないとかアクセスできないので致命的すぎます。
複数プロジェクトを作るなら、javaで共通のコード作って参照できるようにしたほうが管理が楽だと思いました。
執筆:2023.10.26
編集:2023.10.26
編集:2023.10.26
Android11
アプリから外部MicorSDカード領域に保存した画像がMediaStoreに登録できません!
getContentResolver().insert
EXTERNAL_CONTENT_URI
Requested path doesn't apper under [/storage/emulated/0]
なぜ emulated/0 にパスを勝手に変更しているの?
内部のユーザー領域なら正常に実行できる。
外部MicorSDカード領域のパスの場合上記のエラーになる。
フラグは、2種類しかないし INTERNAL_CONTENT_URI は、違うし。
ほかにフラグが増えたとか?
EXTERNAL_CONTENT_URI: The content:// style URI for the "primary" external storage volume.
ほかのアプリ(ファイラーだと)で名称変更でするとMediaStoreに上がってくるので APIレベル指定の違いかな?
古いアンドロイドならOKなのかな?
なにか互換性の設定がいるとか?
よくわからないので別の古い端末で動作確認してみよう。
追記
解決しました
Androidサイトのヘルプにも記述がないから苦労した。
ネットにも情報ないし、みんな迷走してSDCardへの保存が使えないと思い込んでいる模様。
getContentUri([定義済み定数|'ボリューム名']) です。
SDカードは、ボリューム名を入れます。ボリューム名は、getExternalVolumeNames関数から取得できます.
getExternalVolumeNames関数の結果
external_primary : 本体に保存する場合
4桁数値-4桁数値 : SDカードに保存する場合
LContentUri := TJImages_Media.JavaClass.getContentUri(StringToJString([定義済み定数|ボリューム名]));
// 'external_primary' or '4桁数値-4桁数値' : Android11
// 'external' : 古いAndroid
LJNewURI := TAndroidHelper.ContentResolver.insert(LContentUri, LJContentValues);
SDカードは、ボリューム名を入れます。ボリューム名は、getExternalVolumeNames関数から取得できます.
getExternalVolumeNames関数の結果
external_primary : 本体に保存する場合
4桁数値-4桁数値 : SDカードに保存する場合
LContentUri := TJImages_Media.JavaClass.getContentUri(StringToJString([定義済み定数|ボリューム名]));
// 'external_primary' or '4桁数値-4桁数値' : Android11
// 'external' : 古いAndroid
LJNewURI := TAndroidHelper.ContentResolver.insert(LContentUri, LJContentValues);
if (TJBuild_VERSION.JavaClass.SDK_INT >= 29) then // (Android10 API 29)
// MediaStore.VOLUME_EXTERNAL_PRIMARY : Constant Value: "external_primary"
LVolume := 'external_primary'
else
LVolume := 'external';
// LVolume := 'xxxx-xxxx'; // SDカードの場合は数値を書いて有効にする
LContentUri := TJImages_Media.JavaClass.getContentUri(StringToJString(LVolume));
//LContentUri := TJMyAndroidUtils.JavaClass.getContentUriFromFilename(
// TAndroidHelper.Context, StringToJString(LContentFilename));
ShowDebugMessage('ContentResolver:Uri:' + #10 + JStringToString(LContentUri.toString()));
SDカードに画像を保存する場合
Android 11
[ DCIM , Pictures ] フォルダのみ
LPermissions := [FPermissionReadExternalStorage, FPermissionWriteExternalStorage];
すべての フォルダに画像を保存したい場合は、
を取得して、アプリのシステムプロパティの権限で、
許可:ストレージ:すべてのファイル ( すべてのファイル管理を許可 )
にする
if TOSVersion.Check(11,0) then
LPermissions := LPermissions + [FPermissionManageExternalStorage];
その他の設定
プロジェクト オプション:アプリケーション: 使用する権限
も併せて チェックする。
どちらかというとほんの数分の手間で、自前のjavaコードのbuildとjarの参照できるので
Delphiだとコードが長くて、使い勝手がわるいとか定数がないとかではまるので、
最新のこまかいのは javaで書いて その関数とかを 取り込んだほうがいいと思います。
Delphiコードの文献がすくないので、javaで書いたほうが簡単です。
Delphiの素のままだと定数がないとか関数がないとかアクセスできないので致命的すぎます。
複数プロジェクトを作るなら、javaで共通のコード作って参照できるようにしたほうが管理が楽だと思いました。