ClipData.Item.getUri를 통해 앱 외부에 노출


99

Android 파일 시스템에 새로운 기능이 추가 된 후 문제를 해결하려고하는데이 오류가 발생합니다.

android.os.FileUriExposedException: file:///storage/emulated/0/MyApp/Camera_20180105_172234.jpg exposed beyond app through ClipData.Item.getUri()

그래서 누군가가 이것을 고칠 수 있기를 바랍니다. :)

감사

private Uri getTempUri() {
    // Create an image file name
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss");
    String dt = sdf.format(new Date());
    imageFile = null;
    imageFile = new File(Environment.getExternalStorageDirectory()
            + "/MyApp/", "Camera_" + dt + ".jpg");
    AppLog.Log(
            TAG,
            "New Camera Image Path:- "
                    + Environment.getExternalStorageDirectory()
                    + "/MyApp/" + "Camera_" + dt + ".jpg");
    File file = new File(Environment.getExternalStorageDirectory() + "/MyApp");
    if (!file.exists()) {
        file.mkdir();
    }
    imagePath = Environment.getExternalStorageDirectory() + "/MyApp/"
            + "Camera_" + dt + ".jpg";
    imageUri = Uri.fromFile(imageFile);
    return imageUri;
}

답변:


166

SDK 24 이상의 경우 앱 저장소 외부에있는 파일의 Uri를 가져와야하는 경우이 오류가 발생합니다.
@ eranda.del 솔루션을 사용하면이를 허용하도록 정책을 변경할 수 있으며 제대로 작동합니다.

그러나 앱의 API 정책을 변경하지 않고 Google 가이드 라인을 따르려면 FileProvider를 사용해야합니다.

먼저 파일의 URI를 가져 오려면 FileProvider.getUriForFile () 메서드를 사용해야합니다.

Uri imageUri = FileProvider.getUriForFile(
            MainActivity.this,
            "com.example.homefolder.example.provider", //(use your app signature + ".provider" )
            imageFile);

그런 다음 Android 매니페스트에서 공급자를 구성해야합니다.

<application>
  ...
     <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="com.example.homefolder.example.provider"
        android:exported="false"
        android:grantUriPermissions="true">
        <!-- ressource file to create -->
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths">  
        </meta-data>
    </provider>
</application>

( "권한"에서 getUriForFile () 메서드의 두 번째 인수와 동일한 값을 사용합니다 (앱 서명 + ".provider")).

마지막으로 리소스 파일 "file_paths"를 만들어야합니다. 이 파일은 res / xml 디렉토리 아래에 만들어야합니다 (이 디렉토리도 만들어야 할 것입니다).

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

78
"개발자의 삶을 더 편하게"-이것은 모든 새로운 API에 대한 태그 라인입니다. 맞습니까?
Kirill Karmazin

12
Brendon이 제공하는 솔루션은 올바른 솔루션이지만 복사-붙여 넣기 준비가되어 있지 않습니다. 예를 들어 필요에 맞는지 확인해야합니다. <external-path ...Environment.getExternalStorageDirectory ()를 원할 때 사용됩니다. <files-path ...Context.getFilesDir ()이 필요한 경우 사용 하십시오. 공식 문서를 먼저 확인하는 것이 좋습니다. developer.android.com/reference/android/support/v4/content/…
Kirill Karmazin

9
androidx (새 지원 네임 스페이스)를 사용중인 경우 여기 ( developer.android.com/reference/androidx/core/content/… )에서 적절한 문서를 찾을 수 있습니다 .
Rodrirokr 2018

19
참고한다는 점에서 androidx그것은이다android:name="androidx.core.content.FileProvider"
smörkex는

150

카메라 또는 파일 검색을 시작하기 전에 다음 코드 블록을 추가하십시오.

    StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
    StrictMode.setVmPolicy(builder.build());

참조 링크 엄격 모드 와 모든 사용법 및 기술 세부 사항에 대한 설명을 참조하십시오.


24
이 문제를 해결하는 올바른 방법이 아니므로 기본적으로 엄격 모드 정책이 제거됩니다. 및 보안 경고 무시
아산는 Zaheer

이것에 대한 몇 가지 장단점이 있습니다. 더 많은 정보를 얻을 수있는 다음을 참조하십시오 stackoverflow.com/questions/18100161/...
eranda.del

어떤 무승부 다시이 있다면 그것은 :) 다음 알려 주시기 바랍니다, 작동
하난

코드는 나를 위해 예외를 해결했습니다. 그러나 여기의 상단 댓글은 코드가이 문제를 해결하는 올바른 방법이 아니라는 것을 말합니다. 누구든지 적절한 방법이 무엇인지 알고 있습니까?
Shn_Android_Dev

Google은 프로그래머를 싫어합니다.
Joubert Vasconcelos

0

AndroidManifest에 필요한 공급자 구성은 필요하지 않으며 카메라 및 저장소 권한 만 허용되어야합니다. 다음 코드를 사용하여 카메라를 시작하십시오.

final int REQUEST_ACTION_CAMERA = 9;
void openCamra() {
Intent cameraImgIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

cameraImgIntent.putExtra(MediaStore.EXTRA_OUTPUT,
                FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID +".provider",
                new File("your_file_name_with_dir")));
startActivityForResult(cameraImgIntent, REQUEST_ACTION_CAMERA);
}

이미지를 캡처 한 후 다음 위치에서 캡처 한 이미지를 찾을 수 있습니다.

"your_file_name_with_dir"

다른 코드를 제공하는 것보다 AndroidManifest에서 제공자의 구성을 설명하는 것이 좋습니다.
fury.slay
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.