blob: 99be35687cf1061c8a5a38385982da95b8a43bd3 [file] [log] [blame]
luxiaol62677b02013-07-22 07:54:49 +08001/*
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -07002 * Copyright (c) 2013,2014, The Linux Foundation. All rights reserved.
luxiaol62677b02013-07-22 07:54:49 +08003 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
Bijan Amirzada41242f22014-03-21 12:12:18 -070030package com.android.browser;
luxiaol62677b02013-07-22 07:54:49 +080031
32import java.io.File;
33
34import android.app.Activity;
35import android.content.Intent;
36import java.lang.Thread;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080037
Bijan Amirzada41242f22014-03-21 12:12:18 -070038import com.android.browser.R;
Bijan Amirzada9b1e9882014-02-26 17:15:46 -080039
luxiaol62677b02013-07-22 07:54:49 +080040import android.net.Uri;
41import android.os.Bundle;
kaiyizf1a66762013-09-16 16:59:43 +080042import android.os.Environment;
luxiaol62677b02013-07-22 07:54:49 +080043import android.text.format.*;
44import android.util.Log;
45import android.view.View;
46import android.view.View.OnClickListener;
47import android.widget.Button;
48import android.widget.EditText;
49import android.widget.TextView;
50import android.view.Window;
51import android.widget.Toast;
Axesh R. Ajmeraf9cb0cb2015-04-09 17:23:31 -070052import android.webkit.MimeTypeMap;
luxiaol62677b02013-07-22 07:54:49 +080053import android.text.TextUtils;
54
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -070055import com.android.browser.reflect.ReflectHelper;
56
luxiaol62677b02013-07-22 07:54:49 +080057public class DownloadSettings extends Activity {
58
59 private EditText downloadFilenameET;
60 private EditText downloadPathET;
61 private TextView downloadEstimateSize;
62 private TextView downloadEstimateTime;
63 private Button downloadStart;
64 private Button downloadCancel;
65 private String url;
66 private String userAgent;
67 private String contentDisposition;
68 private String mimetype;
69 private String referer;
70 private String filenameBase;
71 private String filename;
72 private String filenameExtension;
73 private boolean privateBrowsing;
74 private long contentLength;
75 private String downloadPath;
76 private String downloadPathForUser;
77 private static final int downloadRate = (1024 * 100 * 60);// Download Rate
78 // 100KB/s
79 private final static String LOGTAG = "DownloadSettings";
80 private final static int DOWNLOAD_PATH = 0;
81 private boolean isDownloadStarted = false;
82
83 private static final String ENV_EMULATED_STORAGE_TARGET = "EMULATED_STORAGE_TARGET";
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -070084 private static final String APK_TYPE="apk";
85 private static final String OCTET_STREAM = "application/octet-stream";
luxiaol62677b02013-07-22 07:54:49 +080086
87 protected void onCreate(Bundle savedInstanceState) {
88 super.onCreate(savedInstanceState);
89 // initial the DownloadSettings view
90 requestWindowFeature(Window.FEATURE_NO_TITLE);
91 setContentView(R.layout.download_settings);
92 downloadFilenameET = (EditText) findViewById(R.id.download_filename_edit);
93 downloadPathET = (EditText) findViewById(R.id.download_filepath_selected);
94 downloadEstimateSize = (TextView) findViewById(R.id.download_estimate_size_content);
95 downloadEstimateTime = (TextView) findViewById(R.id.download_estimate_time_content);
96 downloadStart = (Button) findViewById(R.id.download_start);
97 downloadCancel = (Button) findViewById(R.id.download_cancle);
98 downloadPathET.setOnClickListener(downloadPathListener);
99 downloadStart.setOnClickListener(downloadStartListener);
100 downloadCancel.setOnClickListener(downloadCancelListener);
101
102 // get the bundle from Intent
103 Intent intent = getIntent();
104 Bundle fileInfo = intent.getExtras();
105 url = fileInfo.getString("url");
106 userAgent = fileInfo.getString("userAgent");
107 contentDisposition = fileInfo.getString("contentDisposition");
108 mimetype = fileInfo.getString("mimetype");
109 referer = fileInfo.getString("referer");
110 contentLength = fileInfo.getLong("contentLength");
111 privateBrowsing = fileInfo.getBoolean("privateBrowsing");
112 filename = fileInfo.getString("filename");
113
114 // download filenamebase's length is depended on filenameLength's values
115 // if filenamebase.length >= flienameLength, destroy the last string!
116
117 filenameBase = DownloadHandler.getFilenameBase(filename);
118 if (filenameBase.length() >= (BrowserUtils.FILENAME_MAX_LENGTH)) {
119 filenameBase = filenameBase.substring(0, BrowserUtils.FILENAME_MAX_LENGTH);
120 }
121
122 // warring when user enter more over letters into the EditText
123 BrowserUtils.maxLengthFilter(DownloadSettings.this, downloadFilenameET,
124 BrowserUtils.FILENAME_MAX_LENGTH);
125
126 downloadFilenameET.setText(filenameBase);
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -0700127
128 String filenameExtension = DownloadHandler.getFilenameExtension(filename);
129
Axesh R. Ajmera2e241242014-05-19 15:53:38 -0700130 // introspect for octet stream mimetype what type of file extension it has
131 // and reassign mimetype
132 if (mimetype == null || mimetype.isEmpty() || mimetype.equals(OCTET_STREAM)) {
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -0700133
134 String updatedFileName = filenameBase + "." + filenameExtension;
135 Object[] params = {updatedFileName};
136 Class[] type = new Class[] {String.class};
Bijan Amirzada58383e72014-04-01 14:45:22 -0700137 mimetype = (String) ReflectHelper.invokeMethod("android.media.MediaFile",
Axesh R. Ajmeraf9cb0cb2015-04-09 17:23:31 -0700138 "getMimeTypeForFile", type, params);
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -0700139 }
140
141 //Add special check for .apk files with octet-stream mimetype
Axesh R. Ajmera77258982014-04-02 14:39:09 -0700142 if (filenameExtension.equals(APK_TYPE) && mimetype != null && mimetype.equals(OCTET_STREAM)) {
Axesh R. Ajmera7cfd7a72014-04-01 16:03:42 -0700143 mimetype = "application/vnd.android.package-archive";
144 }
145
Axesh R. Ajmeraf9cb0cb2015-04-09 17:23:31 -0700146 // last way to fetch for mimetype if its still null
147 if (mimetype == null || mimetype.isEmpty())
148 mimetype = MimeTypeMap.getSingleton().getMimeTypeFromExtension(filenameExtension);
149
kaiyizf1a66762013-09-16 16:59:43 +0800150 downloadPath = chooseFolderFromMimeType(BrowserSettings.getInstance().getDownloadPath(),
151 mimetype);
luxiaol62677b02013-07-22 07:54:49 +0800152 downloadPathForUser = DownloadHandler.getDownloadPathForUser(DownloadSettings.this,
153 downloadPath);
Axesh R. Ajmeraf9cb0cb2015-04-09 17:23:31 -0700154
155 autoupdateFileName(filenameBase, DownloadHandler.getFilenameExtension(filename), downloadPath);
luxiaol62677b02013-07-22 07:54:49 +0800156 setDownloadPathForUserText(downloadPathForUser);
157 setDownloadFileSizeText();
158 setDownloadFileTimeText();
luxiaol62677b02013-07-22 07:54:49 +0800159 }
160
Axesh R. Ajmeraf9cb0cb2015-04-09 17:23:31 -0700161 private void autoupdateFileName(String filenameBase, String extension, String downloadPath) {
162 String fullPath = downloadPath + "/" + filenameBase + "." + extension;
163 int count = 1;
164 String newFilenameBase = "";
165
166 while(new File(fullPath).exists()) {
167 newFilenameBase = filenameBase+"-"+count++;
168 fullPath = downloadPath + "/" + newFilenameBase + "." + extension;
169 }
170
171 if(!TextUtils.isEmpty(newFilenameBase)) {
172 filenameBase = newFilenameBase;
173 }
174
175 downloadFilenameET.setText(filenameBase);
176 }
177
luxiaol62677b02013-07-22 07:54:49 +0800178 private OnClickListener downloadPathListener = new OnClickListener() {
179
180 @Override
181 public void onClick(View v) {
182
Vivek Sekharefefe6b2015-01-05 16:01:07 -0800183 final String filemanagerIntent =
184 getResources().getString(R.string.def_intent_file_manager);
185 if (!TextUtils.isEmpty(filemanagerIntent)) {
186 // start filemanager for getting download path
187 try {
188 Intent downloadPathIntent = new Intent(filemanagerIntent);
189 DownloadSettings.this.startActivityForResult(downloadPathIntent, DOWNLOAD_PATH);
190 } catch (Exception e) {
191 String err_msg = getString(R.string.activity_not_found,
192 filemanagerIntent);
193 Toast.makeText(DownloadSettings.this, err_msg, Toast.LENGTH_LONG).show();
194 }
195 } else {
196 Log.e(LOGTAG, "File Manager intent not defined !!");
luxiaol62677b02013-07-22 07:54:49 +0800197 }
198
199 }
200 };
201
202 private OnClickListener downloadStartListener = new OnClickListener() {
203
204 @Override
205 public void onClick(View v) {
206 filenameBase = getFilenameBaseFromUserEnter();
207 // check the filename user enter is null or not
208 if (filenameBase.length() <= 0) {
209 DownloadHandler.showFilenameEmptyDialog(DownloadSettings.this);
210 return;
211 }
212
213 filenameExtension = DownloadHandler.getFilenameExtension(filename);
214 filename = filenameBase + "." + filenameExtension;
215
216 // check the storage status
217 if (!DownloadHandler.isStorageStatusOK(DownloadSettings.this, filename, downloadPath)) {
218 return;
219 }
220
221 // check the storage memory enough or not
222 try {
223 DownloadHandler.setAppointedFolder(downloadPath);
224 } catch (Exception e) {
225 DownloadHandler.showNoEnoughMemoryDialog(DownloadSettings.this);
226 return;
227 }
kaiyize6a27d02013-08-22 15:08:19 +0800228 boolean isNoEnoughMemory = DownloadHandler.manageNoEnoughMemory(contentLength,
229 downloadPath);
luxiaol62677b02013-07-22 07:54:49 +0800230 if (isNoEnoughMemory) {
kaiyize6a27d02013-08-22 15:08:19 +0800231 DownloadHandler.showNoEnoughMemoryDialog(DownloadSettings.this);
luxiaol62677b02013-07-22 07:54:49 +0800232 return;
233 }
234
235 // check the download file is exist or not
236 String fullFilename = downloadPath + "/" + filename;
237 if (mimetype != null && new File(fullFilename).exists()) {
238 DownloadHandler.fileExistQueryDialog(DownloadSettings.this);
239 return;
240 }
241
242 // staring downloading
243 DownloadHandler.startingDownload(DownloadSettings.this,
244 url, userAgent, contentDisposition,
245 mimetype, referer, privateBrowsing, contentLength,
246 Uri.encode(filename), downloadPath);
247 isDownloadStarted = true;
248 }
249 };
250
251 private OnClickListener downloadCancelListener = new OnClickListener() {
luxiaol62677b02013-07-22 07:54:49 +0800252 @Override
253 public void onClick(View v) {
254 finish();
255 }
256 };
257
258 protected void onDestroy() {
259 super.onDestroy();
260 }
261
262 protected void onPause() {
263 super.onPause();
264 if (isDownloadStarted) {
265 finish();
266 }
267 }
268
269 protected void onResume() {
270 super.onResume();
271 }
272
273 @Override
274 protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
Vivek Sekharefefe6b2015-01-05 16:01:07 -0800275
luxiaol62677b02013-07-22 07:54:49 +0800276 if (DOWNLOAD_PATH == requestCode) {
Vivek Sekharefefe6b2015-01-05 16:01:07 -0800277 if (resultCode == Activity.RESULT_OK && intent != null) {
278 final String result_dir_sel =
279 getResources().getString(R.string.def_file_manager_result_dir);
280 downloadPath = intent.getStringExtra(result_dir_sel);
Vivek Sekhar76074ac2014-06-27 16:33:13 -0700281 // Fallback logic to stock browser
282 if (downloadPath == null) {
283 Uri uri = intent.getData();
284 if(uri != null)
285 downloadPath = uri.getPath();
286 }
luxiaol62677b02013-07-22 07:54:49 +0800287 if (downloadPath != null) {
288 String rawEmulatedStorageTarget = System.getenv(ENV_EMULATED_STORAGE_TARGET);
289 if (!TextUtils.isEmpty(rawEmulatedStorageTarget)) {
290 if (downloadPath.startsWith("/storage/sdcard0"))
291 downloadPath = downloadPath.replace("/storage/sdcard0",
292 "/storage/emulated/0");
293 if (downloadPath.startsWith("/storage/emulated/legacy"))
294 downloadPath = downloadPath.replace("/storage/emulated/legacy",
295 "/storage/emulated/0");
296 }
297 downloadPathForUser = DownloadHandler.getDownloadPathForUser(
298 DownloadSettings.this, downloadPath);
299 setDownloadPathForUserText(downloadPathForUser);
300 }
301 }
302 }
303 }
304
kaiyizf1a66762013-09-16 16:59:43 +0800305 // Add for carrier feature - download to related folders by mimetype.
306 private static String chooseFolderFromMimeType(String path, String mimeType) {
307 String destinationFolder = null;
308 if (!path.contains(Environment.DIRECTORY_DOWNLOADS) || null == mimeType)
309 return path;
310 if (mimeType.startsWith("audio"))
311 destinationFolder = Environment.DIRECTORY_MUSIC;
312 else if (mimeType.startsWith("video"))
313 destinationFolder = Environment.DIRECTORY_MOVIES;
314 else if (mimeType.startsWith("image"))
315 destinationFolder = Environment.DIRECTORY_PICTURES;
316 if (null != destinationFolder)
317 path = path.replace(Environment.DIRECTORY_DOWNLOADS, destinationFolder);
318 return path;
319 }
320
luxiaol62677b02013-07-22 07:54:49 +0800321 /**
322 * show download path for user
323 *
324 * @param downloadPath the download path user can see
325 */
326 private void setDownloadPathForUserText(String downloadPathForUser) {
327 downloadPathET.setText(downloadPathForUser);
328 }
329
330 /**
331 * get the filename from user select the download path
332 *
333 * @return String the filename from user selected
334 */
335 private String getFilenameBaseFromUserEnter() {
336 return downloadFilenameET.getText().toString();
337 }
338
339 /**
340 * set the download file size for user to be known
341 */
342 private void setDownloadFileSizeText() {
343 String sizeText;
344 if (contentLength <= 0) {
345 sizeText = getString(R.string.unknow_length);
346 } else {
347 sizeText = getDownloadFileSize();
348 }
349 downloadEstimateSize.setText(sizeText);
350
351 }
352
353 /**
354 * set the time which downloaded this file will be estimately use;
355 */
356 private void setDownloadFileTimeText() {
357 String neededTimeText;
358 if (contentLength <= 0) {
359 neededTimeText = getString(R.string.unknow_length);
360 } else {
361 neededTimeText = getNeededTime() + getString(R.string.time_min);
362 }
363 downloadEstimateTime.setText(neededTimeText);
364 }
365
366 /**
367 * count the download file's size and format the values
368 *
369 * @return String the format values
370 */
371 private String getDownloadFileSize() {
372 String currentSizeText = "";
373 if (contentLength > 0) {
374 currentSizeText = Formatter.formatFileSize(DownloadSettings.this, contentLength);
375 }
376 return currentSizeText;
377 }
378
379 /**
380 * get the time download this file will be use,and format this time values
381 *
382 * @return long the valses of time which download this file will be use
383 */
384 private long getNeededTime() {
385 long timeNeeded = contentLength / downloadRate;
386 if (timeNeeded < 1) {
387 timeNeeded = 1;
388 }
389 Log.e(LOGTAG, "TimeNeeded:" + timeNeeded + "min");
390 // return the time like 5 min, not 5 s;
391 return timeNeeded;
392 }
393}