blob: 15167a0863c25aadd369e319db03e7ad5b292828 [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
luxiaol62677b02013-07-22 07:54:49 +080059 public static void startingDownload(Activity activity,
60 String url, String userAgent, String contentDisposition,
61 String mimetype, String referer, boolean privateBrowsing, long contentLength,
62 String filename, String downloadPath) {
63 // java.net.URI is a lot stricter than KURL so we have to encode some
64 // extra characters. Fix for b 2538060 and b 1634719
65 WebAddress webAddress;
66 try {
67 webAddress = new WebAddress(url);
68 webAddress.setPath(encodePath(webAddress.getPath()));
69 } catch (Exception e) {
70 // This only happens for very bad urls, we want to chatch the
71 // exception here
72 Log.e(LOGTAG, "Exception trying to parse url:" + url);
73 return;
74 }
75
76 String addressString = webAddress.toString();
77 Uri uri = Uri.parse(addressString);
78 final DownloadManager.Request request;
79 try {
80 request = new DownloadManager.Request(uri);
81 } catch (IllegalArgumentException e) {
82 Toast.makeText(activity, R.string.cannot_download, Toast.LENGTH_SHORT).show();
83 return;
84 }
85 request.setMimeType(mimetype);
86 // set downloaded file destination to /sdcard/Download.
87 // or, should it be set to one of several Environment.DIRECTORY* dirs
88 // depending on mimetype?
89 try {
90 setDestinationDir(downloadPath, filename, request);
91 } catch (Exception e) {
92 showNoEnoughMemoryDialog(activity);
93 return;
94 }
95 // let this downloaded file be scanned by MediaScanner - so that it can
96 // show up in Gallery app, for example.
97 request.allowScanningByMediaScanner();
98 request.setDescription(webAddress.getHost());
99 // XXX: Have to use the old url since the cookies were stored using the
100 // old percent-encoded url.
101 String cookies = CookieManager.getInstance().getCookie(url, privateBrowsing);
102 request.addRequestHeader("cookie", cookies);
103 request.addRequestHeader("User-Agent", userAgent);
104 request.addRequestHeader("Referer", referer);
105 request.setNotificationVisibility(
106 DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
107 final DownloadManager manager = (DownloadManager) activity
108 .getSystemService(Context.DOWNLOAD_SERVICE);
109 new Thread("Browser download") {
110 public void run() {
111 manager.enqueue(request);
112 }
113 }.start();
114 showStartDownloadToast(activity);
115 }
116
kaiyize6a27d02013-08-22 15:08:19 +0800117 /**
118 * Notify the host application a download should be done, or that
119 * the data should be streamed if a streaming viewer is available.
120 * @param activity Activity requesting the download.
121 * @param url The full url to the content that should be downloaded
122 * @param userAgent User agent of the downloading application.
123 * @param contentDisposition Content-disposition http header, if present.
124 * @param mimetype The mimetype of the content reported by the server
125 * @param referer The referer associated with the downloaded url
126 * @param privateBrowsing If the request is coming from a private browsing tab.
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
kaiyize6a27d02013-08-22 15:08:19 +0800396 public static boolean manageNoEnoughMemory(long contentLength, String root) {
luxiaol62677b02013-07-22 07:54:49 +0800397 long mAvailableBytes = getAvailableMemory(root);
398 if (mAvailableBytes > 0) {
399 if (contentLength > mAvailableBytes) {
luxiaol62677b02013-07-22 07:54:49 +0800400 return true;
401 }
402 } else {
luxiaol62677b02013-07-22 07:54:49 +0800403 return true;
404 }
405 return false;
406 }
407
408 public static void showStartDownloadToast(Activity activity) {
409 Intent intent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
410 activity.startActivity(intent);
Leon Scroggins63c02662010-11-18 15:16:27 -0500411 Toast.makeText(activity, R.string.download_pending, Toast.LENGTH_SHORT)
Michael Kolb8233fac2010-10-26 16:08:53 -0700412 .show();
413 }
414
luxiaol62677b02013-07-22 07:54:49 +0800415 /**
416 * wheather the storage status OK for download file
417 *
418 * @param activity
419 * @param filename the download file's name
420 * @param downloadPath the download file's path will be in
421 * @return boolean true is ok,and false is not
422 */
423 public static boolean isStorageStatusOK(Activity activity, String filename, String downloadPath) {
424 if (downloadPath.equals(INVALID_PATH)) {
425 new AlertDialog.Builder(activity)
426 .setTitle(R.string.path_wrong)
427 .setIcon(android.R.drawable.ic_dialog_alert)
428 .setMessage(R.string.invalid_path)
429 .setPositiveButton(R.string.ok, null)
430 .show();
431 return false;
432 }
433
434 if (!(isPhoneStorageSupported() && downloadPath.contains(mInternalStorage))) {
435 String status = getExternalStorageState(activity);
436 if (!status.equals(Environment.MEDIA_MOUNTED)) {
437 int title;
438 String msg;
439
440 // Check to see if the SDCard is busy, same as the music app
441 if (status.equals(Environment.MEDIA_SHARED)) {
442 msg = activity.getString(R.string.download_sdcard_busy_dlg_msg);
443 title = R.string.download_sdcard_busy_dlg_title;
444 } else {
445 msg = activity.getString(R.string.download_no_sdcard_dlg_msg, filename);
446 title = R.string.download_no_sdcard_dlg_title;
447 }
448
449 new AlertDialog.Builder(activity)
450 .setTitle(title)
451 .setIcon(android.R.drawable.ic_dialog_alert)
452 .setMessage(msg)
453 .setPositiveButton(R.string.ok, null)
454 .show();
455 return false;
456 }
457 } else {
458 String status = Environment.getExternalStorageState();
459 if (!status.equals(Environment.MEDIA_MOUNTED)) {
460 int mTitle = R.string.download_path_unavailable_dlg_title;
461 String mMsg = activity.getString(R.string.download_path_unavailable_dlg_msg);
462 new AlertDialog.Builder(activity)
463 .setTitle(mTitle)
464 .setIcon(android.R.drawable.ic_dialog_alert)
465 .setMessage(mMsg)
466 .setPositiveButton(R.string.ok, null)
467 .show();
468 return false;
469 }
470 }
471 return true;
472 }
473
474 /**
475 * wheather support Phone Storage
476 *
477 * @return boolean true support Phone Storage ,false will be not
478 */
479 public static boolean isPhoneStorageSupported() {
480 return true;
481 }
482
483 /**
484 * show Dialog to warn filename is null
485 *
486 * @param activity
487 */
488 public static void showFilenameEmptyDialog(Activity activity) {
489 new AlertDialog.Builder(activity)
490 .setTitle(R.string.filename_empty_title)
491 .setIcon(android.R.drawable.ic_dialog_alert)
492 .setMessage(R.string.filename_empty_msg)
493 .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
494 public void onClick(DialogInterface dialog, int which) {
495 }
496 })
497 .show();
498 }
499
500 /**
501 * get the filename except the suffix and dot
502 *
503 * @return String the filename except suffix and dot
504 */
505 public static String getFilenameBase(String filename) {
506 int dotindex = filename.lastIndexOf('.');
507 if (dotindex != -1) {
508 return filename.substring(0, dotindex);
509 } else {
510 return "";
511 }
512 }
513
514 /**
515 * get the filename's extension from filename
516 *
517 * @param filename the download filename, may be the user entered
518 * @return String the filename's extension
519 */
520 public static String getFilenameExtension(String filename) {
521 int dotindex = filename.lastIndexOf('.');
522 if (dotindex != -1) {
523 return filename.substring(dotindex + 1);
524 } else {
525 return "";
526 }
527 }
528
529 public static String getDefaultDownloadPath(Context context) {
530 String defaultDownloadPath;
531
532 String defaultStorage;
533 if (isPhoneStorageSupported()) {
534 defaultStorage = Environment.getExternalStorageDirectory().getPath();
535 } else {
536 defaultStorage = getExternalStorageDirectory(context);
537 }
538
kaiyize6a27d02013-08-22 15:08:19 +0800539 defaultDownloadPath = defaultStorage + context.getString(R.string.download_default_path);
luxiaol62677b02013-07-22 07:54:49 +0800540 Log.e(LOGTAG, "defaultStorage directory is : " + defaultDownloadPath);
541 return defaultDownloadPath;
542 }
543
544 /**
545 * translate the directory name into a name which is easy to know for user
546 *
547 * @param activity
548 * @param downloadPath
549 * @return String
550 */
551 public static String getDownloadPathForUser(Activity activity, String downloadPath) {
552 if (downloadPath == null) {
553 return downloadPath;
554 }
555 final String phoneStorageDir;
556 final String sdCardDir = getExternalStorageDirectory(activity);
557 if (isPhoneStorageSupported()) {
558 phoneStorageDir = Environment.getExternalStorageDirectory().getPath();
559 } else {
560 phoneStorageDir = null;
561 }
562
563 if (downloadPath.startsWith(sdCardDir)) {
564 String sdCardLabel = activity.getResources().getString(
565 R.string.download_path_sd_card_label);
566 downloadPath = downloadPath.replace(sdCardDir, sdCardLabel);
567 } else if ((phoneStorageDir != null) && downloadPath.startsWith(phoneStorageDir)) {
568 String phoneStorageLabel = activity.getResources().getString(
569 R.string.download_path_phone_stroage_label);
570 downloadPath = downloadPath.replace(phoneStorageDir, phoneStorageLabel);
571 }
572 return downloadPath;
573 }
574
575 private static String getExternalStorageDirectory(Context context) {
576 String sd = null;
577 StorageManager mStorageManager = (StorageManager) context
578 .getSystemService(Context.STORAGE_SERVICE);
579 StorageVolume[] volumes = mStorageManager.getVolumeList();
580 for (int i = 0; i < volumes.length; i++) {
581 if (volumes[i].isRemovable() && volumes[i].allowMassStorage()) {
582 sd = volumes[i].getPath();
583 }
584 }
585 return sd;
586 }
587
588 private static String getExternalStorageState(Context context) {
589 StorageManager mStorageManager = (StorageManager) context
590 .getSystemService(Context.STORAGE_SERVICE);
591 return mStorageManager.getVolumeState(getExternalStorageDirectory(context));
592 }
Michael Kolb8233fac2010-10-26 16:08:53 -0700593}