zoukankan      html  css  js  c++  java
  • android实现文件下载功能的3种方法


    一、在android2.3以前要调用系统内部的下载程序进行下载,是没法直接调用调用的,只有通过浏览器进行调用,如下:


    Uri uri = Uri.parse(fileUrl);
    Intent downloadIntent = new Intent(Intent.ACTION_VIEW, uri);
    startActivity(downloadIntent);

    这样就可以直接调用系统的文件进行下载,这样有个好处,就是当前应用可以无须声明任权限即可下载东西,所以并不是没有访问网络权限的应用它就不能访问网络,只能说不能直接访问网络。

    这里下载后的文件存放在/mnt/sdcard/download目录下面。如果当前手机的sdcard不能用,那么将会导致下载失败,但只在sdcard可用时,这个任务可以继续下载。


    这里有个不方便控制的地方,就是文件交给它下载后,就不知道什么时候它下载完成了,如果要想知道什么时候下载完成,还得监测sd卡上面的那个文件的大小是不是和下载的url所访问得到的content-length一样。


    二、

    本文地址:http://blog.csdn.net/whyrjj3/article/details/8000740

    android2.3及以后,系统把内部的下载程序开放出来了。让我们可以使用DownloadManager这个类了。使用方法如下:

        DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
    		
    	Uri uri = Uri.parse("fileUrl");
    	Request request = new Request(uri);
    
    	//设置允许使用的网络类型,这里是移动网络和wifi都可以  
    	request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE|DownloadManager.Request.NETWORK_WIFI);  
    
    	//禁止发出通知,既后台下载,如果要使用这一句必须声明一个权限:android.permission.DOWNLOAD_WITHOUT_NOTIFICATION  
    	//request.setShowRunningNotification(false);  
    
    	//不显示下载界面  
    	request.setVisibleInDownloadsUi(false);
            /*设置下载后文件存放的位置,如果sdcard不可用,那么设置这个将报错,因此最好不设置如果sdcard可用,下载后的文件        在/mnt/sdcard/Android/data/packageName/files目录下面,如果sdcard不可用,设置了下面这个将报错,不设置,下载后的文件在/cache这个  目录下面*/
    //request.setDestinationInExternalFilesDir(this, null, "tar.apk");
    long id = downloadManager.enqueue(request);
    //TODO 把id保存好,在接收者里面要用,最好保存在Preferences里面



    这里注意的是这时候程序就必须至少声明两个权限:

    <uses-permission android:name="android.permission.INTERNET" />  
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


    用这个方法有好处,用户可以控制下载的过程,即如果没有下载完,并且不想下载了,可以终止下载,并且可以注册一个广播接收者,如果文件一下载完,就可以接收到一个广播。然后可以得到下载后的文件的路径:

    package cn.dotcreate.testProcess;
    
    import android.app.DownloadManager;
    import android.app.DownloadManager.Query;
    import android.content.BroadcastReceiver;
    import android.content.Context;
    import android.content.Intent;
    import android.database.Cursor;
    import android.net.Uri;
    import android.widget.Toast;
    
    public class CompleteReceiver extends BroadcastReceiver {
    
    	private DownloadManager downloadManager;
    
    	@Override
    	public void onReceive(Context context, Intent intent) {
    		
    		String action = intent.getAction();
    		if(action.equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
    			Toast.makeText(context, "下载完成了....", Toast.LENGTH_LONG).show();
    			
    			long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);                                                                                      //TODO 判断这个id与之前的id是否相等,如果相等说明是之前的那个要下载的文件
    			Query query = new Query();
    			query.setFilterById(id);
    			downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
    			Cursor cursor = downloadManager.query(query);
    			
    			int columnCount = cursor.getColumnCount();
    			String path = null;                                                                                                                                       //TODO 这里把所有的列都打印一下,有什么需求,就怎么处理,文件的本地路径就是path
    			while(cursor.moveToNext()) {
    				for (int j = 0; j < columnCount; j++) {
    					String columnName = cursor.getColumnName(j);
    					String string = cursor.getString(j);
    					if(columnName.equals("local_uri")) {
    						path = string;
    					}
    					if(string != null) {
    						System.out.println(columnName+": "+ string);
    					}else {
    						System.out.println(columnName+": null");
    					}
    				}
    			}
    			cursor.close();
    		//如果sdcard不可用时下载下来的文件,那么这里将是一个内容提供者的路径,这里打印出来,有什么需求就怎么样处理                                                   if(path.startsWith("content:")) {
                                   cursor = context.getContentResolver().query(Uri.parse(path), null, null, null, null);
                                   columnCount = cursor.getColumnCount();
                                   while(cursor.moveToNext()) {
                                        for (int j = 0; j < columnCount; j++) {
                                                    String columnName = cursor.getColumnName(j);
                                                    String string = cursor.getString(j);
                                                    if(string != null) {
                                                         System.out.println(columnName+": "+ string);
    						}else {
    							System.out.println(columnName+": null");
    						}
    					}
    				}
    				cursor.close();
    			}
    			
    		}else if(action.equals(DownloadManager.ACTION_NOTIFICATION_CLICKED)) {
    			Toast.makeText(context, "点击<span style="font-family: 宋体; ">通知</span><span style="font-size: 10.5pt; text-indent: 21pt; font-family: 宋体; ">了....", Toast.LENGTH_LONG).show();</span>
    		}
    	}
    }
    


    在清单里面注册当前这个receiver:

    <receiver android:name=".CompleteReceiver">
                <intent-filter>
                    <action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
                    <action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED"/>
                </intent-filter>
            </receiver>


        需要说明的是在如果手机的sdcard可用,那么在上面那一步里面的path就是sdcard上面的路径,如果sdcard不可用,那么那个路径将是一个内容提供者的路径。


    三、

    A.创建一个一个URL对象url = new URL(urlStr);这个url可以直接是网络下载地址。
    B.通过URL对象,创建一个HttpURLConnection对象
    // 创建一个Http连接
    HttpURLConnection urlConn = (HttpURLConnection) url
    					.openConnection();
    C.得到InputStram,这个输入流相当于一个管道,将网络上的数据引导到手机上。但是单纯的对于InputStram不好进行操作,它是字节流,因此用InputStreamReader把它转化成字符流。然后在它上面再套一层BufferedReader,这样就能整行的读取数据,十分方便。这个在java的socket编程中我们已经见识过了。
    // 使用IO流读取数据
    buffer = new BufferedReader(new InputStreamReader(urlConn
    					.getInputStream()));
    D.从InputStream当中读取数据
    		while ((line = buffer.readLine()) != null) {
    				sb.append(line);}	
    2.文件存到sd卡中
    SDPATH = Environment.getExternalStorageDirectory() + "/" 
    File dir = new File(SDPATH + dirName);
    dir.mkdirs();
    File file = new File(SDPATH + dirName + fileName);
    file.createNewFile()
    url = new URL(urlStr);这个url可以直接是网络下载地址。
    HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
    inputStream  inputStream =urlConn.getInputStream()
    output = new FileOutputStream(file);
    byte buffer [] = new byte[4 * 1024];
    while((inputStream.read(buffer)) != -1)
    {
    output.write(buffer);
    }//

  • 相关阅读:
    android从资源文件中读取文件流显示
    Android利用Bundle实现Activity间消息的传递
    MyEclipse 9本地安装插件的方法
    XXE漏洞利用详解
    批处理编写
    初见提权
    个人对ip的理解
    业务逻辑漏洞利用
    NTFS安全权限
    Windows系统管理
  • 原文地址:https://www.cnblogs.com/xieyuan/p/3787523.html
Copyright © 2011-2022 走看看