\ [Java][Android]webview 파일 다운로드한 후 파일 열기 :: Something New
728x90
반응형

저는 하이브리드 어플을 개발하고 있구요 webview에서 파일 다운로드하고 파일 열기까지 

제가 하는 환경에서 web에서 다운로드매니저로 다운받을때 url에 서버파일의 path가 담겨있지 않아서

웹.서블렛 수정까지 같이 하느라 시간이 많이 걸렸습니다만

여러분의 url에는 파일명과 파일path가 담겨있을거라 생각하고 

파일 다운로드와 intent로 파일열기 검색한대로 했는데 왜 자꾸 커미션 넣으라고만 하냐구요ㅠㅠ

전 커미션 당연히 설정한 상태였습니다.

중요한건 파일명이 url이나 base64로 인코딩된 상태이면 디코딩이 필요할 수 있구요

저는 내부저장소에 개별어플파일안 \내장 저장공간\Android\data\어플이름\files\download에 저장했습니다.

\내장 저장공간\Download에 저장하고 싶으시다면 request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, mFileName); 

로 바꿔 써주시면 됩니다.

onCreate()안에 여러 웹뷰 세팅하시고 밑의 코드를 넣어주시면 됩니다.

    newWebView.setDownloadListener(new DownloadListener() {

                @Override
                public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {
                    try {
                        DownloadManager dm = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
                        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
                        DownloadManager.Query query = new DownloadManager.Query();

                        request.setMimeType(mimeType);
                        String cookies = CookieManager.getInstance().getCookie(url);
                        request.addRequestHeader("cookie", cookies);
                        request.addRequestHeader("User-Agent", userAgent);
                        request.addRequestHeader("Referer", getReferrer().getAuthority());
                        request.addRequestHeader("Content-Disposition", contentDisposition);
                        request.setDescription("Downloading file...");
                        String content = contentDisposition;
                        String[] contentSplit = content.split(content);

                        mFileName = content.replace("attachment; filename=", "").trim();
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                            mFileName = URLDecoder.decode( mFileName, UTF_8);
                        }

                        request.setTitle(mFileName);
                        request.allowScanningByMediaScanner();
                        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
                        //다운받아서 넣을 파일의 디렉토리 지정해 주세요
                        //request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, mFileName); 
                        request.setDestinationInExternalFilesDir(getApplicationContext(),DIRECTORY_DOWNLOADS, mFileName);
                
                        request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);

                         dm.enqueue(request);
                       Toast.makeText(getApplicationContext(), "Downloading File", Toast.LENGTH_LONG).show();

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

 

여기까지하시면 다운로드가 됩니다.

다운로드 후에 바로 다운로드한 파일을 열고 싶을 때 밑에 소스를 추가해 주세요

 private final BroadcastReceiver mCompleteReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (ActivityCompat.checkSelfPermission(MainActivity.this,
                        Manifest.permission.WRITE_EXTERNAL_STORAGE) !=
                        PackageManager.PERMISSION_GRANTED) {

                    //권한 허가
                    ActivityCompat.requestPermissions(MainActivity.this,
                            new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},1000);
                }
                //파일 다운로드가 완료되었을 때
                if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
                    Toast.makeText(context, "Complete.", Toast.LENGTH_SHORT).show();
                    long downloadId = intent.getLongExtra(
                            DownloadManager.EXTRA_DOWNLOAD_ID, 0);
                    openDownloadedAttachment(context, downloadId);
                }
            }
        };

여기까지는 흔하게 파일 완료 액션을 잡아서 어찌저찌 했습니다만 중요한건 여기부터 입니다

  private void openDownloadedAttachment(final Context context, final long downloadId) {
            DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
            DownloadManager.Query query = new DownloadManager.Query();
            query.setFilterById(downloadId);
            Cursor cursor = downloadManager.query(query);
            //다운로드한 정보를 꺼내서
            if (cursor.moveToFirst()) {
                @SuppressLint("Range") int downloadStatus = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
                @SuppressLint("Range") String downloadLocalUri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                @SuppressLint("Range") String downloadMimeType = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_MEDIA_TYPE));
                if ((downloadStatus == DownloadManager.STATUS_SUCCESSFUL) && downloadLocalUri != null) {
                    openDownloadedAttachment(context, Uri.parse(downloadLocalUri), downloadMimeType);
                    mUri = String.valueOf(Uri.parse(downloadLocalUri));
                }
            }
            cursor.close();
        }
        

		//fileprovider로 열기
        private void openDownloadedAttachment(final Context context, Uri attachmentUri, final String attachmentMimeType) {
            if(attachmentUri!=null) {
                // Get Content Uri.
                if (ContentResolver.SCHEME_FILE.equals(attachmentUri.getScheme())) {
                    // FileUri - Convert it to contentUri.
                    File file = new File(attachmentUri.getPath());
                    attachmentUri = FileProvider.getUriForFile(getApplicationContext(), getApplicationContext()
                            .getPackageName()+".provider", file);
                }

                Intent openAttachmentIntent = new Intent(Intent.ACTION_VIEW);
                openAttachmentIntent.setDataAndType(attachmentUri, attachmentMimeType);
                openAttachmentIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                try {
                    context.startActivity(openAttachmentIntent);
                } catch (ActivityNotFoundException e) {
                    Toast.makeText(context, "error", Toast.LENGTH_LONG).show();
                }
            }
        }

 

예전에는  file:/// 형태의 uri 로 가능했다고 하는데

이젠 content://로 바뀌어야해서 fileprovider를 사용해줍니다. 

저는 이 방법을 통해 파일 다운로드 후 pdf파일 열기까지 성공했습니다

hakusyu위스키 공장에서 시음

 

728x90

+ Recent posts