网络连接和下载

529 查看

连接 Internet 资源

需要在 manifest 文件中配置 <user-permission android:name="android.permission.INTERNET" />

在最新版本的 Android 上在 UI 线程上执行网络操作会引发 NetworkOnMainThreadException 异常,一定要再后台线程中执行。

try {
    URL url = new URL("http://www.baiud.com");

    // 创建 HTTP URL 连接
    URLConnection connection = url.openConnection();
    HttpURLConnection httpConnection = (HttpURLConnection) connection;

    int responseCode = httpConnection.getResponseCode();
    if (responseCode == HttpURLConnection.HTTP_OK) {
        InputStream in = httpConnection.getInputStream();
        processStream(in);
    }
} catch (Exception e) {
    Log.d("TAG", "IO Exception.");
}


下载文件

在 android 2.3(API Level 9)中引入了 Download Manager,作为一个 Service 来优化长时间下载操作的处理。Download Manager 通过处理 HTTP 连接、监控连接的变化和系统重新启动来确保每一次下载都能成功完成。

Download Manager 可以在多个回话之间在后台继续进行下载。可以通过 getSystemService 方法请求 DOWNLOAD_SERVICE 获得一个 Download Manager 对象。

String serviceString = Context.DOWNLOAD_SERVICE;
DownloadManager downloadManager;
downloadManager = (DownloadManager) getSystemService(serviceString);

Uri uri = Uri.parse("http://api.amap.com/Public/down/AMap_Android_2DMap_Lib_V2.2.0.zip");

DownloadManager.Request request = new Request(uri);

// 设置 Notification
request.setTitle("襄阳公交"); // 设置标题
request.setDescription("襄阳公交是一个很方便的产品。"); // 设置描述

// 设置 Notification 的显示模式
request.setNotificationVisibility(Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);

// 设置限制下载的网络类型(移动网络或WIFI)
// request.setAllowedNetworkTypes(Request.NETWORK_WIFI);

// 设置手机漫游时限制下载
// request.setAllowedOverRoaming(false);

// 设置根据系统限制的下载文件大小,是否要确定下载
// DownloadManager.getRecommendedMaxBytesOverMobile(this);

// 使下载的文件可以被扫描器扫描到
request.allowScanningByMediaScanner();

// 使 系统的下载管理器中可以查看到
request.setVisibleInDownloadsUi(true);

默认情况下下载的文件是不会被扫描到的

Request 的 setNotificationVisibility 方法支持一下几种显示方式:

  1. Request.VISIBILITY_VISIBLE 下载时显示,下载完成移除
  2. Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED 下载时和下载完成都显示,选择或取消时移除
  3. Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETED 下载完成后显示
  4. Request.VISIBILITY_HIDDENT 不显示,不过需要指定 DOWNLOAD_WITHOUT_NOTIFITICATION 的权限时有效。


指定下载文件位置

默认情况下,DownloadManager 会把下载的文件保存在共享下载缓存中,而且使用系统生成的文件名。每个下载文件都可以指定一个下载位置,但是所有的下载都必须存储到外部存储器中。而且需要设置外部存储器的写入权限:
<uses-permission android:name="android.permission.WRITE_EXTRANL_STORAGE" />



指定下载路径:

// 在外部存储器上指定文件路径
request.setDestinationUri(Uri.fromFile(f));

// 在应用程序的外部存储文件夹中存储一个文件
request.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, "tm.apk");

// 外部存储器的公共目录下指定一个文件夹来存储文件
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_MUSIC, "android.mp3");

取消和删除下载

可以通过 DownloadManager 的 remove 方法取消一个正在等待的下载。已经下载的关联文件也会被删除。
downloadManager.remove(myReference);

查询 Download Manager

可以通过 query 方法查询 DownloadManager 来得到下载请求的状态、进度和详细信息,该方法会返回下载的 Cursor 对象。

BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        long reference = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
        if (myReference == reference) {
            Query query = new Query();
            query.setFilterById(myReference);

            Cursor cursor = downloadManager.query(query);
            if (cursor.moveToFirst()) {
                int fileNameIdx = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME);
                int fileUriIdx = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);

                String fileName = cursor.getString(fileNameIdx);
                String fileUri = cursor.getString(fileUriIdx);
            }

            cursor.close();
        }
    }
};