blob: e3d31cd0ec6cc8dac69d3680129b1e0e96081ffd [file] [log] [blame]
Michael Kolb8233fac2010-10-26 16:08:53 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.browser;
18
19import android.app.Activity;
20import android.app.AlertDialog;
21import android.app.DownloadManager;
luxiaol62677b02013-07-22 07:54:49 +080022import android.app.DownloadManager.Request;
Michael Kolb8233fac2010-10-26 16:08:53 -070023import android.content.ActivityNotFoundException;
24import android.content.ComponentName;
Michael Kolb8233fac2010-10-26 16:08:53 -070025import android.content.Context;
qqzhoua95a2e22013-04-18 17:28:31 +080026import android.content.DialogInterface;
Michael Kolb8233fac2010-10-26 16:08:53 -070027import android.content.Intent;
28import android.content.pm.PackageManager;
29import android.content.pm.ResolveInfo;
qqzhoua95a2e22013-04-18 17:28:31 +080030import android.media.MediaFile;
Michael Kolb8233fac2010-10-26 16:08:53 -070031import android.net.Uri;
32import android.net.WebAddress;
luxiaol62677b02013-07-22 07:54:49 +080033import android.os.Bundle;
Michael Kolb8233fac2010-10-26 16:08:53 -070034import android.os.Environment;
luxiaol62677b02013-07-22 07:54:49 +080035import android.os.StatFs;
36import android.os.storage.StorageManager;
37import android.os.storage.StorageVolume;
Leon Scroggins63c02662010-11-18 15:16:27 -050038import android.text.TextUtils;
Michael Kolb8233fac2010-10-26 16:08:53 -070039import android.util.Log;
40import android.webkit.CookieManager;
41import android.webkit.URLUtil;
42import android.widget.Toast;
43
luxiaol62677b02013-07-22 07:54:49 +080044import java.io.File;
45
Michael Kolb8233fac2010-10-26 16:08:53 -070046/**
47 * Handle download requests
48 */
49public class DownloadHandler {
50
51 private static final boolean LOGD_ENABLED =
52 com.android.browser.Browser.LOGD_ENABLED;
53
54 private static final String LOGTAG = "DLHandler";
luxiaol62677b02013-07-22 07:54:49 +080055 private static String mInternalStorage;
56 private static String mExternalStorage;
57 private final static String INVALID_PATH = "/storage";
Michael Kolb8233fac2010-10-26 16:08:53 -070058
Michael Kolb8233fac2010-10-26 16:08:53 -070059 /**
60 * Notify the host application a download should be done, or that
61 * the data should be streamed if a streaming viewer is available.
Leon Scroggins63c02662010-11-18 15:16:27 -050062 * @param activity Activity requesting the download.
Michael Kolb8233fac2010-10-26 16:08:53 -070063 * @param url The full url to the content that should be downloaded
Leon Scroggins63c02662010-11-18 15:16:27 -050064 * @param userAgent User agent of the downloading application.
65 * @param contentDisposition Content-disposition http header, if present.
Michael Kolb8233fac2010-10-26 16:08:53 -070066 * @param mimetype The mimetype of the content reported by the server
Selim Gurun0b3d66f2012-08-29 13:08:13 -070067 * @param referer The referer associated with the downloaded url
Kristian Monsenbc5cc752011-03-02 13:14:03 +000068 * @param privateBrowsing If the request is coming from a private browsing tab.
Michael Kolb8233fac2010-10-26 16:08:53 -070069 */
luxiaol62677b02013-07-22 07:54:49 +080070
71 public static void startingDownload(Activity activity,
72 String url, String userAgent, String contentDisposition,
73 String mimetype, String referer, boolean privateBrowsing, long contentLength,
74 String filename, String downloadPath) {
75 // java.net.URI is a lot stricter than KURL so we have to encode some
76 // extra characters. Fix for b 2538060 and b 1634719
77 WebAddress webAddress;
78 try {
79 webAddress = new WebAddress(url);
80 webAddress.setPath(encodePath(webAddress.getPath()));
81 } catch (Exception e) {
82 // This only happens for very bad urls, we want to chatch the
83 // exception here
84 Log.e(LOGTAG, "Exception trying to parse url:" + url);
85 return;
86 }
87
88 String addressString = webAddress.toString();
89 Uri uri = Uri.parse(addressString);
90 final DownloadManager.Request request;
91 try {
92 request = new DownloadManager.Request(uri);
93 } catch (IllegalArgumentException e) {
94 Toast.makeText(activity, R.string.cannot_download, Toast.LENGTH_SHORT).show();
95 return;
96 }
97 request.setMimeType(mimetype);
98 // set downloaded file destination to /sdcard/Download.
99 // or, should it be set to one of several Environment.DIRECTORY* dirs
100 // depending on mimetype?
101 try {
102 setDestinationDir(downloadPath, filename, request);
103 } catch (Exception e) {
104 showNoEnoughMemoryDialog(activity);
105 return;
106 }
107 // let this downloaded file be scanned by MediaScanner - so that it can
108 // show up in Gallery app, for example.
109 request.allowScanningByMediaScanner();
110 request.setDescription(webAddress.getHost());
111 // XXX: Have to use the old url since the cookies were stored using the
112 // old percent-encoded url.
113 String cookies = CookieManager.getInstance().getCookie(url, privateBrowsing);
114 request.addRequestHeader("cookie", cookies);
115 request.addRequestHeader("User-Agent", userAgent);
116 request.addRequestHeader("Referer", referer);
117 request.setNotificationVisibility(
118 DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
119 final DownloadManager manager = (DownloadManager) activity
120 .getSystemService(Context.DOWNLOAD_SERVICE);
121 new Thread("Browser download") {
122 public void run() {
123 manager.enqueue(request);
124 }
125 }.start();
126 showStartDownloadToast(activity);
127 }
128
qqzhoua95a2e22013-04-18 17:28:31 +0800129 public static boolean onDownloadStart(final Activity activity, final String url,
130 final String userAgent, final String contentDisposition, final String mimetype,
luxiaol62677b02013-07-22 07:54:49 +0800131 final String referer, final boolean privateBrowsing, final long contentLength) {
Michael Kolb8233fac2010-10-26 16:08:53 -0700132 // if we're dealing wih A/V content that's not explicitly marked
133 // for download, check if it's streamable.
134 if (contentDisposition == null
135 || !contentDisposition.regionMatches(
136 true, 0, "attachment", 0, 10)) {
qqzhoua95a2e22013-04-18 17:28:31 +0800137
138 // Add for Carrier Feature - When open an audio/video link, prompt a dialog
139 // to let the user choose play or download operation.
140 Uri uri = Uri.parse(url);
141 String scheme = uri.getScheme();
142 Log.v(LOGTAG, "scheme:" + scheme + ", mimetype:" + mimetype);
143 // Some mimetype for audio/video files is not started with "audio" or "video",
144 // such as ogg audio file with mimetype "application/ogg". So we also check
145 // file type by MediaFile.isAudioFileType() and MediaFile.isVideoFileType().
146 // For those file types other than audio or video, download it immediately.
147 int fileType = MediaFile.getFileTypeForMimeType(mimetype);
148 if ("http".equalsIgnoreCase(scheme) &&
149 (mimetype.startsWith("audio/") ||
150 mimetype.startsWith("video/") ||
151 MediaFile.isAudioFileType(fileType) ||
152 MediaFile.isVideoFileType(fileType))) {
153 new AlertDialog.Builder(activity)
154 .setTitle(R.string.application_name)
155 .setIcon(R.drawable.default_video_poster)
156 .setMessage(R.string.http_video_msg)
157 .setPositiveButton(R.string.video_save, new DialogInterface.OnClickListener() {
158 public void onClick(DialogInterface dialog, int which) {
159 onDownloadStartNoStream(activity, url, userAgent, contentDisposition,
luxiaol62677b02013-07-22 07:54:49 +0800160 mimetype, referer, privateBrowsing, contentLength);
qqzhoua95a2e22013-04-18 17:28:31 +0800161 }
162 })
163 .setNegativeButton(R.string.video_play, new DialogInterface.OnClickListener() {
164 public void onClick(DialogInterface dialog, int which) {
165 Intent intent = new Intent(Intent.ACTION_VIEW);
166 intent.setDataAndType(Uri.parse(url), mimetype);
167 try {
168 String title = URLUtil.guessFileName(url, contentDisposition, mimetype);
169 intent.putExtra(Intent.EXTRA_TITLE, title);
170 activity.startActivity(intent);
171 } catch (ActivityNotFoundException ex) {
172 Log.w(LOGTAG, "When http stream play, activity not found for "
173 + mimetype + " over " + Uri.parse(url).getScheme(),
174 ex);
175 }
176 }
177 }).show();
178
179 return true;
180 }
181
Michael Kolb8233fac2010-10-26 16:08:53 -0700182 // query the package manager to see if there's a registered handler
183 // that matches.
184 Intent intent = new Intent(Intent.ACTION_VIEW);
185 intent.setDataAndType(Uri.parse(url), mimetype);
Leon Scroggins63c02662010-11-18 15:16:27 -0500186 ResolveInfo info = activity.getPackageManager().resolveActivity(intent,
Michael Kolb8233fac2010-10-26 16:08:53 -0700187 PackageManager.MATCH_DEFAULT_ONLY);
188 if (info != null) {
Leon Scroggins63c02662010-11-18 15:16:27 -0500189 ComponentName myName = activity.getComponentName();
Michael Kolb8233fac2010-10-26 16:08:53 -0700190 // If we resolved to ourselves, we don't want to attempt to
191 // load the url only to try and download it again.
192 if (!myName.getPackageName().equals(
193 info.activityInfo.packageName)
194 || !myName.getClassName().equals(
195 info.activityInfo.name)) {
196 // someone (other than us) knows how to handle this mime
197 // type with this scheme, don't download.
198 try {
Leon Scroggins63c02662010-11-18 15:16:27 -0500199 activity.startActivity(intent);
qqzhoua95a2e22013-04-18 17:28:31 +0800200 return false;
Michael Kolb8233fac2010-10-26 16:08:53 -0700201 } catch (ActivityNotFoundException ex) {
202 if (LOGD_ENABLED) {
203 Log.d(LOGTAG, "activity not found for " + mimetype
204 + " over " + Uri.parse(url).getScheme(),
205 ex);
206 }
207 // Best behavior is to fall back to a download in this
208 // case
209 }
210 }
211 }
212 }
Leon Scroggins63c02662010-11-18 15:16:27 -0500213 onDownloadStartNoStream(activity, url, userAgent, contentDisposition,
luxiaol62677b02013-07-22 07:54:49 +0800214 mimetype, referer, privateBrowsing, contentLength);
qqzhoua95a2e22013-04-18 17:28:31 +0800215 return false;
Michael Kolb8233fac2010-10-26 16:08:53 -0700216 }
217
218 // This is to work around the fact that java.net.URI throws Exceptions
219 // instead of just encoding URL's properly
220 // Helper method for onDownloadStartNoStream
221 private static String encodePath(String path) {
222 char[] chars = path.toCharArray();
223
224 boolean needed = false;
225 for (char c : chars) {
Selim Guruna770f8d2012-06-13 14:51:23 -0700226 if (c == '[' || c == ']' || c == '|') {
Michael Kolb8233fac2010-10-26 16:08:53 -0700227 needed = true;
228 break;
229 }
230 }
231 if (needed == false) {
232 return path;
233 }
234
235 StringBuilder sb = new StringBuilder("");
236 for (char c : chars) {
Selim Guruna770f8d2012-06-13 14:51:23 -0700237 if (c == '[' || c == ']' || c == '|') {
Michael Kolb8233fac2010-10-26 16:08:53 -0700238 sb.append('%');
239 sb.append(Integer.toHexString(c));
240 } else {
241 sb.append(c);
242 }
243 }
244
245 return sb.toString();
246 }
247
248 /**
249 * Notify the host application a download should be done, even if there
250 * is a streaming viewer available for thise type.
Leon Scroggins63c02662010-11-18 15:16:27 -0500251 * @param activity Activity requesting the download.
Michael Kolb8233fac2010-10-26 16:08:53 -0700252 * @param url The full url to the content that should be downloaded
Leon Scroggins63c02662010-11-18 15:16:27 -0500253 * @param userAgent User agent of the downloading application.
254 * @param contentDisposition Content-disposition http header, if present.
Michael Kolb8233fac2010-10-26 16:08:53 -0700255 * @param mimetype The mimetype of the content reported by the server
Selim Gurun0b3d66f2012-08-29 13:08:13 -0700256 * @param referer The referer associated with the downloaded url
Kristian Monsenbc5cc752011-03-02 13:14:03 +0000257 * @param privateBrowsing If the request is coming from a private browsing tab.
Michael Kolb8233fac2010-10-26 16:08:53 -0700258 */
luxiaol62677b02013-07-22 07:54:49 +0800259 /* package */static void onDownloadStartNoStream(Activity activity,
Leon Scroggins63c02662010-11-18 15:16:27 -0500260 String url, String userAgent, String contentDisposition,
luxiaol62677b02013-07-22 07:54:49 +0800261 String mimetype, String referer, boolean privateBrowsing, long contentLength) {
Michael Kolb8233fac2010-10-26 16:08:53 -0700262
luxiaol62677b02013-07-22 07:54:49 +0800263 initStorageDefaultPath(activity);
Michael Kolb8233fac2010-10-26 16:08:53 -0700264 String filename = URLUtil.guessFileName(url,
265 contentDisposition, mimetype);
266
267 // Check to see if we have an SDCard
268 String status = Environment.getExternalStorageState();
269 if (!status.equals(Environment.MEDIA_MOUNTED)) {
270 int title;
271 String msg;
272
273 // Check to see if the SDCard is busy, same as the music app
274 if (status.equals(Environment.MEDIA_SHARED)) {
Leon Scroggins63c02662010-11-18 15:16:27 -0500275 msg = activity.getString(R.string.download_sdcard_busy_dlg_msg);
Michael Kolb8233fac2010-10-26 16:08:53 -0700276 title = R.string.download_sdcard_busy_dlg_title;
277 } else {
Leon Scroggins63c02662010-11-18 15:16:27 -0500278 msg = activity.getString(R.string.download_no_sdcard_dlg_msg, filename);
Michael Kolb8233fac2010-10-26 16:08:53 -0700279 title = R.string.download_no_sdcard_dlg_title;
280 }
281
Leon Scroggins63c02662010-11-18 15:16:27 -0500282 new AlertDialog.Builder(activity)
Michael Kolb8233fac2010-10-26 16:08:53 -0700283 .setTitle(title)
Björn Lundén2aa8ba22012-05-31 23:05:56 +0200284 .setIconAttribute(android.R.attr.alertDialogIcon)
Michael Kolb8233fac2010-10-26 16:08:53 -0700285 .setMessage(msg)
286 .setPositiveButton(R.string.ok, null)
287 .show();
288 return;
289 }
290
Michael Kolb8233fac2010-10-26 16:08:53 -0700291 if (mimetype == null) {
Michael Kolb8233fac2010-10-26 16:08:53 -0700292 // We must have long pressed on a link or image to download it. We
293 // are not sure of the mimetype in this case, so do a head request
luxiaol62677b02013-07-22 07:54:49 +0800294 new FetchUrlMimeType(activity, url, userAgent, referer,
295 privateBrowsing, filename).start();
Michael Kolb8233fac2010-10-26 16:08:53 -0700296 } else {
luxiaol62677b02013-07-22 07:54:49 +0800297 startDownloadSettings(activity, url, userAgent, contentDisposition, mimetype, referer,
298 privateBrowsing, contentLength, filename);
Michael Kolb8233fac2010-10-26 16:08:53 -0700299 }
luxiaol62677b02013-07-22 07:54:49 +0800300
301 }
302
303 public static void initStorageDefaultPath(Context context) {
304 mExternalStorage = getExternalStorageDirectory(context);
305 if (isPhoneStorageSupported()) {
306 mInternalStorage = Environment.getExternalStorageDirectory().getPath();
307 } else {
308 mInternalStorage = null;
309 }
310 }
311
312 public static void startDownloadSettings(Activity activity,
313 String url, String userAgent, String contentDisposition,
314 String mimetype, String referer, boolean privateBrowsing, long contentLength,
315 String filename) {
316 Bundle fileInfo = new Bundle();
317 fileInfo.putString("url", url);
318 fileInfo.putString("userAgent", userAgent);
319 fileInfo.putString("contentDisposition", contentDisposition);
320 fileInfo.putString("mimetype", mimetype);
321 fileInfo.putString("referer", referer);
322 fileInfo.putLong("contentLength", contentLength);
323 fileInfo.putBoolean("privateBrowsing", privateBrowsing);
324 fileInfo.putString("filename", filename);
325 Intent intent = new Intent("android.intent.action.BROWSERDOWNLOAD");
326 intent.putExtras(fileInfo);
327 activity.startActivity(intent);
328 }
329
330 public static void setAppointedFolder(String downloadPath) {
331 File file = new File(downloadPath);
332 if (file.exists()) {
333 if (!file.isDirectory()) {
334 throw new IllegalStateException(file.getAbsolutePath() +
335 " already exists and is not a directory");
336 }
337 } else {
338 if (!file.mkdir()) {
339 throw new IllegalStateException("Unable to create directory: " +
340 file.getAbsolutePath());
341 }
342 }
343 }
344
345 private static void setDestinationDir(String downloadPath, String filename, Request request) {
346 File file = new File(downloadPath);
347 if (file.exists()) {
348 if (!file.isDirectory()) {
349 throw new IllegalStateException(file.getAbsolutePath() +
350 " already exists and is not a directory");
351 }
352 } else {
353 if (!file.mkdir()) {
354 throw new IllegalStateException("Unable to create directory: " +
355 file.getAbsolutePath());
356 }
357 }
358 setDestinationFromBase(file, filename, request);
359 }
360
361 private static void setDestinationFromBase(File file, String filename, Request request) {
362 if (filename == null) {
363 throw new NullPointerException("filename cannot be null");
364 }
365 request.setDestinationUri(Uri.withAppendedPath(Uri.fromFile(file), filename));
366 }
367
368 public static void fileExistQueryDialog(Activity activity) {
369 new AlertDialog.Builder(activity)
370 .setTitle(R.string.download_file_exist)
371 .setIcon(android.R.drawable.ic_dialog_info)
372 .setMessage(R.string.download_file_exist_msg)
373 // if yes, delete existed file and start new download thread
374 .setPositiveButton(R.string.ok, null)
375 // if no, do nothing at all
376 .show();
377 }
378
379 public static long getAvailableMemory(String root) {
380 StatFs stat = new StatFs(root);
381 final long LEFT10MByte = 2560;
382 long blockSize = stat.getBlockSize();
383 long availableBlocks = stat.getAvailableBlocks() - LEFT10MByte;
384 return availableBlocks * blockSize;
385 }
386
387 public static void showNoEnoughMemoryDialog(Activity mContext) {
388 new AlertDialog.Builder(mContext)
389 .setTitle(R.string.download_no_enough_memory)
390 .setIconAttribute(android.R.attr.alertDialogIcon)
391 .setMessage(R.string.download_no_enough_memory)
392 .setPositiveButton(R.string.ok, null)
393 .show();
394 }
395
396 public static boolean manageNoEnoughMemory(Activity mContext, long contentLength, String root) {
397 Log.i(LOGTAG, "----------- download file contentLength is ------------>" + contentLength);
398 long mAvailableBytes = getAvailableMemory(root);
399 if (mAvailableBytes > 0) {
400 if (contentLength > mAvailableBytes) {
401 showNoEnoughMemoryDialog(mContext);
402 return true;
403 }
404 } else {
405 showNoEnoughMemoryDialog(mContext);
406 return true;
407 }
408 return false;
409 }
410
411 public static void showStartDownloadToast(Activity activity) {
412 Intent intent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
413 activity.startActivity(intent);
Leon Scroggins63c02662010-11-18 15:16:27 -0500414 Toast.makeText(activity, R.string.download_pending, Toast.LENGTH_SHORT)
Michael Kolb8233fac2010-10-26 16:08:53 -0700415 .show();
416 }
417
luxiaol62677b02013-07-22 07:54:49 +0800418 /**
419 * wheather the storage status OK for download file
420 *
421 * @param activity
422 * @param filename the download file's name
423 * @param downloadPath the download file's path will be in
424 * @return boolean true is ok,and false is not
425 */
426 public static boolean isStorageStatusOK(Activity activity, String filename, String downloadPath) {
427 if (downloadPath.equals(INVALID_PATH)) {
428 new AlertDialog.Builder(activity)
429 .setTitle(R.string.path_wrong)
430 .setIcon(android.R.drawable.ic_dialog_alert)
431 .setMessage(R.string.invalid_path)
432 .setPositiveButton(R.string.ok, null)
433 .show();
434 return false;
435 }
436
437 if (!(isPhoneStorageSupported() && downloadPath.contains(mInternalStorage))) {
438 String status = getExternalStorageState(activity);
439 if (!status.equals(Environment.MEDIA_MOUNTED)) {
440 int title;
441 String msg;
442
443 // Check to see if the SDCard is busy, same as the music app
444 if (status.equals(Environment.MEDIA_SHARED)) {
445 msg = activity.getString(R.string.download_sdcard_busy_dlg_msg);
446 title = R.string.download_sdcard_busy_dlg_title;
447 } else {
448 msg = activity.getString(R.string.download_no_sdcard_dlg_msg, filename);
449 title = R.string.download_no_sdcard_dlg_title;
450 }
451
452 new AlertDialog.Builder(activity)
453 .setTitle(title)
454 .setIcon(android.R.drawable.ic_dialog_alert)
455 .setMessage(msg)
456 .setPositiveButton(R.string.ok, null)
457 .show();
458 return false;
459 }
460 } else {
461 String status = Environment.getExternalStorageState();
462 if (!status.equals(Environment.MEDIA_MOUNTED)) {
463 int mTitle = R.string.download_path_unavailable_dlg_title;
464 String mMsg = activity.getString(R.string.download_path_unavailable_dlg_msg);
465 new AlertDialog.Builder(activity)
466 .setTitle(mTitle)
467 .setIcon(android.R.drawable.ic_dialog_alert)
468 .setMessage(mMsg)
469 .setPositiveButton(R.string.ok, null)
470 .show();
471 return false;
472 }
473 }
474 return true;
475 }
476
477 /**
478 * wheather support Phone Storage
479 *
480 * @return boolean true support Phone Storage ,false will be not
481 */
482 public static boolean isPhoneStorageSupported() {
483 return true;
484 }
485
486 /**
487 * show Dialog to warn filename is null
488 *
489 * @param activity
490 */
491 public static void showFilenameEmptyDialog(Activity activity) {
492 new AlertDialog.Builder(activity)
493 .setTitle(R.string.filename_empty_title)
494 .setIcon(android.R.drawable.ic_dialog_alert)
495 .setMessage(R.string.filename_empty_msg)
496 .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
497 public void onClick(DialogInterface dialog, int which) {
498 }
499 })
500 .show();
501 }
502
503 /**
504 * get the filename except the suffix and dot
505 *
506 * @return String the filename except suffix and dot
507 */
508 public static String getFilenameBase(String filename) {
509 int dotindex = filename.lastIndexOf('.');
510 if (dotindex != -1) {
511 return filename.substring(0, dotindex);
512 } else {
513 return "";
514 }
515 }
516
517 /**
518 * get the filename's extension from filename
519 *
520 * @param filename the download filename, may be the user entered
521 * @return String the filename's extension
522 */
523 public static String getFilenameExtension(String filename) {
524 int dotindex = filename.lastIndexOf('.');
525 if (dotindex != -1) {
526 return filename.substring(dotindex + 1);
527 } else {
528 return "";
529 }
530 }
531
532 public static String getDefaultDownloadPath(Context context) {
533 String defaultDownloadPath;
534
535 String defaultStorage;
536 if (isPhoneStorageSupported()) {
537 defaultStorage = Environment.getExternalStorageDirectory().getPath();
538 } else {
539 defaultStorage = getExternalStorageDirectory(context);
540 }
541
542 defaultDownloadPath = defaultStorage + context.getString(R.string.default_savepath_name);
543 Log.e(LOGTAG, "defaultStorage directory is : " + defaultDownloadPath);
544 return defaultDownloadPath;
545 }
546
547 /**
548 * translate the directory name into a name which is easy to know for user
549 *
550 * @param activity
551 * @param downloadPath
552 * @return String
553 */
554 public static String getDownloadPathForUser(Activity activity, String downloadPath) {
555 if (downloadPath == null) {
556 return downloadPath;
557 }
558 final String phoneStorageDir;
559 final String sdCardDir = getExternalStorageDirectory(activity);
560 if (isPhoneStorageSupported()) {
561 phoneStorageDir = Environment.getExternalStorageDirectory().getPath();
562 } else {
563 phoneStorageDir = null;
564 }
565
566 if (downloadPath.startsWith(sdCardDir)) {
567 String sdCardLabel = activity.getResources().getString(
568 R.string.download_path_sd_card_label);
569 downloadPath = downloadPath.replace(sdCardDir, sdCardLabel);
570 } else if ((phoneStorageDir != null) && downloadPath.startsWith(phoneStorageDir)) {
571 String phoneStorageLabel = activity.getResources().getString(
572 R.string.download_path_phone_stroage_label);
573 downloadPath = downloadPath.replace(phoneStorageDir, phoneStorageLabel);
574 }
575 return downloadPath;
576 }
577
578 private static String getExternalStorageDirectory(Context context) {
579 String sd = null;
580 StorageManager mStorageManager = (StorageManager) context
581 .getSystemService(Context.STORAGE_SERVICE);
582 StorageVolume[] volumes = mStorageManager.getVolumeList();
583 for (int i = 0; i < volumes.length; i++) {
584 if (volumes[i].isRemovable() && volumes[i].allowMassStorage()) {
585 sd = volumes[i].getPath();
586 }
587 }
588 return sd;
589 }
590
591 private static String getExternalStorageState(Context context) {
592 StorageManager mStorageManager = (StorageManager) context
593 .getSystemService(Context.STORAGE_SERVICE);
594 return mStorageManager.getVolumeState(getExternalStorageDirectory(context));
595 }
Michael Kolb8233fac2010-10-26 16:08:53 -0700596}