내가 카메라로 촬영한 사진이나 영상을 다른 앱으로 보고자 하는 경우 이전에는 아래와 같이 하였다.
File file = new File('파일경로');
Intent. inetnt = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(file), "image/png");
startActivity(intent);
하지만 안드로이드 10부터 Scopped storate모드가 지원되면서 안되기 시작하더니 이제는 그냥 안된되고 보면 될것 같다.
이젠 아래와 같이 호출해야 정상적으로 다른앱으로 내가 만든 사진을 볼수가 있다. 그것도 앱이 사용중에만.
File file = new File('파일경로');
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
intent.sestDataAndType(
FileProvider.getUriForFile(this, getPackageName()+".fileprovider", file),
"image/png");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
Uri.fromFile()이 아니라 FileProvider.getUriForFile(...)를 사용하였고 FLAG_GRANT_READ_URI_PERMISSION권한을 추가해 주었다. 이 권한은 호출한 앱의 테스크가 유지되는 동안 유지된다. 즉 앱이 종료될때까지 된다고 보면 될것 같다.
'파일경로'라고 되어 있는 부분은 아무 경로나 되는것이 아니며 일반적으로 개발자들은 sdcard에 저장하길 원할것이다.
앱패키지명이 'com.my.app'이라면 '/sdcard/Android/data/com.my.app/files'가 된다.
FileProvider에 대한 글은 많이 있기 때문에 자세한 설명은 하지 않고 만일 /image폴더에 저장하고 그 파일을 다른 앱으로 보고자 할 경우에는 아래와 같이 하면 된다.
AndroidManifest.xml
<provider
android:name="androidx.core.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>
/res/xml/provider_paths.xml
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-files-path name="external_files" path="." />
</paths>
/sdcard/Android/data/com.my.app/files/image 폴더내의 sample.png파일은 아래와 같이 지정한다.
File file = new File(getExternalFilesDir("image") + "/sample.png");
이렇게 지정된 파일을 FilrProvider.getUriForFile()로 Uri를 얻어내어 Intent에 던져 주면 이미지파일을 열 수 있는 다른 앱이 이미지를 보여줄수 있게 된다.
provider_paths.xml에서 외부에 공유 가능한 폴더 목록을 지정하게 되어 있는데 external-files-path이외에 아래와 같이 추가로 지정할 수 있다.
files-path | Context.getFilesDir()에 해당 |
cache-path | Context.getCacheDir()에 해당 |
external-path | Environment.getExternalStorageDirectory()에 해당 |
external-cache-path | Context.getExternalCacheDir()에 해당 |
external-media-path | Context.getExternalMediaDirs()에 해당 |