web-dev-qa-db-ja.com

FileProvider - IllegalArgumentException:設定されたルートが見つけませんでした

カメラで写真を撮ろうとしていますが、次のようなエラーが表示されます。

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を理解しようとしていましたが、このエラーメッセージが何を伝えようとしているのかわかりません。もっと情報やコードが欲しいなら、コメント欄に私を書いてください。

133
Pivoman

あなたのファイルは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>
97
CommonsWare

有効なフレーバー(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>
70
antygravity

これは、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>
49
Mitul Varmora

あなたが内部キャッシュを使用しているならば、次にを使ってください。

<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <cache-path name="cache" path="/" />
</paths>
40
Innocent

これも私を少し混乱させます。

問題は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>

この「パス」をフルパスに変更するだけでうまくいきます。

15
Supakij

お使いのデバイスが提供するストレージの数を確認します - セカンダリストレージからのファイルの共有はサポートされていません。 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の場合)。複数のストレージをサポートするように要求されます。結局、私はこれについての質問 も見つけました

14
lef

遅れるかもしれませんが、それに対する解決策を見つけました。うまくいくように、XMLファイルのパスを次のように変更しました。

 <?xml version="1.0" encoding="utf-8"?>
<paths>
    <root-path name="root" path="." />
</paths>
11
subbu

External-pathがあなたの二次記憶装置、別名「リムーバブル記憶装置」を指していないことに注意してください(名前「外部」にもかかわらず)。 「設定されたルートが見つかりませんでした」というメッセージが表示された場合は、この行をXMLファイルに追加してください。

<root-path name="root" path="." />

詳細はこちら FileProviderと二次外部ストレージ

10
Peter Shashkin

これのどれも私のために働きませんでした。機能する唯一の方法は、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>
8
spartanfree

私の問題は、私はこのように異なる種類のファイルパスに重複する名前があることです。

<cache-path
    name="cached_files"
    path="." />
<external-cache-path
    name="cached_files"
    path="." />

名前( "cached_files")を一意に変更した後、エラーを取り除きました。私の推測では、これらのパスはいくつかのHashMapまたは重複を許可しないものに格納されています。

7
Jeopardy

これは私のためにもうまくいった。フルパスを与える代わりに私はpath = "Pictures"を与え、それはうまくいった。

<?xml version="1.0" encoding="utf-8"?>
 <paths>
  <external-files-path
    name="images"
    path="Pictures">
  </external-files-path>
 </paths>
3
Amit Arora

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 - カメラがエミュレータでアクティブになっているかどうかを確認することを忘れないでください。

3
Diego Venâncio

これを解決するために私がしたこと -

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);
2
Rupam Das

このエラーが出ました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)));
    }
2
Ali Tamoor

私はこれに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/" ......

それでうまくいきます!

2
Seho Park

上記のどれも私のために働きませんでした、数時間のデバッグの後、私は問題が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();
        }
    }
2
grandia

どのような種類のストレージ(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"/>
1
Manmohan Soni

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>
1
Shripad Bhat

私はついに自分の問題を見つけた。私は このリンクでそれを説明しました。

私の問題はデバッグモードとリリースモードのアプリケーションIDの違いでした

0
saleh sereshki

あなたの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/" />
0
Oladipo Olasemo

こんにちは友人がこれを試します

このコードでは

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までお問い合わせください。

0
Rahul Patil

何も助けにならず、エラーが発生している場合

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なので、これは変です。

0

問題はパス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に設定するのは愚かな考えです。この権限は非常に一般的であるため、他のプロバイダによって使用される可能性があります。これにより、パス設定が台無しになります。

0
thundertrick

私の問題は間違ったファイル名でした:マニフェストでリソースが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_pathsfile_pathsに変更し、問題を解決しました。

0

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>
0
Johan Paul
  • Xamarin.Androidユーザーの場合

これは、Android 7.1、8.0以降をターゲットにしているときにサポートパッケージが更新されないことが原因である可能性もあります。それらを v25.4.0.2 + に更新すると、この特定のエラーがなくなる可能性があります(他の人が言ったようにfile_pathファイルを正しく構成したことになります)。


コンテキストの指定: Xamarin.FormsでNougatからOreoをターゲティングに切り替えました アプリで Xam.Plugin.Media で写真を撮ると、上記のエラーメッセージが表示されて失敗したため、パッケージの更新には失敗しました私のためのトリックは大丈夫です。

0
Ahmed Alejo

私は同じ問題を抱えていた、私はその作業のために以下のコードを試した。

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);
0
Suresh kumar

少なくともfile_paths.xmlで他のパスと同じパスを指定していないようです。それで、あなたが正確に同じパッケージ名またはパスを3つの場所で提供することを確認してください:

  • マニフェストのAndroid:authorities属性
  • file_paths.xmlのpath属性
  • FileProvider.getUriForFile()を呼び出すときのauthority引数。
0
Pei

あなたは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>
0
Andrey