【问题标题】:java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/java.lang.IllegalArgumentException:未能找到包含 /storage/emulated/0/Android/data/ 的已配置根目录
【发布时间】:2017-02-23 05:06:45
【问题描述】:

构建基本应用程序并获得 IllegalArgumentException:有一个按钮来启动相机应用程序,我正在尝试将图像保存到图片中。 dispatchTakePictureIntent(); 方法在我点击图片按钮时被调用

发现了一些类似的问题,但无法解决我的问题:

下面是我的代码。有人可以帮我解决我所缺少的吗?

public class CatalogDataActivity extends AppCompatActivity {

    static final int REQUEST_IMAGE_CAPTURE = 1;
    public String path= Environment.getExternalStorageDirectory().getAbsolutePath()+"/CatalogData";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //verifyStoragePermissions();
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_catalog_data);
        final Button btCamera=(Button)findViewById(R.id.btn_camera);
        final Button btSave=(Button)findViewById(R.id.btn_save);

        final EditText etProductName=(EditText)findViewById(R.id.et_productName);
        final EditText etProductDescription=(EditText)findViewById(R.id.et_description);
        final TextView finalText=(TextView)findViewById(R.id.tv_saved_text);
        File dir=new File(path);
        if(!dir.isDirectory()){
            dir.mkdir();
        }
        btCamera.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
               /* Intent takePictureIntent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                if(takePictureIntent.resolveActivity(getPackageManager())!=null){
                    startActivityForResult(takePictureIntent,REQUEST_IMAGE_CAPTURE);
                }*/
                dispatchTakePictureIntent();
            }
        });
        btSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String newProductDataStr=etProductName.getText()+","+etProductDescription.getText()+"|";
                File file=new File(path+"/catalogdata.txt");
                System.out.println("Path:"+path);
                writeToFile(newProductDataStr,getApplicationContext());
                String data=readFromFile(getApplicationContext());
                finalText.setText(data);
                //finalText.
                String []splitData=data.split("|");

                //System.out.println(">>>>>>>>>>>>>>>>>>>>////"+splitData.length+"/////>>>>>>>>>>>>>>>>>>"+splitData[splitData.length-4]);
            }
        });

    }

    private void writeToFile(String data,Context context) {
        try {
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(context.openFileOutput("config1.txt", Context.MODE_APPEND));
            outputStreamWriter.write(data);
            outputStreamWriter.close();
        }
        catch (IOException e) {
            System.out.println("Exception"+ "File write failed: " + e.toString());
        }
    }

    private String readFromFile(Context context) {

        String ret = "";

        try {
            InputStream inputStream = context.openFileInput("config1.txt");

            if ( inputStream != null ) {
                InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
                BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
                String receiveString = "";
                StringBuilder stringBuilder = new StringBuilder();

                while ( (receiveString = bufferedReader.readLine()) != null ) {
                    stringBuilder.append(receiveString);
                }

                inputStream.close();
                ret = stringBuilder.toString();
            }
        }
        catch (FileNotFoundException e) {
            Log.e("login activity", "File not found: " + e.toString());
        } catch (IOException e) {
            Log.e("login activity", "Can not read file: " + e.toString());
        }

        return ret;
    }

    @Override
    public void onActivityResult(int requestCode,int resultCode,Intent data){
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
            Bundle extras = data.getExtras();
            Bitmap bitMap = (Bitmap) extras.get("data");
            String ImagePath = MediaStore.Images.Media.insertImage(
                    getContentResolver(),
                    bitMap,
                    "demo_image",
                    "demo_image"
            );
            System.out.println("Saved Image in :"+ImagePath);
        }
    }

    String mCurrentPhotoPath;

    private File createImageFile() throws IOException {
        // Create an image file name
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        if(!storageDir.isDirectory()){
            storageDir.mkdir();
        }
        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;
    }
    static final int REQUEST_TAKE_PHOTO = 1;

    private void dispatchTakePictureIntent() {
        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) {
                ex.printStackTrace();

            }
            // Continue only if the File was successfully created
            if (photoFile != null) {
                try {
                    Uri photoURI = FileProvider.getUriForFile(this,
                            "com.example.android.fileprovider",
                            photoFile);
                    takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
                    startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
            //galleryAddPic();
        }
    }
    private void galleryAddPic() {
        Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
        File f = new File(mCurrentPhotoPath);
        Uri contentUri = Uri.fromFile(f);
        mediaScanIntent.setData(contentUri);
        this.sendBroadcast(mediaScanIntent);
    }

}

manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.androidapp.natty.catalogcreate">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".CatalogDataActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-feature android:name="android.hardware.camera"
        android:required="true" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
        android:maxSdkVersion="18" />
    <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.example.android.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths"></meta-data>
    </provider>
</manifest>

file_paths.xml 放在 res/xml/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="com.androidapp.natty.catalogcreate/files/Pictures" />
</paths>    

activity_catalog_data.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_catalog_data"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.androidapp.natty.catalogcreate.CatalogDataActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:id="@+id/textView" />

    <Button
        android:text="Open Camera"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView"
        android:layout_marginTop="10dp"
        android:id="@+id/btn_camera"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:elevation="0dp" />

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="textPersonName"
        android:text="Product Name"
        android:ems="10"
        android:layout_below="@+id/btn_camera"
        android:layout_marginTop="50dp"
        android:id="@+id/et_productName"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true" />

    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:inputType="textMultiLine"
        android:ems="10"
        android:id="@+id/et_description"
        android:text="Enter Description"
        android:layout_below="@+id/et_productName"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:srcCompat="@android:drawable/ic_menu_add"
        android:layout_marginTop="28dp"
        android:id="@+id/iv_image1"
        android:layout_below="@+id/et_description" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:srcCompat="@android:drawable/ic_menu_add"
        android:layout_alignTop="@+id/iv_image1"
        android:layout_toRightOf="@+id/textView"
        android:layout_toEndOf="@+id/textView"
        android:id="@+id/iv_image2" />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:srcCompat="@android:drawable/ic_menu_add"
        android:layout_marginLeft="41dp"
        android:layout_marginStart="41dp"
        android:id="@+id/iv_image3"
        android:layout_alignTop="@+id/iv_image2"
        android:layout_toRightOf="@+id/iv_image2"
        android:layout_toEndOf="@+id/iv_image2" />

    <Button
        android:text="Save Product"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/iv_image2"
        android:layout_marginTop="18dp"
        android:id="@+id/btn_save"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/btn_save"
        android:layout_marginTop="56dp"
        android:text="Hello World!"
        android:id="@+id/tv_saved_text" />

</RelativeLayout>

> W/System.err: java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/Android/data/com.androidapp.natty.catalogcreate/files/Pictures/JPEG_20170222_233359_1077283085.jpg
W/System.err:     at android.support.v4.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:711)
W/System.err:     at android.support.v4.content.FileProvider.getUriForFile(FileProvider.java:400)
W/System.err:     at com.androidapp.natty.catalogcreate.CatalogDataActivity.dispatchTakePictureIntent(CatalogDataActivity.java:176)
W/System.err:     at com.androidapp.natty.catalogcreate.CatalogDataActivity.access$000(CatalogDataActivity.java:33)
W/System.err:     at com.androidapp.natty.catalogcreate.CatalogDataActivity$1.onClick(CatalogDataActivity.java:61)
W/System.err:     at android.view.View.performClick(View.java:5612)
W/System.err:     at android.view.View$PerformClick.run(View.java:22285)
W/System.err:     at android.os.Handler.handleCallback(Handler.java:751)
W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:95)
W/System.err:     at android.os.Looper.loop(Looper.java:154)
W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6123)
W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:757)
I/Choreographer: Skipped 2537 frames!  The application may be doing too much work on its main thread.
I/art: Do full code cache collection, code=101KB, data=124KB
I/art: After code cache collection, code=64KB, data=67KB

【问题讨论】:

  • 使用 6.0 taget sdk ?
  • 最小 sdk 4,我已经在 7.0 中测试过
  • 你需要给运行时权限,我在下面给出答案

标签: java android


【解决方案1】:

我认为这是正确的方法

<?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>

【讨论】:

  • 是的,这行得通。当我使用 context.getFilesDir() 保存文件时。谢谢
  • 这对我有用,非常感谢
【解决方案2】:

如果您是初学者或对文件提供程序配置有一点困惑,请考虑这一点

  • &lt;files-path/&gt; - internal app storage, Context#getFilesDir()
  • &lt;cache-path/&gt; - internal app cache storage, Context#getCacheDir()
  • &lt;external-path/&gt; - public external storage, Environment.getExternalStorageDirectory()
  • &lt;external-files-path/&gt; - external app storage, Context#getExternalFilesDir(null)
  • &lt;external-cache-path/&gt; - external app cache storage, Context#getExternalCacheDir()

这是一个真实或安全的案例解决方案

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="my_images" path="/" />
</paths>

Environment.getExternalStorageDirectory() 返回路径如下:

/storage/emulated/0

所以

<external-path name="my_images" path="/" />

如果你想对文件夹进行一些控制,你可以访问文件夹内的所有文件,你可以像这样&lt;external-path name="my_images" path="/b" /&gt; 进行更改。那么你只得到 b 文件夹、文件和文件夹

【讨论】:

    【解决方案3】:

    com.androidapp.natty.catalogcreate / files / Pictures directory in the root directory / storage / emulated / 0 /(external-path)不能直接访问,需要指定完整路径,即'Android / data / com.androidapp.natty .catalogcreate / files / Pictures'。

    也可以使用external-files-path(对应/storage/emulated/0/com.androidapp.natty.catalogcreate/files/目录),然后指定其Pictures目录。 代码如下:

    <?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.androidapp.natty.catalogcreate/files/Pictures" />
        </paths>
    

    或:

        <?xml version="1.0" encoding="utf-8"?>
        <paths xmlns:android="http://schemas.android.com/apk/res/android">
            <external-files-path name="my_images" path="" />
        </paths>  
    

    或:

        <?xml version="1.0" encoding="utf-8"?>
        <paths xmlns:android="http://schemas.android.com/apk/res/android">
            <external-files-path name="my_images" path="Pictures" />
        </paths>  
    

    【讨论】:

    • 在堆栈溢出时通常会感谢一些解释。
    • 英文不好,第一次评论栈溢出。我希望你明白我在说什么。
    • 第二个也对我有用...这之前很头疼,谢谢!
    • 我也有类似的问题。能否请你帮忙? stackoverflow.com/questions/67279734/…
    【解决方案4】:

    我通过移动解决了这个问题

    <uses-feature android:name="android.hardware.camera"
            android:required="true" />
        <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
            android:maxSdkVersion="18" />
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="com.example.android.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"></meta-data>
        </provider>
    

    清单文件中应用程序级别的代码。

    【讨论】:

      【解决方案5】:

      在清单中使用文件提供程序

      并声明provider_path,如下所述

          <external-path path="." name="external_storage_root" />
      

      它会解决问题

      【讨论】:

      • 这是否意味着我们要求访问整个根文件夹而不是应用程序特定文件夹?
      【解决方案6】:
      public void getGROUPSTORAGEPremission(){
              int hasWriteContactsPermission = Splash_activity.this.checkSelfPermission(Manifest.permission_group.STORAGE);
              if (hasWriteContactsPermission != PackageManager.PERMISSION_GRANTED) {
                  Splash_activity.this.requestPermissions(new String[]{  Manifest.permission_group.STORAGE},
                          PERMISSION_GROUPSTORAGE);
              } else {
      
                  //your code here
              }
      
          }
      
      
      @Override
          public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
              super.onRequestPermissionsResult(requestCode, permissions, grantResults);
              if (requestCode == PERMISSION_RECEIVESMS) {
                  if (grantResults[0] == PackageManager.PERMISSION_GROUPSTORAGE) {
                      //your code here
                  } else {
                      // Permission Denied
      //              Toast.makeText(mContext, "STORAGE Denied", Toast.LENGTH_SHORT)
      //                      .show();
                  }
              }
      

      【讨论】:

        【解决方案7】:

        这样使用:

        private static final int REQUEST_ID_MULTIPLE_PERMISSIONS = 1;
        public static final int MEDIA_TYPE_IMAGE = 1;
        private Uri fileUri;
        int isCamera = 1;
        
        
        
            if (options[item].equals("Camera")) {
                isCamera = 1;
                if (checkandRequestPermission()) {
                   Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                       intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                       fileUri = FileProvider.getUriForFile(EditProfile.this, getPackageName()+ ".provider", getOutputMediaFile(MEDIA_TYPE_IMAGE));
                       intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
                   } else {
                              fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
                              intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
                     }
                     startActivityForResult(intent, 1);
                  }
               } else if (options[item].equals("Choose from Gallery")) {
                        isCamera = 0;
                        if (checkandRequestPermission()) {
                        Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                        startActivityForResult(intent, 2);
               } 
        }
        
        
        private boolean checkandRequestPermission() {
                int camera = ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA);
                int storageread = ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE);
                int storagewrite = ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE);
        
                List<String> listpermissionNeeded = new ArrayList<>();
        
                if (camera != PackageManager.PERMISSION_GRANTED) {
                    listpermissionNeeded.add(Manifest.permission.CAMERA);
                }
                if (storageread != PackageManager.PERMISSION_GRANTED) {
                    listpermissionNeeded.add(Manifest.permission.READ_EXTERNAL_STORAGE);
                }
                if (storagewrite != PackageManager.PERMISSION_GRANTED) {
                    listpermissionNeeded.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
                }
                if (!listpermissionNeeded.isEmpty()) {
                    ActivityCompat.requestPermissions(EditProfile.this, listpermissionNeeded.toArray(new String[listpermissionNeeded.size()]), REQUEST_ID_MULTIPLE_PERMISSIONS);
                    return false;
                }
                return true;
            }
        

        并添加 onRequestPermission 结果。

        @Override
            public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
                switch (requestCode) {
                    case REQUEST_ID_MULTIPLE_PERMISSIONS: {
                        // If request is cancelled, the result arrays are empty.
                        if (grantResults.length > 0
                                && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        
                            // permission was granted, yay! Do the
                            //  task you need to do.
                            if ((ContextCompat.checkSelfPermission(this,
                                Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
                                && (ContextCompat.checkSelfPermission(this,
                                Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)
                                && (ContextCompat.checkSelfPermission(this,
                                Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)) {
                                if (isCamera == 1) {
                                    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                                        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                                        fileUri = FileProvider.getUriForFile(EditProfile.this, getPackageName()+ ".provider", getOutputMediaFile(MEDIA_TYPE_IMAGE));
                                        intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
                                    } else {
                                        fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
                                        intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);
                                    }
                                    startActivityForResult(intent, 1);
                                } else {
                                    Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                                    startActivityForResult(intent, 2);
                                }
                            }
        
                        } else {
                            // permission denied, boo! Disable the
                            // functionality that depends on this permission.
                            Toast.makeText(this, "permission denied", Toast.LENGTH_LONG).show();
                        }
                        return;
                    }
                }
            }
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多