Android

[Android] FileProvider ๋‹ค๋ฅธ ์•ฑ์œผ๋กœ ํŒŒ์ผ ์ „๋‹ฌ ์˜ˆ์ œ

devSunny99 2022. 11. 9. 16:30

๐Ÿ“Œ๊ฐœ์š”

  • Android7(=sdk24)์ด์ƒ๋ถ€ํ„ฐ File:// ํ˜•์‹์˜ File uri๋ฅผ ๋„˜๊ฒจ์ฃผ๋ฉด ์•ˆ๋˜๋ฉฐ FileProvider๋ฅผ ํ†ตํ•˜์—ฌ ๋„˜๊ฒจ์ฃผ๋„๋ก ๋ฐ”๋€Œ์—ˆ์Œ
  • ์ฆ‰, ์ผ๋ฐ˜์ ์œผ๋กœ ํŒŒ์ผ์„ ๋‹ค๋ฅธ ์•ฑ์ด๋‚˜ ๋‹ค๋ฅธ ์•กํ‹ฐ๋น„ํ‹ฐ๋กœ ๋„˜๊ฒจ์ค„ ๊ฒฝ์šฐ, ๋‹ค์Œ๊ณผ ๊ฐ™์ด Uri.fromFile์„ intent์— ๋„ฃ์–ด ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ์—ˆ์Œ
intent.setDataAndType(Uri.fromFile(new File(filePath)), getFileMimeType(filePath));
  • ํ•˜์ง€๋งŒ Android7์ด์ƒ ๋ถ€ํ„ฐ๋Š” ํ•ด๋‹น ๋กœ์ง์„ ํƒ€๊ฒŒ๋˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ exception์„ ๋งž์ดํ•˜๊ฒŒ ๋  ๊ฒƒ์ž„!!
android.os.FileUriExposedException: file:///storage/emulated/0/Download/test.xlsx exposed beyond app through Intent.getData()

 

๐Ÿ“ŒFileProvider ์‚ฌ์šฉ๋ฒ•

โœ”ํŒŒ์ผ์„ ์ „๋‹ฌํ•˜๋Š” "์ฃผ์ฒด" ์•ฑ์˜ AndroidManifest.xml <application> </application> ์•ˆ์— ์•„๋ž˜ ๋‚ด์šฉ์„ ๋„ฃ์ž

<provider
	android:authorities="${applicationId}.FileProvider"
	android:name="androidx.core.content.FileProvider"
	android:exported="false"
	android:grantUriPermissions="true">
   <meta-data
   		android:name="android.support.FILE_PROVIDER_PATHS"
		android:resource="@xml/file_path"/>
</provider>
  • android:authorities๋Š” ํŒŒ์ผ ์ œ๊ณต์ž๊ฐ€ ๋ˆ„๊ตฌ๋ƒ๋ผ๋Š” ์˜๋ฏธ๋กœ ๋ณด๋ฉด ๋  ๊ฒƒ์ž„
  • ์ผ๋ฐ˜์ ์œผ๋กœ ๋ณธ์ธ App์ด ํŒŒ์ผ์ œ๊ณต์ž ์ผ ํ…Œ๋‹ˆ ${applicationId}.FileProvider๋กœ ์„ธํŒ…ํ•˜์ž!!
  • ${applicationId} ๋Š” build.gradle์˜ defaultConfig์— ์„ค์ •ํ•œ applicationId๋ฅผ ์˜๋ฏธํ•จ

โœ”res/xml/file_path.xml ์ถ”๊ฐ€ ํ›„ ์•„๋ž˜ ๋‚ด์šฉ์„ ๋„ฃ์ž

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="Download" path="."/>
</paths>
  • ๋‚˜๋Š” external-path๋กœ ์ง€์ •ํ•˜์˜€๊ณ , ๋‚ด App์—์„œ ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ ๋‹ค์šด๋กœ๋“œ ๊ฒฝ๋กœ์˜ ํŒŒ์ผ์„ ๋ณด๋‚ด๊ธฐ ์œ„ํ•ด์„œ์˜€๋‹ค!
  • ํ˜ธ์ถœ๋‹นํ•˜๋Š” ๋‚˜์˜ ๋‹ค๋ฅธ App์ด ๋ชจ๋“ ํŒŒ์ผ์— ๋Œ€ํ•œ ๊ฒฝ๋กœ ์ ‘๊ทผ์ด ํ—ˆ์šฉ๋˜์–ด์žˆ์–ด ์ž˜ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ ๊ฐ™๊ณ , ์ผ๋ฐ˜์ ์œผ๋กœ ๋‚ด๋ถ€๊ฒฝ๋กœ์— ์žˆ๋Š” ํŒŒ์ผ์„ ๋‹ค๋ฅธ ํŒŒ์ผ์•ฑ์œผ๋กœ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์„ ๊ฒƒ์ด๋‹ค.
  • ๋‹ค์šด๋กœ๋“œ ๊ฒฝ๋กœ(์™ธ๋ถ€๊ฒฝ๋กœ) ๋ง๊ณ  ๋‹ค๋ฅธ ๊ฒฝ๋กœ๋Š” ์•„๋ž˜ ๋‚ด์šฉ์„ ์ฐธ๊ณ ํ•˜์—ฌ file_path.xml์— ๋„ฃ์ž
*Cache ๊ฒฝ๋กœ
<cache-path name="name" path="path" />
์˜๋ฏธ: getCacheDir()
------------------------------------------------------
*์™ธ๋ถ€ ๊ฒฝ๋กœ
<external-path name="name" path="path" />
์˜๋ฏธ: Environment.getExternalStorageDirectory()
------------------------------------------------------
*์™ธ๋ถ€ Cache ๊ฒฝ๋กœ
<external-cache-path name="name" path="path" />
์˜๋ฏธ: Context.getExternalCacheDir().
------------------------------------------------------
*์™ธ๋ถ€ ๋ฏธ๋””์–ด ๊ฒฝ๋กœ
<external-media-path name="name" path="path" />
์˜๋ฏธ: Context.getExternalMediaDirs().

โœ”FileProvider ๊ตฌํ˜„

private void openFileOtherApp(String filePath) {
        if (Build.VERSION.SDK_INT < 24) { //์•ˆ๋“œ๋กœ์ด๋“œ7.0 = API 24
            return;
        }
        File file = new File(filePath);
        Uri uri = FileProvider.getUriForFile(context, getApplicationContext().getPackageName() + ".FileProvider", file);

        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_VIEW);
        intent.setDataAndType(uri, getFileMimeType(filePath));
        intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION |Intent.FLAG_GRANT_WRITE_URI_PERMISSION| Intent.FLAG_ACTIVITY_NEW_TASK);

        boolean test3 = new File(filePath).exists(); //ํ•ด๋‹น๊ฒฝ๋กœ ํŒŒ์ผ์กด์žฌ์—ฌ๋ถ€ test์šฉ
        Uri test = intent.getData(); //test์šฉ
        try {
            context.startActivity(intent);
        } catch (ActivityNotFoundException e) {
            e.printStackTrace();
        }
 }
  • mimeType๊ตฌํ•˜๊ธฐ ์œ„ํ•œ getFileMimeType()ํ•จ์ˆ˜๋Š” ๋งํฌ ์ฐธ๊ณ  ๐Ÿ‘‰ https://sunny-develop.tistory.com/12
  • Uri uri = FileProvider.getUriForFile(context, getApplicationContext().getPackageName() + ".FileProvider", file);          ์ด ๋ถ€๋ถ„์ด FileProvider์˜ ํ•ต์‹ฌ

  • content://com.*****/Download/Download/100k%20(1).xlsx๋ฅผ ๋ณด๋ฉด Download/Download/๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๊ฒƒ์€ ์œ—๋‹จ๊ณ„์—์„œ file_path.xml์„ค์ •ํ–ˆ๋˜ name์ด๋‹ค. ๋ณด์•ˆ์ƒ์œผ๋กœ ๋ณ„๋ช…๋А๋‚Œ์œผ๋กœ ํ•˜๋Š” ๊ฑฐ๋ผ๊ณ  ํ•œ๋‹ค!
  • ํŠน์ • ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ, ์œ„์˜ openFileOtherAppํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ™”๋ฉด์„ ๋ณผ ์ˆ˜ ์žˆ์Œ

 

์šฐ๋ฆฌ์•ฑ ๊ด€๋ จ ์ •๋ณด๋Š” ๋ชจ์ž์ดํฌ

 

  • ์œ„ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ํ˜ธ์ถœ ๋‹นํ•˜๋Š” App์€ intent-filter์— ACTION_VIEW๊ฐ€ ์„ค์ •๋˜์–ด์žˆ์–ด์•ผ ํ•จ
  • ์ง€๊ธˆ ์œ„์˜ ์ด๋ฏธ์ง€์— ์—ฐ๊ฒฐ ํ”„๋กœ๊ทธ๋žจ์— ๋œจ๋Š” ์•ฑ๋“ค์€ intent-filter์— ACTION_VIEW๊ฐ€ ์„ค์ •๋˜์–ด ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

 

โœ”๋ฒ„ํŠผ ํด๋ฆญ ์‹œ, ํŠน์ • ์•ฑ ๋ฐ”๋กœ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ๋ฒ•

.......
intent.setPackage("com.~~~ํŒจํ‚ค์ง€๋ช…!!");
context.startActivity(intent);

์œ„์™€ setPackage๋กœ ํŒจํ‚ค์ง€๋ช…(App id)์„ ์ง€์ •ํ•ด๋‘๋ฉด ์—ฐ๊ฒฐ ํ”„๋กœ๊ทธ๋žจ์„ ๋ฌป์ง€ ์•Š๊ณ  ๋ฐ”๋กœ ์—ฐ๋™ํ•ด์ค€๋‹ค!