zoukankan      html  css  js  c++  java
  • DownloadManager系统自带下载实现apk后台下载功能

    DownloadManager是android2.3以后,系统下载的方法,是处理长期运行的HTTP下载的系统服务。客户端可以请求的URI被下载到一个特定的目标文件。客户端将会在后台与http交互进行下载,或者在下载失败,或者连接改变,重新启动系统后重新下载。还可以进入系统的下载管理界面查看进度。DownloadManger有两个内部类,Request 和Query。Request类可设置下载的一些属性。Query类可查询当前下载的进度,下载地址,文件存放目录等数据。

    DownloadManager

    1、所需权限

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

     2、获得对象,开始下载

    DownloadManager downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
    DownloadManager.Request request = new DownloadManager.Request(Uri.parse(apkUrl));
    long id = downloadManager.enqueue(request);
    //每下载的一个文件对应一个id,通过此id可以查询数据。
    

     3、取消下载

    downloadManager.remove(REFERENCE_1, REFERENCE_2, REFERENCE_3);  
    

     该方法返回成功取消的下载的个数,如果一个下载被取消了,所有相关联的文件,部分下载的文件和完全下载的文件都会被删除.


    Request类

    1.指定下载位置,及文件名称

          /**
             * 方法1: 
             * 目录: Android -> data -> com.app -> files -> Download -> dxtj.apk
             * 这个文件是你的应用所专用的,软件卸载后,下载的文件将随着卸载全部被删除
             */
      request.setDestinationInExternalFilesDir( this , Environment.DIRECTORY_DOWNLOADS ,  "dxtj.apk" );  
    
            /**
             * 方法2:
             * 下载的文件存放地址  SD卡 download文件夹,dxtj.apk
             * 软件卸载后,下载的文件会保留
             */
            //在SD卡上创建一个文件夹
        request.setDestinationInExternalPublicDir(  "/epmyg/"  , "dxtj.apk" ) ;  
    
    
            /**
             * 方法3:
             * 如果下载的文件希望被其他的应用共享
             * 特别是那些你下载下来希望被Media Scanner扫描到的文件(比如音乐文件)
             */
         request.setDestinationInExternalPublicDir( Environment.DIRECTORY_MUSIC,  "告白气球.mp3" );  
    
            /**
             * 方法4
             * 文件将存放在外部存储的确实download文件内,如果无此文件夹,创建之,如果有,下面将返回false。
             * 系统有个下载文件夹,比如小米手机系统下载文件夹  SD卡--> Download文件夹
             */
            //创建目录
         Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).mkdir() ; 
    
            //设置文件存放路径
         request.setDestinationInExternalPublicDir(  Environment.DIRECTORY_DOWNLOADS  , "dxtj.apk" ) ;
        }
    

     2、指定下载的网络类型

    //指定在WIFI状态下,执行下载操作。
    request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
    //指定在MOBILE状态下,执行下载操作
    request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE);
    //是否允许漫游状态下,执行下载操作
    request.setAllowedOverRoaming(boolean);
    //是否允许“计量式的网络连接”执行下载操作
    request.setAllowedOverMetered(boolean); //默认是允许的。
    

     3、定制Notification样式

    //设置Notification的标题和描述
    request.setTitle("标题");  
    request.setDescription("描述"); 
    //设置Notification的显示,和隐藏。
    request.setNotificationVisibility(visibility);
    

     VISIBILTY_HIDDEN: Notification:将不会显示,如果设置该属性的话,必须要添加权限

    Android.permission.DOWNLOAD_WITHOUT_NOTIFICATION. 
    

    VISIBILITY_VISIBLE: Notification显示,但是只是在下载任务执行的过程中显示,下载完成自动消失。(默认值)
    VISIBILITY_VISIBLE_NOTIFY_COMPLETED : Notification显示,下载进行时,和完成之后都会显示。
    VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION :只有当任务完成时,Notification才会显示。
    对Notification的设定方法相对较少。

    4、设置下载文件类型:

    request.setMimeType("application/vnd.android.package-archive");
    

    这是安卓.apk文件的类型。有些机型必须设置此方法,才能在下载完成后,点击通知栏的Notification时,才能正确的打开安装界面。不然会弹出一个Toast(can not open file).其他文件类型的MimeType ,去百度一下 。

    5、添加请求下载的网络链接的http头,比如User-Agent,gzip压缩等:

    request.addRequestHeader(String header, String value);
    

    Query 类

    我们的需求,可能不只是在Notification 中显示进度就好了,也许,在app中也需要获取实时下载进度。所以Query类就是提供查询的一些方法。
    但API中就只有两个方法,原来,他把数据保存在数据库中去了。我们需要获得一个Cursor 结果集,通过结果集获得我们想要的数据。

    DownloadManager.Query query = new DownloadManager.Query();
     Cursor cursor = downloadManager.query(query.setFilterById(id));
                    if (cursor != null && cursor.moveToFirst()) {
                        //下载的文件到本地的目录
                        String address = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                        //已经下载的字节数
                        int bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                        //总需下载的字节数
                        int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
                        //Notification 标题
                        String title =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TITLE));
                        //描述
                        String description =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_DESCRIPTION));
                        //下载对应id
                        long id =cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_ID));
                        //下载文件名称
                        String filename =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
                        //下载文件的URL链接
                        String url =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_URI));
    }
    

    这只能获取一次,数据库中的信息。我们可以使用Timer类,每隔一段时间去查询数据库即可。也可以使用ContentProvider去访问。

    不足之处:

    1、我发现,在下载的时候,发送Notification时 是没有声音的。也没有设置声音的方法。不过这影响不大。主要的功能实现就好。
    2、因为这是系统的类,每个系统的Notification界面是不一样的。这就是每个rom厂家的自定义了。小米和魅族的就大不一样。魅族Notification上有一个下载暂停的按钮,而小米没有。所以导致Notification是不能统一的。其实,暂停的话用户可以点击notification,进入到下载管理界面,就有暂停按钮了。


    实现代码

    import android.app.DownloadManager;
    import android.content.Intent;
    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Bundle;
    import android.os.Environment;
    import android.os.Handler;
    import android.os.Message;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    import android.widget.ProgressBar;
    import android.widget.TextView;
    
    import java.util.Timer;
    import java.util.TimerTask;
    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener {
        private TextView                down;
        private TextView                progress;
        private TextView                file_name;
        private ProgressBar             pb_update;
        private DownloadManager         downloadManager;
        private DownloadManager.Request request;
        public static String downloadUrl = "http://ucdl.25pp.com/fs08/2017/01/20/2/2_87a290b5f041a8b512f0bc51595f839a.apk";
        Timer     timer;
        long      id;
        TimerTask task;
        Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Bundle bundle = msg.getData();
                int pro = bundle.getInt("pro");
                String name = bundle.getString("name");
                pb_update.setProgress(pro);
                progress.setText(String.valueOf(pro) + "%");
                file_name.setText(name);
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            down = (TextView) findViewById(R.id.down);
            progress = (TextView) findViewById(R.id.progress);
            file_name = (TextView) findViewById(R.id.file_name);
            pb_update = (ProgressBar) findViewById(R.id.pb_update);
            down.setOnClickListener(this);
            downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
            request = new DownloadManager.Request(Uri.parse(downloadUrl));
    
            request.setTitle("大象投教");
            request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
            request.setAllowedOverRoaming(false);
            request.setMimeType("application/vnd.android.package-archive");
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
            //创建目录
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).mkdir();
    
            //设置文件存放路径
            request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "app-release.apk");
            pb_update.setMax(100);
            final DownloadManager.Query query = new DownloadManager.Query();
            timer = new Timer();
            task = new TimerTask() {
                @Override
                public void run() {
                    Cursor cursor = downloadManager.query(query.setFilterById(id));
                    if (cursor != null && cursor.moveToFirst()) {
                        if (cursor.getInt(
                                cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
                            pb_update.setProgress(100);
                            install(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/app-release.apk");
                            task.cancel();
                        }
                        String title = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_TITLE));
                        String address = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                        int bytes_downloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
                        int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
                        int pro = (bytes_downloaded * 100) / bytes_total;
                        Message msg = Message.obtain();
                        Bundle bundle = new Bundle();
                        bundle.putInt("pro", pro);
                        bundle.putString("name", title);
                        msg.setData(bundle);
                        handler.sendMessage(msg);
                    }
                    cursor.close();
                }
            };
            timer.schedule(task, 0, 1000);
        }
    
        @Override
        public void onClick(View v) {
            id = downloadManager.enqueue(request);
            task.run();
            down.setClickable(false);
            down.setBackgroundResource(R.drawable.background);
    
        }
    
        private void install(String path) {
            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(Uri.parse("file://" + path), "application/vnd.android.package-archive");
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//4.0以上系统弹出安装成功打开界面
            startActivity(intent);
        }
    }
    

     progressbar_color.xml

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item android:id="@android:id/background">
            <shape>
                <corners android:radius="10dip"/>
                <gradient
                    android:angle="0"
                    android:centerColor="#e4e4e4"
                    android:centerY="0.75"
                    android:endColor="#e4e4e4"
                    android:startColor="#e4e4e4"/>
            </shape>
        </item>
        <item android:id="@android:id/secondaryProgress">
            <clip>
                <shape>
                    <corners android:radius="10dip"/>
                    <gradient
                        android:angle="0"
                        android:centerColor="#e4e4e4"
                        android:centerY="0.75"
                        android:endColor="#e4e4e4"
                        android:startColor="#e4e4e4"/>
                </shape>
            </clip>
        </item>
        <item android:id="@android:id/progress">
            <clip>
                <shape>
                    <corners android:radius="10dip"/>
                    <gradient
                        android:angle="0"
                        android:endColor="@color/red"
                        android:startColor="@color/red"/>
                </shape>
            </clip>
        </item>
    </layer-list>
    

     效果:


    本文学习来源地址:http://blog.csdn.net/u012209506/article/details/56012744


    AKP更新案例学习代码:

    import android.app.DownloadManager;
    import android.app.ProgressDialog;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.content.pm.PackageInfo;
    import android.content.pm.PackageManager;
    import android.net.Uri;
    import android.os.Bundle;
    import android.os.Environment;
    import android.support.v7.app.AlertDialog;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.loaderman.group09.redboy11.R;
    import com.loaderman.group09.redboy11.utils.PrefUtils;
    import com.zhy.http.okhttp.OkHttpUtils;
    import com.zhy.http.okhttp.callback.FileCallBack;
    import com.zhy.http.okhttp.callback.StringCallback;
    
    import org.json.JSONException;
    import org.json.JSONObject;
    
    import java.io.File;
    
    import okhttp3.Call;
    
    import static com.loaderman.global.GlobalConstants.URL_PREFIX;
    
    /*
     * @author: Ji.C.F
     * Desc   :  关于
     * date   : 2016/12/23 19:29
    */
    public class AboutActivity extends BaseActivity {
    
        private TextView tvVersion;
        private Button   btnUpdateApk;
        private String   mDownloadUrl;
        private String   versionMessage;
        private boolean  isUpdateVersion;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_about);
            ivLeft.setVisibility(View.VISIBLE);
            ivCenter.setVisibility(View.GONE);
            tvCenter.setText("关于");
            tvCenter.setVisibility(View.VISIBLE);
            btnUpdateApk = (Button) findViewById(R.id.btn_update_apk);
            tvVersion = (TextView) findViewById(R.id.tv_version);
            tvVersion.setText(getVersionName());
            isUpdateVersion = PrefUtils.getBoolean(AboutActivity.this, "isUpdateVersion", false);
            if (!isUpdateVersion) {
                btnUpdateApk.setText("当前已经是最新版本");
            } else {
                //Toast.makeText(AboutActivity.this, "有新版本可以更新了", Toast.LENGTH_SHORT).show();
                btnUpdateApk.setText("有新版本可以更新了");
            }
            btnUpdateApk.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (!isUpdateVersion) {
                        Toast.makeText(AboutActivity.this, "当前已经是最新版本了", Toast.LENGTH_SHORT).show();
                    } else {
                        updateVersion();
                    }
                }
            });
        }
    
        private void updateVersion() {
            OkHttpUtils.get().addParams("ver", getVersionCode() + "").url(URL_PREFIX + "index/index_checkVersion.html").build().execute(new StringCallback() {
                @Override
                public void onError(Call call, Exception e, int i) {
                    e.printStackTrace();
                    Toast.makeText(AboutActivity.this, "网络异常", Toast.LENGTH_SHORT).show();
                }
    
                @Override
                public void onResponse(String result, int i) {
                    try {
                        JSONObject json = new JSONObject(result);
                        String version = json.optString("version");
                        JSONObject json2 = new JSONObject(version);
                        String versionCode = json2.optString("versionCode");
                        versionMessage = json2.optString("versionMessage");
                        System.out.println(versionMessage);
                        mDownloadUrl = json2.optString("downloadUrl");
                        System.out.println(mDownloadUrl);
                        showUpdateDialog(versionCode);
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
    
                }
            });
    
        }
    
        private void showUpdateDialog(String mVersionName) {
            System.out.println("showUpdateDialog");
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setTitle("发现新版本:" + mVersionName);
            builder.setMessage(versionMessage);
            builder.setPositiveButton("前台更新", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    download();
                }
            });
            builder.setNegativeButton("后台更新", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    download(URL_PREFIX + mDownloadUrl);
                }
            });
            AlertDialog dialog = builder.create();
            dialog.show();
        }
        private void download(String downloadUrl) {
            DownloadManager manager = (DownloadManager) getApplicationContext()
                    .getSystemService(Context.DOWNLOAD_SERVICE);
            DownloadManager.Request request = new DownloadManager.Request(
                    Uri.parse(downloadUrl));
            request.setTitle("红孩子下载中...");
            request.setDescription("让你的购物从此与众不同!!!");
            request.allowScanningByMediaScanner();// 设置可以被扫描到
            request.setVisibleInDownloadsUi(true);// 设置下载可见
            String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/"));// 解析fileName
            request.setDestinationInExternalPublicDir(
                    Environment.DIRECTORY_DOWNLOADS, fileName);// 设置下载位置,sdcard/Download/fileName
            long refernece = manager.enqueue(request);// 加入下载并取得下载ID
            SharedPreferences sPreferences = getApplicationContext()
                    .getSharedPreferences("downloadplato", 0);
            sPreferences.edit().putLong("plato", refernece).commit();//保存此次下载ID
        }
        private void download() {
            //设置进度条
            final ProgressDialog progressDialog = new ProgressDialog(this);
            //水平显示
            progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            progressDialog.setTitle("拼命下载中");
            //显示
            progressDialog.show();
            OkHttpUtils.get().url(URL_PREFIX + mDownloadUrl).build().execute(new FileCallBack(Environment.getExternalStorageDirectory().getAbsolutePath(), "RedBoy.apk") {
                @Override
                public void onError(Call call, Exception e, int i) {
                    progressDialog.dismiss();
                }
    
                @Override
                public void inProgress(float progress, long total, int id) {
                    super.inProgress(progress, total, id);
                    progressDialog.setProgress((int) (progress * 100));
                }
    
                @Override
                public void onResponse(File file, int i) {
                    progressDialog.dismiss();
                    installAPK(file);
                }
            });
        }
    
        private void installAPK(File file) {
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_VIEW);
            intent.addCategory(Intent.CATEGORY_DEFAULT);
            intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
            startActivityForResult(intent, 0);
        }
    
    
        private String getVersionName() {
            PackageManager pm = getPackageManager();
            try {
                PackageInfo info = pm.getPackageInfo(getPackageName(), 0);
                String versionName = info.versionName;
                return versionName;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "";
        }
    
        private int getVersionCode() {
            PackageManager pm = getPackageManager();
            try {
                PackageInfo info = pm.getPackageInfo(getPackageName(), 0);
                int versionCode = info.versionCode;
                return versionCode;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return -1;
        }
    
    }
    
  • 相关阅读:
    (转)Android Studio解决unspecified on project app resolves to an APK archive which is not supported
    OpenGL 学习总结
    关于tap设备
    写把proto函数搞清楚
    qemu中是怎么模拟的新的设备
    kvm搭建完成了,那么问题来了,到底是什么原理
    kvm竟然抓不到kvm的tracepoint
    安装KVM
    试着理解下kvm
    网络namespace
  • 原文地址:https://www.cnblogs.com/loaderman/p/6474363.html
Copyright © 2011-2022 走看看