Android

[안드로이드] 저장소 파일 처리 FileProvider를 사용한 Context.getDir() 사용시 IllegalArgumentException: Failed to find configured root that contains /data/data/ 오류 처리 방법

안드로이드 앱 내부 저장소에 디렉토리 자동 생성 및 파일 쓰기를 위해서 ContextWrapper 클래스를 사용하여 초기화 후 getDir(name, mode)메소드를 사용하여 파일쓰기를 하였다. getDir()메소드는 앱의 고유한 파일 시스템 디렉토리 내에 새 디렉토리를 생성한다. 존재한다면 기존 디렉토리를 열어서 파일을 생성할 수 있다. 디렉토리를 별도로 생성하는 과정을 줄일 수 있어서 사용해왔는데 문제가 발생되었다. 공유하려고 보니 해당 파일의 경로를 찾지 못하는  java.lang.IllegalArgumentException: Failed to find configured root that contains /data/data/ 오류가 발생하였다.

String filename = getFileName();

ContextWrapper cw = new ContextWrapper(PreviewActivity.this);

File directory = cw.getDir("g_pdf", Context.MODE_PRIVATE);  

final File mypath = new File(directory,filename);
shareFile = mypath;
FileOutputStream fos = null;
try {
	fos = new FileOutputStream(mypath);
	createPDF(fos);
	Log.d("TAG", "==================  PDF  : " + mypath.getPath());
} catch (Exception e) {
	e.printStackTrace(); 
} finally {
	try {
		if(fos!=null)
			fos.close();
	} catch (IOException e) {
		e.printStackTrace();
	}
}

 

다음 메소드를 사용하여 파일을 생성할 경우 앱 사용자에게 저장소 권한을 요청할 필요가 없다.

메소드 설명
getDir(name, mode) 앱의 고유한 파일 시스템 디렉터리 내에 새 디렉터리를 생성 또는 기존 디렉터리에 파일을 쓴다.
getCacheDir() 앱과 고유하게 연결된 파일 시스템의 캐시 디렉터리에 파일을 쓴다.
getFilesDir() 앱과 고유하게 연결된 파일 시스템의 디렉터리에 파일을 쓴다.


AndroidManifest.xml

<provider
	android:name="androidx.core.content.FileProvider"
	android:authorities="ddolcat.app.tools.test.provider"
	android:exported="false"
	android:grantUriPermissions="true">
	<meta-data
		android:name="android.support.FILE_PROVIDER_PATHS"
		android:resource="@xml/fileprovider" />
</provider>

@xml/fileprovider.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <cache-path
        name="cache"
        path="." /> <!--Context.getCacheDir() 내부 저장소-->
    <files-path
        name="files"
        path="." /> <!--Context.getFilesDir() 내부 저장소-->
 
    <external-path
        name="external"
        path="."/>  <!--  Environment.getExternalStorageDirectory() 외부 저장소-->
    <external-cache-path
        name="external-cache"
        path="."/> <!--  Context.getExternalCacheDir() 외부 저장소-->
    <external-files-path
        name="external-files"
        path="."/> <!--  Context.getExternalFilesDir() 외부 저장소-->

    <files-path name="app_g_pdf" path="." />
</paths>    

 

생성한 PDF파일을 공유하기 위한 코드 스니펫은 다음과 같다. Intent를 생성할때 반드시 Intent.FLAG_GRANT_READ_URI_PERMISSION 플래그를 추가해주어야한다. 그렇지 않으며 공유 프로그램 호출하는 과정에 오류가 발생하기 때문이다.

if (shareFile!=null && shareFile.exists()) {
	File cacheFile = shareFile;
	Uri uri = FileProvider.getUriForFile(PreviewActivity.this, "ddolcat.app.tools.test.provider", cacheFile); 

	Intent intent = ShareCompat.IntentBuilder.from(PreviewActivity.this)
			.setType("application/pdf")
			.setStream(uri)
			.createChooserIntent()
			.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

	List<ResolveInfo> resInfoList = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
	for (ResolveInfo resolveInfo : resInfoList) {
		String packageName = resolveInfo.activityInfo.packageName;
		getApplicationContext().grantUriPermission(packageName, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
	} 
	startActivity(intent);
}

} catch (Exception e) {
	e.printStackTrace(); 
}

 

발생 오류 java.lang.IllegalArgumentException: Failed to find configured root that contains /data/data/…………..

2021-02-18 19:47:07.471 21386-21386/ddolcat.app.tools.test D/TAG: ====  PDF  : /data/user/0/ddolcat.app.tools.test/app_g_pdf/pdf_code_194706.pdf
  21386-21386/ddolcat.app.tools.test W/System.err: java.lang.IllegalArgumentException: Failed to find configured root that contains /data/data/ddolcat.app.tools.test/app_g_pdf/pdf_code_194706.pdf
  21386-21386/ddolcat.app.tools.test W/System.err:     at androidx.core.content.FileProvider$SimplePathStrategy.getUriForFile(FileProvider.java:744)
  21386-21386/ddolcat.app.tools.test W/System.err:     at androidx.core.content.FileProvider.getUriForFile(FileProvider.java:418)
  21386-21386/ddolcat.app.tools.test W/System.err:     at ddolcat.app.tools.test.PreviewActivity.sharePDFContents(PreviewActivity.java:151)
  21386-21386/ddolcat.app.tools.test W/System.err:     at ddolcat.app.tools.test.PreviewActivity.printPDF(PreviewActivity.java:339)
  21386-21386/ddolcat.app.tools.test W/System.err:     at ddolcat.app.tools.test.PreviewActivity$1.onClick(PreviewActivity.java:117)
  21386-21386/ddolcat.app.tools.test W/System.err:     at android.view.View.performClick(View.java:7169)
  21386-21386/ddolcat.app.tools.test W/System.err:     at android.view.View.performClickInternal(View.java:7139)
  21386-21386/ddolcat.app.tools.test W/System.err:     at android.view.View.access$3900(View.java:808)
  21386-21386/ddolcat.app.tools.test W/System.err:     at android.view.View$PerformClick.run(View.java:27481)
  21386-21386/ddolcat.app.tools.test W/System.err:     at android.os.Handler.handleCallback(Handler.java:883)
  21386-21386/ddolcat.app.tools.test W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:100)
  21386-21386/ddolcat.app.tools.test W/System.err:     at android.os.Looper.loop(Looper.java:214)
 21386-21386/ddolcat.app.tools.test W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:7615)
21386-21386/ddolcat.app.tools.test W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
21386-21386/ddolcat.app.tools.test W/System.err:     at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
21386-21386/ddolcat.app.tools.test W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:964)

 

파일생성시 cw.getDir(“g_pdf”, Context.MODE_PRIVATE); 로 접근했기 때문에  폴더는  app_(고정) 그 뒤에 g_pdf(개발자 정의 디렉토리)이름이 붙은 후 생성된다.  그런까닥에 오류 해결을 위해 @xml/fileprovider.xml에 아래와 같은 file경로를 추가해주고 다시 시도해보았으나 여전히 동일한 오류가 발생하였다. 해결법이 아닌 것이다.

<files-path name="app_g_pdf" path="." />


 

오류 해결방법

파일 생성시 getDir()메소드 대신 getFilesDir()메소드를 사용하여 처리하면 해결할 수 있으며 파일프로바이더(FileProvider)가 접근할 수 있도록@xml/fileprovider.xml에 files-path는 이미 추가해 준 상태이다.

 File directory = cw.getFilesDir();
    <files-path
        name="files"
        path="." /> <!--Context.getFilesDir() 내부 저장소-->

 

또 다른 오류 해결방법

@xml/fileprovider.xml에 root-path를 추가해 주면 접근이 가능해진다. 그러나 위의 방법을 권장한다.  루트 경로를 추가했을 때 액세스 권한이 있다면  모든 파일에 접근이 가능해지기 때문이다.

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

 

REFERENCE

stackoverflow.com/questions/42516126/fileprovider-illegalargumentexception-failed-to-find-configured-root

stackoverflow.com/questions/31345275/android-fileprovider-illegalargumentexception-failed-to-find-configured-root-th

 

Leave a Reply

error: Content is protected !!