1 // Copyright (c) 2013 Intel Corporation. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.xwalk.core.client;
7 import android.app.DownloadManager;
8 import android.app.DownloadManager.Request;
9 import android.content.pm.PackageManager;
10 import android.content.Context;
11 import android.net.Uri;
12 import android.os.AsyncTask;
13 import android.os.Environment;
14 import android.webkit.MimeTypeMap;
15 import android.webkit.URLUtil;
16 import android.widget.Toast;
17 import android.Manifest;
20 import java.io.FileOutputStream;
21 import java.io.InputStream;
22 import java.io.IOException;
23 import java.io.OutputStream;
25 import org.xwalk.core.AndroidProtocolHandler;
26 import org.xwalk.core.DownloadListener;
27 import org.xwalk.core.R;
29 public class XWalkDefaultDownloadListener implements DownloadListener {
30 private static String DOWNLOAD_START_TOAST;
31 private static String DOWNLOAD_NO_PERMISSION_TOAST;
32 private static String DOWNLOAD_ALREADY_EXISTS_TOAST;
33 private static String DOWNLOAD_FAILED_TOAST;
34 private static String DOWNLOAD_FINISHED_TOAST;
36 private Context mContext;
38 public XWalkDefaultDownloadListener(Context context) {
41 DOWNLOAD_START_TOAST = mContext.getString(R.string.download_start_toast);
42 DOWNLOAD_NO_PERMISSION_TOAST =
43 mContext.getString(R.string.download_no_permission_toast);
44 DOWNLOAD_ALREADY_EXISTS_TOAST =
45 mContext.getString(R.string.download_already_exists_toast);
46 DOWNLOAD_FAILED_TOAST =
47 mContext.getString(R.string.download_failed_toast);
48 DOWNLOAD_FINISHED_TOAST =
49 mContext.getString(R.string.download_finished_toast);
53 public void onDownloadStart(String url, String userAgent,
54 String contentDisposition, String mimetype, long contentLength) {
55 String fileName = getFileName(url, contentDisposition, mimetype);
57 // Check whether we have permission to write file to external storage.
58 // We only start download request if we have permission.
59 if (!checkWriteExternalPermission()) return;
61 Uri src = Uri.parse(url);
62 if (src.getScheme().equals("http") || src.getScheme().equals("https")) {
63 Request request = new Request(Uri.parse(url));
64 request.setDestinationInExternalPublicDir(
65 Environment.DIRECTORY_DOWNLOADS, fileName);
66 getDownloadManager().enqueue(request);
67 popupMessages(DOWNLOAD_START_TOAST + fileName);
69 new FileTransfer(url, fileName).execute();
73 private String getFileName(String url, String contentDisposition, String mimetype) {
74 String fileName = URLUtil.guessFileName(url, contentDisposition, mimetype);
75 int extensionIndex = fileName.lastIndexOf(".");
76 String extension = null;
77 if ((extensionIndex > 1) && (extensionIndex < fileName.length())) {
78 extension = fileName.substring(extensionIndex + 1);
81 // If the file name does not have a file extension, append extension based on MIME type.
82 if (extension == null) {
83 extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimetype);
84 if (extension != null) fileName = fileName + "." + extension;
89 private DownloadManager getDownloadManager() {
90 DownloadManager downloadManager =
91 (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
92 return downloadManager;
95 private boolean checkWriteExternalPermission() {
96 int result = mContext.checkCallingOrSelfPermission(
97 Manifest.permission.WRITE_EXTERNAL_STORAGE);
98 if (result == PackageManager.PERMISSION_GRANTED) return true;
100 popupMessages(DOWNLOAD_NO_PERMISSION_TOAST);
104 private void popupMessages(String message) {
105 Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
108 private class FileTransfer extends AsyncTask<Void, Void, String> {
112 public FileTransfer(String url, String fileName) {
114 this.fileName = fileName;
118 protected String doInBackground(Void... params) {
119 OutputStream dstStream = null;
120 InputStream srcStream = null;
121 File dir = Environment.getExternalStoragePublicDirectory(
122 Environment.DIRECTORY_DOWNLOADS);
123 File dst = new File(dir, fileName);
128 dstStream = new FileOutputStream(dst);
129 srcStream = AndroidProtocolHandler.open(mContext, url);
130 if (dstStream != null && srcStream != null) {
131 streamTransfer(srcStream, dstStream);
133 } catch (IOException e) {
137 if (srcStream != null) srcStream.close();
138 if (dstStream != null) dstStream.close();
139 } catch (IOException e) {
148 protected void onPostExecute(String result) {
149 if (result.equals("Failed")) {
150 popupMessages(DOWNLOAD_FAILED_TOAST);
151 } else if (result.equals("Existed")) {
152 popupMessages(DOWNLOAD_ALREADY_EXISTS_TOAST);
153 } else if (result.equals("Finished")) {
154 popupMessages(DOWNLOAD_FINISHED_TOAST);
158 private void streamTransfer(InputStream src, OutputStream dst) throws IOException {
159 // Transfer bytes from src to dst.
160 byte[] buf = new byte[1024];
162 while ((length = src.read(buf)) > 0) {
163 dst.write(buf, 0, length);