API26 이후 부터는 파일경로를 직접적으로 노출하게되면 아래와 같은 에러가 발생됩니다.

 

Android.OS.FileUriExposedException: file:///storage/emulated/0/test.png exposed beyond app through ClipData.Item.getUri()

 

이를 위해선

먼저 AndroidManifest.xml 에 아래 처럼 FileProvider 를 추가하고 Resource 폴더 아래에 xml 폴더를 만들어 file_paths.xml 파일을 추가 생성합니다.

 

<application android:label="QrCodeManager">

<provider android:name="android.support.v4.content.FileProvider" android:authorities="kr.kjun.QrCodeManager.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>

 

생성된 file_paths.xml 파일에 아래처럼 내용울 추가합니다.

 

<?xml version="1.0" encoding="utf-8" ?>

  <paths xmlns:android="http://schemas.android.com/apk/res/android">

    <external-path name="storage/emulated/0" path="."/>

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

  </paths>

 

 

여기서 중요한건 <root-path name="root" path="."/> 을 추가하지 않으면 아래와 같은 에러가 발생되니 반드시 추가가 필요합니다.

 

Java.Lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/0/test.png

 

 

코드 단에서 사용할때 아래 굵게 표시된 부분처럼 처리하면 된다.

 

var tempFilename = "test.png";

var sdCardPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath;

var filePath = System.IO.Path.Combine(sdCardPath, tempFilename);

 

Bitmap bitmap = ..;

using (var fileStream = new FileStream(filePath, FileMode.Create))

{

    bitmap.Compress(Bitmap.CompressFormat.Png, 100, fileStream);

}

bitmap.Dispose();

 

Android.Net.Uri imageUri = null;

 

if (Build.VERSION.SdkInt >= BuildVersionCodes.M)

{

    Java.IO.File file = new Java.IO.File(filePath);

    imageUri = FileProvider.GetUriForFile(this, "kr.kjun.QrCodeManager.fileprovider", file);

}

else

{

    imageUri = Android.Net.Uri.Parse($"file://{sdCardPath}/{tempFilename}");

}

..

 

 

 

 

 

+ Recent posts