본문 바로가기

android/Process

[ Android ] sdcard 폴더 내 앱 데이터를 다른 앱에 제공하기

반응형

FileProvider는 Android에서 앱 간에 파일을 안전하게 공유할 수 있도록 도와주는 클래스로, 특히 Android 7.0(API 레벨 24)부터 도입된 "파일 URI 노출(File URI Exposure)" 문제를 해결하기 위해 사용됩니다. FileProvider를 사용하면 content:// 스킴을 사용하는 URI를 생성하여 다른 앱에 파일을 안전하게 공유할 수 있습니다.

FileProvider 사용 방법

1. FileProvider 설정

먼저, FileProviderAndroidManifest.xml에 설정합니다. 이를 위해 <provider> 요소를 추가하고, FileProvider가 제공할 수 있는 파일 경로를 정의하는 XML 파일을 준비합니다.


<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="${applicationId}.provider"
    android:exported="false"
    android:grantUriPermissions="true" >
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>
  • android:name: androidx.core.content.FileProvider를 지정하여 기본 제공 FileProvider 클래스를 사용합니다.
  • android:authorities: 고유한 권한(authority)을 지정합니다. 일반적으로 ${applicationId}.fileprovider 형식으로 설정합니다.
  • android:exported: false로 설정하여 다른 앱이 직접 이 FileProvider에 접근하지 못하게 합니다.
  • android:grantUriPermissions: true로 설정하여 다른 앱에 URI 권한을 부여할 수 있도록 합니다.
  • @xml/file_paths: 파일 경로를 지정하는 XML 리소스 파일을 참조합니다.

2. 파일 경로 정의

res/xml/file_paths.xml 파일을 생성하고, FileProvider가 접근할 수 있는 디렉토리와 파일을 정의합니다.


<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="sdcard" path="."/>
</paths>
  • external-path: 외부 저장소의 경로를 지정합니다 (예: SD 카드).
  • files-path: 앱의 내부 저장소에서의 파일 경로를 지정합니다 (/data/data/<package-name>/files).
  • cache-path: 앱의 캐시 디렉토리 경로를 지정합니다 (/data/data/<package-name>/cache).
  • external-cache-path: 외부 캐시 디렉토리 경로를 지정합니다 (/sdcard/Android/data/<package-name>/cache).

3. 파일 공유 URI 생성

이제 파일의 URI를 생성하여 다른 앱에 파일을 공유할 수 있습니다. FileProvider.getUriForFile() 메서드를 사용하여 URI를 생성합니다.


Uri uriFile = FileProvider.getUriForFile(MainActivity.this,
    getApplicationContext().getPackageName() + ".provider",
    new File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS) .getAbsolutePath() + "/myfile.txt;
  • this: 컨텍스트입니다.
  • "com.example.myapp.fileprovider": FileProvider의 권한(authority)을 지정합니다. AndroidManifest.xml에서 설정한 값과 일치해야 합니다.
  • file: 공유할 파일 객체입니다.

4. Intent를 사용하여 파일 공유

생성된 URI를 사용하여 다른 앱과 파일을 공유할 수 있습니다. 예를 들어, 이메일을 통해 파일을 공유하거나, 이미지를 다른 앱에서 열 수 있습니다.


    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setDataAndType(uriFile, "*/*");
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    startActivity(intent);
  • Intent.FLAG_GRANT_READ_URI_PERMISSION: URI에 대해 읽기 권한을 일시적으로 부여합니다. 지젇하지 않으면 SecurityException이 발생합니다.
  • Intent.ACTION_VIEW: 파일을 처리하는 액션을 지정합니다. 처리하고자 하는 앱의 Intent-filter 등록 필요합니다.
  • setType: 공유할 파일의 MIME 타입을 설정합니다.

5. FileProvider를 통해서 파일 제공 받는 앱 설정


        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <category android:name="android.intent.category.OPENABLE"/>
                <data android:scheme="content"/>
                <data android:scheme="file"/>
                <data android:host="*"/>
                <data android:mimeType="*/*"/>
                <data android:pathPattern=".*\\.txt"/>
                <data android:pathPattern=".*\\..*\\.txt"/>
                <data android:pathPattern=".*\\..*\\..*\\.txt"/>
                <data android:pathPattern=".*\\..*\\..*\\..*\\.txt"/>
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.txt"/>
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.txt"/>
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.txt"/>
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.txt"/>
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.txt"/>
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.txt"/>
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.txt"/>
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.txt"/>
            </intent-filter>

        </activity>

        Intent intent = getIntent();
        if (intent != null) {
            Uri uri = getIntent().getData();
            if (uri != null) {
                Log.d(TAG, "uri.getPath():" + uri.getPath());
                mPathFile = new String(uri.getPath());
                mFile = new File(uri.getPath());
                Log.d(TAG, "file.exists(): " + mFile.exists());

            }
        }

중요한 점

  • 보안: FileProvider를 통해 생성된 URI는 안전하게 관리되어야 합니다. URI를 통해 접근 가능한 파일이 외부 앱에 의해 잘못 사용되지 않도록 주의해야 합니다.
  • URI 권한: URI 권한은 일시적이며, 일반적으로 Intent를 통해 파일을 공유할 때만 유효합니다. Intent.FLAG_GRANT_READ_URI_PERMISSION 플래그를 사용하여 다른 앱이 파일을 읽을 수 있도록 권한을 부여할 수 있습니다.
  • 파일 URI 노출 문제 해결: Android 7.0(API 레벨 24) 이상에서는 file:// URI를 통해 파일을 공유할 수 없으므로, FileProvider를 사용하여 content:// URI로 변환하는 것이 필수적입니다.

이렇게 FileProvider를 설정하고 사용하는 방법을 통해, 앱 간에 파일을 안전하게 공유할 수 있습니다.

반응형