이번 포스팅은 FileProvider를 사용하여 파일 공유하는 방법에 대하여 알아보도록 하겠습니다.
1. FileProvider 란
ContentProvider는 데이터를 캡슐화하여 다른 응용 프로그램에 제공하는 Android 구성 요소입니다. 여러 응용 프로그램간에 데이터를 공유해야하는 경우에만 필요합니다. 예를 들어 연락처 데이터는 ContentProvider의 하위 클래스 인 ContactsProvider를 사용하여 다른 응용 프로그램과 공유됩니다.
FileProvider는 ContentProvider의 하위 클래스입니다. ContentProvider는 모든 종류의 데이터를 안전하게 공유 할 수있는 구성 요소이지만 FileProvider는 특히 앱의 내부 파일을 공유하는 데 사용됩니다. FileProvider 클래스는 v4 지원 라이브러리의 일부이므로 프로젝트에 포함시켜야합니다.
FileProvider가 작동하도록하려면 다음 세 단계를 수행하십시오.
▶ AndroidManifest 파일에서 FileProvider 정의
▶ FileProvider가 다른 응용 프로그램과 공유 할 모든 경로가 포함 된 XML 파일을 만듭니다.
▶ Intent에 유효한 URI를 번들로 묶어 활성화
2. FileProvider 정의
AndroidManifest 내에서 FileProvider를 정의하려면 다음 속성 및 요소에 익숙해야합니다.
▶ android : authorities
▶ android : exported
▶ android : grantUriPermissions
▶ android : name
▶ <meta-data> subelement
이들 모두가 매우 친숙해 보인다면 FileProvider를 둘러 보는 방법이 약간 쉬울 것입니다. 그렇지 않으면 각 속성과 그 목적에 대한 자세한 설명을 준비했습니다.
android : authorities
적어도 하나의 고유 권한을 반드시 정의합니다. Android 시스템은 모든 제공자의 목록을 유지하며 권한별로 이를 구분합니다. 권한은 애플리케이션 ID가 Android 애플리케이션을 정의하는 것처럼 FileProvider를 정의합니다.
일반적으로 Android 시스템은 ContentProviders에 특정 URI 체계를 사용합니다. 체계는 content : // <authority> / <path>로 정의 되므로 시스템은 URI의 권한을 ContentProvider의 권한과 일치시켜 어떤 ContentProvider가 요청되는지 알 수 있습니다.
android : exported
이 속성은 이름이 잘못되어 쉽게 오용 될 수 있습니다. 이 속성을 이해하려면 FileProvider를 door가 잠긴 방으로 생각하십시오. 값을 true로 설정하면 기본적으로 모든 사람에게 문이 열립니다. 모든 것이 귀하의 관점에서 작동하지만 다른 모든 앱이 권한을 부여받지 않고 FileProvider를 사용할 수 있기 때문에 방금 큰 보안 문제가 발생했습니다.
이를 통해 우연의 일치로 프로그램하지 말고 항상 코드의 부작용을 인식 할 수 있습니다. 또한 SDK 16 이하의 기본값이 true 이므로 항상이 속성을 정의하십시오 .
android : grantUriPermissions
FileProvider를 잠긴 방으로 계속 생각하면이 속성은 외부 앱에 임시 일회성 키를 제공하는 데 사용됩니다. 이 속성을 사용하면 앱의 내부 저장소를 안전하게 공유 할 수 있습니다. FLAG_GRANT_READ_URI_PERMISSION 또는 FLAG_GRANT_WRITE_URI_PERMISSION을 구성 요소를 활성화하여 앱의 내부 파일을 여는 의도에 추가하기 만하면됩니다. 이 플래그를 사용하려면 해당 값을 true로 설정하십시오 .
<provider> 요소는 <grant-uri-permission> 하위 요소도 가질 수 있습니다. 유일한 차이점은이 속성을 사용하면 앱의 내부 저장소 내에서 무엇이든 공유 할 수 있고 하위 요소를 사용하면 공유 할 특정 데이터 하위 집합을 선택할 수 있다는 것입니다. 하위 요소를 대신 사용하려면 값을 false로 설정하십시오 .
<메타 데이터> 하위 요소
FileProvider를 사용할 때이 하위 요소를 정의해야합니다. FileProvider가 외부 앱과 공유 할 수있는 모든 데이터 경로가 포함 된 XML 파일의 경로를 정의해야합니다.
XML 파일에는 루트로 <paths> 요소가 있어야합니다. <paths> 요소에는 다음 중 하나 일 수있는 하나 이상의 하위 요소가 있어야합니다.
<files-path />-내부 앱 스토리지, Context # getFilesDir ()
<cache-path />-내부 앱 캐시 스토리지, Context # getCacheDir ()
<external-path />-공용 외부 저장소, Environment.getExternalStorageDirectory ()
<external-files-path />-외부 앱 스토리지, 컨텍스트 #getExternalFilesDir (null)
<external-cache-path />-외부 앱 캐시 스토리지, 컨텍스트 #getExternalCacheDir ()
그것들은 그들이 정의한 앱의 디렉토리에 따라 다르다는 것을 알았을 것입니다.
각 요소에는 경로와 이름 속성이 있어야합니다. path 속성은 공유하려는 서브 디렉토리를 정의하며 와일드 카드를 지원 하지 않습니다 . name 속성은 보안상의 이유로 사용되며 하위 디렉토리 이름을 해당 값으로 대체합니다.
안드로이드 : 이름
이 값을 android.support.v4.content.FileProvider로 설정했습니다 .
AndroidManifest 파일에 FileProvider를 정의하면 사용할 준비가 된 것입니다. 파일을 공유하려면 인 텐트를 작성하고 유효한 URI를 제공해야합니다. URI는 FileProvider 클래스를 사용하여 생성됩니다.
코드 구현
AndroidManifest.xml
<provider
android:name="android.support.v4.content.FileProvider"
android:grantUriPermissions="true"
android:exported="false"
android:authorities="${applicationId}">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_paths"/>
</provider>
권한을 위해 앱 ID를 사용하고 있습니다. 프로젝트에 여러 가지 특징이 있으며 동시에 장치에 설치할 수 있기 때문입니다. Android 시스템에서는 동일한 FileProvider로 여러 응용 프로그램을 설치할 수 없으므로 각 기능마다 고유 한 권한이 필요합니다.
file_provider_paths.xml
<paths>
<cache-path name="cache" path="/" />
<files-path name=”files” path=”/” />
</paths>
이와 같은 경로를 정의함으로써 FileProvider가 앱의 내부 캐시 및 파일 디렉토리에있는 모든 파일을 공유 할 수 있습니다.
FileProvider 사용
// create new Intent
Intent intent = new Intent(Intent.ACTION_VIEW);
// set flag to give temporary permission to external app to use your FileProvider
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// generate URI, I defined authority as the application ID in the Manifest, the last param is file I want to open
String uri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID, file);
// I am opening a PDF file so I give it a valid MIME type
intent.setDataAndType(uri, "application/pdf");
// validate that the device can open your File!
PackageManager pm = getActivity().getPackageManager();
if (intent.resolveActivity(pm) != null) {
startActivity(intent);
}
작동 방식을 이해하면 고유 한 FileProvider를 구현하는 것이 매우 간단합니다.
문제의 복잡성은 코드 자체가 아니라 모든 것이 상호 연결되는 방법에 대한 문서와 이해입니다. 이 기사가 자신의 유스 케이스에 FileProvider를 구현하고 공식 문서를 읽기 쉽게 만드는 데 도움이되기를 바랍니다.
https://infinum.co/the-capsized-eight/share-files-using-fileprovider
'Development > Android' 카테고리의 다른 글
[Android] Fragment의 개요 (0) | 2019.09.06 |
---|---|
[Android] Button의 배경을 투명하게 하는 방법 (0) | 2019.09.05 |
[Android] Pie (Android OS 9) 동적 변경 사항 (0) | 2019.08.17 |
[Android] AndroidX 개요 (0) | 2019.01.31 |
[Android] Android Pie의 향상된 생체 인식 (0) | 2019.01.31 |