2021. 4. 14. 16:11ㆍ모바일/Android_Java
pdf open with instantly(immediatly) close error + Failed to find configured root that contains /data~
pdf open 기존 방식
Intent intent = new Intent(android.content.Intent.ACTION_VIEW);
Uri path = Uri.fromFile(new File(FileUtil.makeDir(mFileDir) + mFileName));
// intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(path, "application/pdf");
if (canUseExternalMemory()) {
try {
//파일명이 Pdf라면 인텐트를 날린다.
if (FileUtil.getFileFind(mFileName).compareTo("pdf") == 0) {
// ((Activity) context).startActivity(intent);
((Activity) context).startActivityForResult(intent, 20201);
}
} catch (Exception e) {
//Exception 에러가 나면은 마켓에서 다운받을지 동의의사를 물어본다.
AlertUtil.Alert(context, "알림", "PDF뷰어 관련 어플리케이션이 없습니다. 마켓에서 PDF뷰어를 다운받으시겠습니까?",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
((Activity) context).startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(context.getResources().getString(R.string.config_ThinkFreeMarketUrl))));
}
});
}
}
public static String makeDir(String dir) {
String rootPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/" + dir;
try {
File file = new File(rootPath);
if (!file.exists()) {
if (!file.mkdirs()) {
}
}
} catch (Exception e) {
rootPath = "-1";
}
return rootPath + "/";
}
이렇게
Uri.fromFile(new File(FileUtil.makeDir(mFileDir) + mFileName));
코드로 임시 다운받은 pdf 를 열었더니 google pdf 뷰어 or 드라이브 pdf 는 바로 꺼지는 현상이 발생했다
원인은 아직 파악중이지만 FileProvider를 통해 해결했다.
수정(원인 - 추측)
파일 선택에 응답
사용자가 공유 파일을 선택하면 애플리케이션에서는 선택된 파일을 확인한 후 파일의 콘텐츠 URI를 생성해야 합니다. Activity는 사용 가능한 파일 목록을 ListView에 표시하므로 사용자가 파일 이름을 클릭하면 시스템에서는 onItemClick() 메서드를 호출합니다. 이를 통해 선택된 파일을 가져올 수 있습니다.
인텐트를 사용하여 한 앱에서 다른 앱으로 파일의 URI를 전송할 때 다른 앱에서 읽을 수 있는 URI를 가져오도록 주의해야 합니다. Android 6.0(API 수준 23) 이상을 실행 중인 기기에서 이렇게 하려면 특별한 주의가 필요합니다. 이 Android 버전의 권한 모델이 변경되어 특히 READ_EXTERNAL_STORAGE가 수신 앱에는 없을 수 있는 위험한 권한이 되기 때문입니다.
이러한 사항을 고려할 때 몇 가지 단점이 있는 Uri.fromFile()은 사용하지 않는 것이 좋습니다. 이 메서드의 특성은 다음과 같습니다.
프로필 간 파일 공유를 허용하지 않습니다.
Android 4.4(API 수준 19) 이하를 실행 중인 기기에서는 앱에 WRITE_EXTERNAL_STORAGE 권한이 있어야 합니다.
수신 앱에 READ_EXTERNAL_STORAGE 권한이 있어야 합니다. 이 권한은 이 권한이 없는 Gmail과 같은 중요 공유 타겟에서는 실패합니다.
Uri.fromFile()을 사용하는 대신 URI 권한을 사용하여 다른 앱에 특정 URI에 액세스할 수 있는 권한을 부여할 수 있습니다. URI 권한은 Uri.fromFile()에서 생성한 file:// URI에서는 작동하지 않지만 콘텐츠 제공업체에 연결된 URI에서는 작동합니다. FileProvider API는 이러한 URI를 만드는 데 도움이 될 수 있습니다. 또한 이 방법은 외부 저장소가 아니라 인텐트를 전송하는 앱의 로컬 저장소에 있는 파일에도 사용할 수 있습니
출처 : https://developer.android.com/training/secure-file-sharing/share-file?hl=ko
새로운 구현 방법
위에 코드를
Uri path = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID+".fileprovider",new File(FileUtil.makeDir(mFileDir) + mFileName));
로 변경하고 manifest.xml에 provider를 추가한다
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="kr.co.koreastock.mts.android.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
Drawable/xml에 file_paths.xml을 추가한다.
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<!-- <root-path-->
<!-- name="name"-->
<!-- path="."/>-->
<external-path
name="name"
path="."/>
</paths>
paths태그 안의 태그명은 아래와 같다
<files-path/>
-->Context.getFilesDir()
<cache-path/>
-->Context.getCacheDir()
<external-path/>
-->Environment.getExternalStorageDirectory()
<external-files-path/>
-->Context.getExternalFilesDir(String)
<external-cache-path/>
-->Context.getExternalCacheDir()
<external-media-path/>
-->Context.getExternalMediaDirs()
Failed to find configured root that contains /data~ 이 에러는 대신 태그로 선언했더니 발생했던 에러임
어떤 글에는 <root-path 태그로도 된다고 해서 해보니까 저것도 정상적으로 열린다.
참고) 파일 다운코드
DownloadFile down = new DownloadFile();
down.fileName(mFileName);
down.execute(mUrlName);
private class DownloadFile extends AsyncTask<String, Integer, String> {
private String fileName = "";
long total = 0;
public String fileName(String fileName) {
return this.fileName = fileName;
}
@Override
protected String doInBackground(String... paramUrl) {
HttpURLConnection conn = null;
try {
URL url = new URL(paramUrl[0]);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Language", "EUC-KR");
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.connect();
String filePath = FileUtil.makeDir(mFileDir);
File file = new File(filePath, fileName);
if (file.exists()) {
file.delete();
} else {
file.createNewFile();
}
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
OutputStream os = new FileOutputStream(file, false);
BufferedOutputStream bos = new BufferedOutputStream(os);
int tmp = 0;
int MAX_BUFFER_LENGTH = 5120;
byte data[] = new byte[MAX_BUFFER_LENGTH];
//progress
//그냥 의미없이 진행 상태 보여주기
int prog = 0;
// Log.e("bis.available()", String.valueOf(bis.available()));
while ((tmp = bis.read(data)) != -1) {
bos.write(data, 0, tmp);
total += tmp;
prog++;
publishProgress((int) ((prog % 2000) * 100 / 2000));
}
//100%
publishProgress(100);
bos.flush();
os.flush();
try {
bos.close();
} catch (Exception eee) {
}
try {
os.close();
} catch (Exception eee) {
}
try {
bis.close();
} catch (Exception eee) {
}
try {
is.close();
} catch (Exception eee) {
}
} catch (Exception e) {
if (mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
}
mHandler.sendEmptyMessage(NETWORKFAIL);
// Log.e("Exception", e.getMessage());
e.getStackTrace();
return "fail";
} finally {
if (conn != null) {
conn.disconnect();
}
}
return Integer.toString(DOWNLOADSUECCS);
}
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
public void onProgressUpdate(Integer... args) {
mProgressDialog.setProgress(args[0]);
}
/**
* 백그라운드 작업이 완료시 수행
*
* @param result
*/
@Override
protected void onPostExecute(String result) {
if (result.compareTo(Integer.toString(DOWNLOADSUECCS)) == 0) {
if (mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
}
mHandler.sendEmptyMessage(DOWNLOADSUECCS);
}
}
/**
* 비정상종료
*/
@Override
protected void onCancelled() {
super.onCancelled();
mProgressDialog.dismiss();
}
}
'모바일 > Android_Java' 카테고리의 다른 글
[Android] android weburl get paramater (0) | 2021.04.22 |
---|---|
[Android] ViewPager 내부 내용 높이에 따른 스크롤 설정하기 (0) | 2021.04.14 |
[Android] 스크롤 하면서 라디오버튼 체크 변경, 체크 클릭시 하면 해당 스크롤로 가기 (0) | 2021.04.13 |
[Android] ViewPager 화면에 보일 때 호출 (setUserVisibleHint함수, mIsVisibleToUser변수) (0) | 2021.04.01 |
[java] sns 형태 시간 (몇분전)으로 변경하기 (0) | 2021.03.26 |