source

ClipData를 통해 앱을 넘어 노출됩니다.Item.getUri

goodcode 2022. 9. 5. 22:57
반응형

ClipData를 통해 앱을 넘어 노출됩니다.Item.getUri

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;
}

sdk 24 이상의 경우 앱 스토리지 외부에 있는 파일의 URI를 가져와야 하는 경우 이 오류가 발생합니다.
@eranda.del 솔루션을 사용하면 정책을 변경하여 이를 허용하고 정상적으로 작동합니다.

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

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

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

그런 다음 안드로이드 매니페스트에서 프로바이더를 설정해야 합니다.

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

('authority'에서는 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>

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

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

참조 링크 엄밀한 모드와 사용 방법 및 기술 세부 정보를 참조하십시오.

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"

코드를 추가하다

onCreate(Budle savedInstancesState){
    if (Build.VERSION.SDK_INT >= 24) {
        try {
            Method m = StrictMode.class.getMethod("disableDeathOnFileUriExposure");
            m.invoke(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

언급URL : https://stackoverflow.com/questions/48117511/exposed-beyond-app-through-clipdata-item-geturi

반응형