カメラで写真を撮ろうとしていますが、次のようなエラーが表示されます。
FATAL EXCEPTION: main
Process: com.example.marek.myapplication, PID: 6747
Java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.example.marek.myapplication/files/Pictures/JPEG_20170228_175633_470124220.jpg
at Android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.Java:711)
at Android.support.v4.content.FileProvider.getUriForFile(FileProvider.Java:400)
at com.example.marek.myapplication.MainActivity.dispatchTakePictureIntent(MainActivity.Java:56)
at com.example.marek.myapplication.MainActivity.access$100(MainActivity.Java:22)
at com.example.marek.myapplication.MainActivity$1.onClick(MainActivity.Java:35)
AndroidManifest.xml:
<provider
Android:name="Android.support.v4.content.FileProvider"
Android:authorities="com.example.marek.myapplication.fileprovider"
Android:enabled="true"
Android:grantUriPermissions="true">
<meta-data
Android:name="Android.support.FILE_PROVIDER_PATHS"
Android:resource="@xml/file_paths" />
</provider>
Java:
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException ex) {
Toast.makeText(getApplicationContext(), "Error while saving picture.", Toast.LENGTH_LONG).show();
}
// Continue only if the File was successfully created
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this,
"com.example.marek.myapplication.fileprovider",
photoFile);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
}
}
file_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="my_images" path="images/"/>
</paths>
私は一日中このエラーについて調べていてFileProvider
を理解しようとしていましたが、このエラーメッセージが何を伝えようとしているのかわかりません。もっと情報やコードが欲しいなら、コメント欄に私を書いてください。
あなたのファイルはgetExternalFilesDir()
の下に保存されています。これは<external-files-path>
ではなく<files-path>
に対応します。また、ファイルパスの中にimages/
が含まれていないため、XMLのpath
属性は無効です。
res/xml/file_paths.xml
を次のように置き換えます。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path name="my_images" path="my_images" />
</paths>
有効なフレーバー(dev、stage)の後で同様の問題が発生しました。
風味を付ける前は、私のパスリソースは次のようになっていました。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="my_images"
path="Android/data/pl.myapp/files/Pictures" />
</paths>
Androidを追加した後:マニフェストappIdのauthorities = "$ {applicationId} .fileprovider"がpl.myapp.devまたはpl.myapp.stageになっていたため、フレーバーに依存し、アプリがクラッシュし始めました。フルパスを削除してドットに置き換えたところ、すべてが機能し始めました。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="my_images"
path="." />
</paths>
これは、everyonesの問題を解決する可能性があります。すべてのタグが追加されるので、フォルダパスを心配する必要はありません。 res/xml/file_paths.xmlを次のように置き換えます。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external"
path="." />
<external-files-path
name="external_files"
path="." />
<cache-path
name="cache"
path="." />
<external-cache-path
name="external_cache"
path="." />
<files-path
name="files"
path="." />
</paths>
あなたが内部キャッシュを使用しているならば、次にを使ってください。
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
<cache-path name="cache" path="/" />
</paths>
これも私を少し混乱させます。
問題はxmlファイルの "path"属性にあります。
このドキュメントから FileProvider 'path'はサブディレクトリですが、別のドキュメント(camera/photobasics)では 'path'はフルパスです。
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
<external-path name="my_images" path="Android/data/com.example.package.name/files/Pictures" />
</paths>
この「パス」をフルパスに変更するだけでうまくいきます。
お使いのデバイスが提供するストレージの数を確認します - セカンダリストレージからのファイルの共有はサポートされていません。 FileProvider.Java
ソースを見てください(support-core-utils 25.3.1から):
} else if (TAG_EXTERNAL_FILES.equals(tag)) {
File[] externalFilesDirs = ContextCompat.getExternalFilesDirs(context, null);
if (externalFilesDirs.length > 0) {
target = externalFilesDirs[0];
}
} else if (TAG_EXTERNAL_CACHE.equals(tag)) {
File[] externalCacheDirs = ContextCompat.getExternalCacheDirs(context);
if (externalCacheDirs.length > 0) {
target = externalCacheDirs[0];
}
}
だから、彼らは最初のストレージだけを取ります。
また、getExternalCacheDirs()
がContextCompat
インターフェースを介してストレージのリストを取得するために使用されていることがわかります。その限界については ドキュメント を参照してください(例えばUSBフラッシュを認識しないように言われます)。このAPIからストレージのリストのデバッグ出力を自分で作成して、ストレージへのパスがgetUriForFile()
に渡されたパスと一致することを確認することをお勧めします。
Googleのissue trackerにはすでに チケットが割り当てられています (06-2017の場合)。複数のストレージをサポートするように要求されます。結局、私はこれについての質問 も見つけました 。
遅れるかもしれませんが、それに対する解決策を見つけました。うまくいくように、XMLファイルのパスを次のように変更しました。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<root-path name="root" path="." />
</paths>
External-pathがあなたの二次記憶装置、別名「リムーバブル記憶装置」を指していないことに注意してください(名前「外部」にもかかわらず)。 「設定されたルートが見つかりませんでした」というメッセージが表示された場合は、この行をXMLファイルに追加してください。
<root-path name="root" path="." />
詳細はこちら FileProviderと二次外部ストレージ
これのどれも私のために働きませんでした。機能する唯一の方法は、xmlで明示的なパスを宣言しないことです。そうこれをし、幸せになりなさい:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
<external-path name="my_images" path="." />
</paths>
こちらもこの質問に関する優れたチュートリアルです。 https://www.youtube.com/watch?v=9ZxRTKvtfnY&t=613s
私はパーティーに遅れていると確信していますが、以下が私のために働きました。
<paths>
<root-path name="root" path="." />
</paths>
私の問題は、私はこのように異なる種類のファイルパスに重複する名前があることです。
<cache-path
name="cached_files"
path="." />
<external-cache-path
name="cached_files"
path="." />
名前( "cached_files")を一意に変更した後、エラーを取り除きました。私の推測では、これらのパスはいくつかのHashMapまたは重複を許可しないものに格納されています。
これは私のためにもうまくいった。フルパスを与える代わりに私はpath = "Pictures"を与え、それはうまくいった。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path
name="images"
path="Pictures">
</external-files-path>
</paths>
2週間で解決策を見つけようとしましたが、上記のような後退を試みた後にここに到着した場合は、次の手順を実行してください。
1 - タグプロバイダがタグアプリケーションの内側にあるかどうかを確認します
<application>
<provider Android:name="Android.support.v4.content.FileProvider" Android:authorities="com.companyname.Pocidadao.fileprovider" Android:exported="false" Android:grantUriPermissions="true">
<meta-data Android:name="Android.support.FILE_PROVIDER_PATHS" Android:resource="@xml/file_paths"></meta-data>
</provider>
</application>
2 - 成功せずにたくさんの方法を試した場合、これでテストしてください。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<cache-path name="cache" path="." />
<external-path name="external" path="." />
<root-path name="root" path="." />
<files-path name="my_images" path="/" />
<files-path name="my_images" path="myfile/"/>
<files-path name="files" path="." />
<external-path name="external_files" path="." />
<external-path name="images" path="Pictures" />
<external-path name="my_images" path="." />
<external-path name="my_images" path="Android/data/com.companyname.yourproject/files/Pictures" />
<external-path name="my_images" path="Android/data/com.companyname.yourproject/files/Pictures/" />
<external-files-path name="images" path="Pictures"/>
<external-files-path name="camera_image" path="Pictures/"/>
<external-files-path name="external_files" path="." />
<external-files-path name="my_images" path="my_images" />
<external-cache-path name="external_cache" path="." />
</paths>
カメラが動作する場合は、これをテストし、次にいくつかの行を削除してテストを続ける...
3 - カメラがエミュレータでアクティブになっているかどうかを確認することを忘れないでください。
これを解決するために私がしたこと -
AndroidManifest.xml
<provider
Android:name="Android.support.v4.content.FileProvider"
Android:authorities="com.mydomain.fileprovider"
Android:exported="false"
Android:grantUriPermissions="true">
<meta-data
Android:name="Android.support.FILE_PROVIDER_PATHS"
Android:resource="@xml/filepaths"/>
</provider>
filepaths.xml(FileProviderがアプリの外部ファイルディレクトリ内にあるすべてのファイルを共有できるようにする)
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
<external-files-path name="files"
path="/" />
</paths>
そしてJavaクラスで -
Uri fileProvider = FileProvider.getUriForFile(getContext(),"com.mydomain.fileprovider",newFile);
このエラーが出ましたFailed to find configured root that contains...
次の回避策は私の問題を解決します
res/xml/file_paths.xml
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
<external-path name="media" path="." />
</paths>
AndroidManifest.xml
<provider
Android:name="Android.support.v4.content.FileProvider"
Android:authorities="[PACKAGE_NAME]"
Android:exported="false"
Android:grantUriPermissions="true">
<meta-data
Android:name="Android.support.FILE_PROVIDER_PATHS"
Android:resource="@xml/file_paths">
</meta-data>
</provider>
ActivityClass.Java
void shareImage() {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/*");
intent.putExtra(Intent.EXTRA_STREAM, FileProvider.getUriForFile(this,"com.slappstudio.pencilsketchphotomaker", selectedFilePath));
startActivity(Intent.createChooser(intent,getString(R.string.string_share_with)));
}
私はこれに5時間を費やしました。
私は上記のすべての方法を試しましたが、それはあなたのアプリが現在使用している格納容量によって異なります。
https://developer.Android.com/reference/Android/support/v4/content/FileProvider#GetUri
コードを試す前にドキュメントを確認してください。
私の場合はfiles-path
サブディレクトリはContext.getFilesDir()
になります。ファンキーなことは、Context.getFilesDir()
が別のサブディレクトリをメモしているということです。
探しているのは
data/user/0/com.psh.mTest/app_imageDir/20181202101432629.png
Context.getFilesDir()
/data/user/0/com.psh.mTest/files
を返します
タグは
....files-path name="app_imageDir" path="../app_imageDir/" ......
それでうまくいきます!
上記のどれも私のために働きませんでした、数時間のデバッグの後、私は問題がcreateImageFile()
、特にabsolute path
vs relative path
にあることを知りました
私はあなたたちみんなが公式のAndroidガイドを使って写真を撮っていると思います。 https://developer.Android.com/training/camera/photobasics
private static File createImageFile(Context context) throws IOException {
// Create an image file name
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
String imageFileName = "JPEG_" + timeStamp + "_";
File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
imageFileName, /* prefix */
".jpg", /* suffix */
storageDir /* directory */
);
// Save a file: path for use with ACTION_VIEW intents
mCurrentPhotoPath = image.getAbsolutePath();
return image;
}
storageDir
に注意してください。これはファイルが作成される場所です。そのため、このファイルの絶対パスを取得するには、単にimage.getAbsolutePath()
を使用します。写真を撮った後にビットマップ画像が必要な場合は、このパスがonActivityResult
で使用されます
以下はfile_path.xml
です、絶対パスを使うように単に.
を使ってください
<paths>
<external-path
name="my_images"
path="." />
</paths>
写真を撮った後にビットマップが必要な場合
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Bitmap bmp = null;
try {
bmp = BitmapFactory.decodeFile(mCurrentPhotoPath);
} catch (Exception e) {
e.printStackTrace();
}
}
どのような種類のストレージ(INTERNALまたはEXTERNAL)を実行したいかによって異なります。
外部保管用
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path name="my_images" path="my_images" />
</paths>
しかし、INTERNAL STORAGEの場合は、パスに注意してください。getFilesDir()メソッドを使用するため、ファイルはアプリのルートディレクトリ( "/")に配置されます。
File storeDir = getFilesDir(); // path "/"
だからあなたのプロバイダファイルはこのようなものでなければなりません:
<paths>
<files-path name="my_images" path="/" />
</paths>
以下のxml file_pathsファイルの変更は私にとってうまくいきました。
<external-files-path name="my_images" path="Pictures"/>
<external-files-path name="my_movies" path="Movies"/>
Androidの公式文書には、file_paths.xmlには次のように記載されています。
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
<external-path name="my_images"
path="Android/data/com.example.package.name/files/Pictures" />
</paths>
しかし、これを最新のAndroidで動作させるには、パスの最後に次のように「/」を付けます。
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
<external-path name="my_images"
path="Android/data/com.example.package.name/files/Pictures/" />
</paths>
私はついに自分の問題を見つけた。私は このリンクでそれを説明しました。
私の問題はデバッグモードとリリースモードのアプリケーションIDの違いでした
あなたのfile_paths.xmlファイルの内容がこの文字列を含んでいることを確認する必要があります=> "/Android/data/com.example.marek.myapplication/files/Pictures/"
エラーメッセージから、それはあなたの写真が保存されている場所のパスです。期待のサンプルを見る
下記のfiles_path.xml:
<external-path name="qit_images" path="Android/data/com.example.marek.myapplication/files/Pictures/" />
こんにちは友人がこれを試します
このコードでは
1)マニフェストで2ファイルプロバイダを宣言する方法。
2)ファイルの最初の提供者ダウンロード
3)カメラおよびギャラリに使用される2番目のプロバイダ
ステップ1
<provider
Android:name="Android.support.v4.content.FileProvider"
Android:authorities="${applicationId}.fileprovider"
Android:exported="false"
Android:grantUriPermissions="true">
<meta-data
Android:name="Android.support.FILE_PROVIDER_PATHS"
Android:resource="@xml/provider_paths" />
</provider>
Provider_paths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="apks" path="." />
</paths>
2番目のプロバイダ
<provider
Android:name=".Utils.MyFileProvider"
Android:authorities="${applicationId}.provider"
Android:exported="false"
Android:grantUriPermissions="true"
tools:replace="Android:authorities"
tools:ignore="InnerclassSeparator">
<meta-data
Android:name="Android.support.FILE_PROVIDER_PATHS"
Android:resource="@xml/file_path" />
</provider>
file_path.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path name="storage/emulated/0" path="."/>
</paths>
。Utils.MyFileProvider
クラスの作成MyFileProvider(クラスの作成のみメソッド宣言なし)
ファイルプロバイダを使用したとき(.fileprovider)にこの名前を使用し、画像に使用したとき(.provider)にこれを使用した。
このコードを理解するのに問題がある場合は、rp1741995 @ gmail.comまでお問い合わせください。
何も助けにならず、エラーが発生している場合
failed to find configured root that contains /data/data/...
それから次のようにいくつかの行を変更してみてください。
File directory = thisActivity.getDir("images", Context.MODE_PRIVATE);
に:
File directory = new File(thisActivity.getFilesDir(), "images");
そしてxmlファイルで:
<files-path name="files" path="." />
私がアクセスするフォルダは/images
なので、これは変です。
問題はパスxmlだけではないかもしれません。
以下は私の修正です:
Android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile()
でルートコースを調べます。
public File getFileForUri(Uri uri) {
String path = uri.getEncodedPath();
final int splitIndex = path.indexOf('/', 1);
final String tag = Uri.decode(path.substring(1, splitIndex));
path = Uri.decode(path.substring(splitIndex + 1));
final File root = mRoots.get(tag); // mRoots is parsed from path xml
if (root == null) {
throw new IllegalArgumentException("Unable to find configured root for " + uri);
}
// ...
}
これはmRoots
が要求されたuriのタグを含むべきであることを意味します。 それでmRoots
とtag of uriを印刷するためのコードを書くと、タグが一致しないことが簡単にわかります。
プロバイダ権限を${applicationID}.provider
に設定するのは愚かな考えです。この権限は非常に一般的であるため、他のプロバイダによって使用される可能性があります。これにより、パス設定が台無しになります。
私の問題は間違ったファイル名でした:マニフェストでリソースがfile_paths.xml
に設定されているのにres/xmlの下にprovider_paths.xml
を作成しました。
<provider
Android:authorities="ir.aghigh.radio.fileprovider"
Android:name="Android.support.v4.content.FileProvider"
Android:exported="false"
Android:grantUriPermissions="true">
<meta-data
Android:name="Android.support.FILE_PROVIDER_PATHS"
Android:resource="@xml/provider_paths"/>
</provider>
provider_paths
をfile_paths
に変更し、問題を解決しました。
path.xml
ファイルに関するポリシーまたは動作がサポートライブラリ26と27の間で変更されたことに気付きました。カメラから写真をキャプチャするために、次の変更が行われました。
26では、<external-path>
とpath
引数で与えられたフルパスを使わなければなりませんでした。
27では、path
引数に<external-files-path>
とサブフォルダーのみを使用する必要がありました。
それでpath.xml
ファイルとしてSupport Library 27で私のために特に働いたものは、
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path name="camera_image" path="Pictures/"/>
</paths>
これは、Android 7.1、8.0以降をターゲットにしているときにサポートパッケージが更新されないことが原因である可能性もあります。それらを v25.4.0.2 + に更新すると、この特定のエラーがなくなる可能性があります(他の人が言ったようにfile_pathファイルを正しく構成したことになります)。
コンテキストの指定: Xamarin.FormsでNougatからOreoをターゲティングに切り替えました アプリで Xam.Plugin.Media で写真を撮ると、上記のエラーメッセージが表示されて失敗したため、パッケージの更新には失敗しました私のためのトリックは大丈夫です。
私は同じ問題を抱えていた、私はその作業のために以下のコードを試した。
1. Xmlfileを作成します:provider_paths
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="my_images" path="myfile/"/>
</paths>
2。メインフェストファイル
<provider
Android:name="Android.support.v4.content.FileProvider"
Android:authorities="com.ril.learnet.provider"
Android:exported="false"
Android:grantUriPermissions="true">
<meta-data
Android:name="Android.support.FILE_PROVIDER_PATHS"
Android:resource="@xml/provider_paths"/>
</provider>
3.あなたのJavaファイルに
File file = new File(getActivity().getFilesDir(), "myfile");
if (!file.exists()) {
file.mkdirs();
}
String destPath = file.getPath() + File.separator + attachmentsListBean.getFileName();
file mfile = new File(destPath);
Uri path;
Intent intent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
path = FileProvider.getUriForFile(AppController.getInstance().getApplicationContext(), AppController.getInstance().getApplicationContext().getPackageName() + ".provider", mfile );
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
} else {
path = Uri.fromFile(mfile);
}
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(path, "image/*");
getActivity().startActivity(intent);
少なくともfile_paths.xmlで他のパスと同じパスを指定していないようです。それで、あなたが正確に同じパッケージ名またはパスを3つの場所で提供することを確認してください:
Android:authorities
属性path
属性authority
引数。あなたはxmlファイルfile_paths.xmlをから変更する必要があります。
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="my_images" path="images/"/>
</paths>
に
<?xml version="1.0" encoding="utf-8"?>
<paths>
<fexeternal-path name="my_images" path="Android/data/com.example.marek.myapplication/files/Pictures"/>
</paths>