@@ -143,7 +143,7 @@ private class DownloadTask extends AsyncTask<String, Integer, String> {
143
143
< uses- permission android: name= " android.permission.WAKE_LOCK" / >
144
144
```
145
145
146
- ### 从服务器上下载文件
146
+ #### 2. 从服务器上下载文件
147
147
148
148
这里有个最大的问题:* 我怎么从service来更新我的activity?* 。
149
149
在下一个例子当中我们会使用两个你可能不熟悉的类:`ResultReceiver `和`IntentService `。`ResultReceiver `是一个可以允许我们用Service 来更新线程的类;`IntentService `是一个可以生成用来处理后台任务的线程的`Service `子类(你需要知道,`Service `实际上是和你的应用运行在同一个线程的;当你继承了`Service `之后,你必须手动生成一个新的线程来处理费时操作)。
@@ -237,5 +237,137 @@ private class DownloadReceiver extends ResultReceiver{
237
237
}
238
238
```
239
239
240
- #### 使用Groundy 库
241
- [Groundy](http:// casidiablo.github.com/groundy)
240
+ ##### 2.1 使用Groundy 库
241
+ [Groundy](http:// casidiablo.github.com/groundy)是一个可以帮助你在后台服务中运行代码片段的库,它是基于`ResultReceiver`这一概念。但是这个库现在已经被标记为**过时**了(deprecated)。下面是**完整**代码的样子。
242
+
243
+ 你要展示dialog的Activity:
244
+
245
+ ```java
246
+ public class MainActivity extends Activity {
247
+
248
+ private ProgressDialog mProgressDialog;
249
+
250
+ @Override
251
+ public void onCreate(Bundle savedInstanceState) {
252
+ super . onCreate(savedInstanceState);
253
+ setContentView(R . layout. main);
254
+
255
+ findViewById(R . id. btn_download). setOnClickListener(new View .OnClickListener () {
256
+ public void onClick (View view ) {
257
+ String url = ((EditText ) findViewById(R . id. edit_url)). getText(). toString(). trim();
258
+ Bundle extras = new Bundler (). add(DownloadTask . PARAM_URL , url). build();
259
+ Groundy . create(DownloadExample . this , DownloadTask . class)
260
+ .receiver(mReceiver)
261
+ .params(extras)
262
+ .queue();
263
+
264
+ mProgressDialog = new ProgressDialog (MainActivity . this );
265
+ mProgressDialog. setProgressStyle(ProgressDialog . STYLE_HORIZONTAL );
266
+ mProgressDialog. setCancelable(false );
267
+ mProgressDialog. show();
268
+ }
269
+ });
270
+ }
271
+
272
+ private ResultReceiver mReceiver = new ResultReceiver (new Handler ()) {
273
+ @Override
274
+ protected void onReceiveResult (int resultCode , Bundle resultData ) {
275
+ super . onReceiveResult(resultCode, resultData);
276
+ switch (resultCode) {
277
+ case Groundy . STATUS_PROGRESS:
278
+ mProgressDialog. setProgress(resultData. getInt(Groundy . KEY_PROGRESS ));
279
+ break ;
280
+ case Groundy . STATUS_FINISHED:
281
+ Toast . makeText(DownloadExample . this , R . string. file_downloaded, Toast . LENGTH_LONG );
282
+ mProgressDialog. dismiss();
283
+ break ;
284
+ case Groundy . STATUS_ERROR:
285
+ Toast . makeText(DownloadExample . this , resultData. getString(Groundy . KEY_ERROR ), Toast . LENGTH_LONG ). show();
286
+ mProgressDialog. dismiss();
287
+ break ;
288
+ }
289
+ }
290
+ };
291
+ }
292
+ ```
293
+
294
+ ** Groundy ** 使用一个`GroundyTask `的实现类来下载文件和显示进度:
295
+
296
+ ```java
297
+ public class DownloadTask extends GroundyTask {
298
+ public static final String PARAM_URL = " com.groundy.sample.param.url" ;
299
+
300
+ @Override
301
+ protected boolean doInBackground () {
302
+ try {
303
+ String url = getParameters(). getString(PARAM_URL );
304
+ File dest = new File (getContext(). getFilesDir(), new File (url). getName());
305
+ DownloadUtils . downloadFile(getContext(), url, dest, DownloadUtils . getDownloadListenerForTask(this ));
306
+ return true ;
307
+ } catch (Exception pokemon) {
308
+ return false ;
309
+ }
310
+ }
311
+ }
312
+ ```
313
+
314
+ 添加这行代码到清单文件中:
315
+ ```
316
+ < service android: name= " com.codeslap.groundy.GroundyService" / >
317
+ ```
318
+
319
+ 这实在是太简单了!只需要从[Github](https:// github.com/casidiablo/groundy/downloads)上下载最新的jar文件就可以开始了。但是要记住,Groundy的主要用途是在后台服务中调用外部的REST API,然后更简单地在UI上更新结果。如果你要在你的应用里面做类似的事情,这个库将非常有帮助。
320
+
321
+ ##### 2.2 使用[ion](https:// github.com/koush/ion)
322
+
323
+ #### 3. 使用`DownloadManager`类(只适用于GingerBread及其以上的系统)
324
+
325
+ 这个方法很酷炫,你不需要担心手动下载文件、处理线程和流之类等乱七八糟的东西。GingerBread带来一项新功能:`DownloadManager`。`DownloadManager`允许你轻松地下载文件和把复杂计算的任务委托给系统。
326
+
327
+ 首先,我们来看一下工具方法:
328
+
329
+ ```java
330
+ /**
331
+ * @param 使用context来检查设备信息和 DownloadManager 的信息
332
+ * @return 如果downloadmanager可用则返回 true
333
+ */
334
+ public static boolean isDownloadManagerAvailable (Context context ) {
335
+
336
+ if (Build . VERSION. SDK_INT >= Build . VERSION_CODES. GINGERBREAD ) {
337
+ return true ;
338
+ }
339
+ return false ;
340
+ }
341
+ ```
342
+
343
+ 方法的名字就已经告诉了我们一切,只有当你确保可以使用`DownloadManager `的时候,你才可以做下面的事情:
344
+
345
+ ```java
346
+ String url = " url you want to download" ;
347
+ DownloadManager . Request request = new DownloadManager .Request (Uri . parse(url));
348
+ request.setDescription ("Some descrition ");
349
+ request.setTitle ("Some title ");
350
+ // in order for this if to run, you must use the android 3.2 to compile your app
351
+ // 为了保证这个if语句会运行,你必须使用android 3.2来编译 (译者注:应该是大于android 3.2的版本)
352
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .HONEYCOMB ) {
353
+ request. allowScanningByMediaScanner();
354
+ request. setNotificationVisibility(DownloadManager . Request . VISIBILITY_VISIBLE_NOTIFY_COMPLETED );
355
+ }
356
+ request.setDestinationInExternalPublicDir (Environment .DIRECTORY_DOWNLOADS , "name -of -the -file .ext ");
357
+
358
+ // 获得下载服务和队列文件
359
+ DownloadManager manager = (DownloadManager ) getSystemService(Context . DOWNLOAD_SERVICE );
360
+ manager.enqueue (request );
361
+ ```
362
+
363
+ #### 最后的一些思考
364
+
365
+ 第一个和第二个方法只是冰山一角。如果你想你的应用更加健壮,你得留意许多事情。这里是一些建议:
366
+
367
+ + 你必须检查用户是否有Internet 连接。
368
+ + 确保你有正确的权限(`Internet `和`WRITE_EXTERNAL_STORAGE `),如果要检查网络可用性,你还需要`ACCESS_NETWORK_STATE `权限。
369
+ + 确保你要保存下载文件的目录存在,并且有相应的写入权限。
370
+ + 如果下载的文件太大,你可能需要实现一种方法来确保上次的请求失败后,可以接着从来。
371
+ + 如果可以有暂停或者取消下载的选项,用户会很感激你的!
372
+
373
+ 除非你想对下载过程有绝对的控制权,否则我强烈推荐你使用`DownloadManager `。因为他已经处理好了上面的大部分建议。
0 commit comments