[Android] 안드로이드 웹뷰(WebView) 파일 다운로드

[Android] 안드로이드 웹뷰(WebView) 파일 다운로드

안드로이드 하이브리드 앱의 웹뷰(WebView) 안에서 파일 다운로드 URL을 호출했을 때 아무 반응이 없는 경우.

오류가 아니고 원래 안드로이드는 웹뷰에 DownloadListener를 구현해줘야만 파일 다운로드 가능하다.

해당 웹뷰를 사용하는 Activity(정확히 표현하면 Activity 클래스를 상속받은 특정 Activity) 의 onCreate 메서드 안에 다음과 같이 작성한다.

public class OOOActivity extends Activity {

    public Activity thisActivity = null;

    public WebView webView = null;

 

    (중략)

  

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        thisActivity = this;

        (중략)

        // 안드로이드 파일 다운로드 구현 (웹메일 첨부 다운로드)
        webView.setDownloadListener(new DownloadListener() {
            @Override
            public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
                try {
                    DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
                    DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);

                    contentDisposition = URLDecoder.decode(contentDisposition,”UTF-8″);

                    // 파일명 잘라내기

                    String fileName = contentDisposition;
                    if (fileName != null && fileName.length() > 0) {
                        int idxFileName = fileName.indexOf(“filename=”);
                        if (idxFileName > -1) {
                            fileName = fileName.substring(idxFileName + 9).trim();
                        }

                        if (fileName.endsWith(“;”)) {
                            fileName = fileName.substring(0, fileName.length() – 1);
                        }

                        if (fileName.startsWith(“\””) && fileName.startsWith(“\””)) {
                            fileName = fileName.substring(1, fileName.length() – 1);
                        }
                    }

                    // 세션 유지를 위해 쿠키 세팅하기
                    String cookie = CookieManager.getInstance().getCookie(url);
                    request.addRequestHeader(“Cookie”, cookie);

                    request.setMimeType(mimetype);
                    request.addRequestHeader(“User-Agent”, userAgent);
                    request.setDescription(“Downloading File”);
                    request.setAllowedOverMetered(true);
                    request.setAllowedOverRoaming(true);
                    request.setTitle(fileName);
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                        request.setRequiresCharging(false);
                    }

                    request.allowScanningByMediaScanner();
                    request.setAllowedOverMetered(true);
                    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
                    request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);

                    dm.enqueue(request);
                    Toast.makeText(getApplicationContext(),”파일을 다운로드 합니다.”, Toast.LENGTH_LONG).show();
                }
                catch (Exception e) {
                    if (ContextCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                        if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                            Toast.makeText(getBaseContext(), “파일 다운로드 권한을 허용해주십시오.”, Toast.LENGTH_LONG).show();
                            ActivityCompat.requestPermissions(thisActivity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1004);
                        }
                        else {
                            Toast.makeText(getBaseContext(), “파일 다운로드 권한을 허용해주십시오.”, Toast.LENGTH_LONG).show();
                            ActivityCompat.requestPermissions(thisActivity, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1004);
                        }
                    }
                }
            }
        });

(후략)

이어서 AndroidManifest.xml 에 다음과 같이 권한 코드를 넣는다.

    <!– 파일 다운로드 권한 –>
    <uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE” />
    <uses-permission android:name=”android.permission.READ_EXTERNAL_STORAGE” />

파일 다운로드가 수행되지 않는 경우가 발견되어 내용을 추가한다. URL이 파일명으로 끝나지 않는 경우에만 그랬다. 처음엔 https 문제인 것으로 판단했는데, 드랍박스에 파일을 업로드해서 테스트 해본 결과 https 도 잘 동작했다.

확인해보니 파일 다운로드 앞단에서 세션을 체크하는 경우였다. 파일 다운로드가 정상적으로 수행되는 것처럼 보이지만 용량이 3.28kb 로 나오는 등 턱없이 작았다.

아래 코드를 추가하자 해결됐다.

// 세션 유지를 위해 쿠키 세팅하기
String cookie = CookieManager.getInstance().getCookie(url);
request.addRequestHeader(“Cookie”, cookie);

참고사이트 1 : https://onedaycodeing.tistory.com/71

참고사이트 2 : https://stackoverrun.com/ko/q/4885896