android 利用dwonLoadManager 实现apk下载更新

项目之前一直用的友盟的自动更新,但好像友盟那边10月份就开始不支持软件更新了,所以把更新的功能做到自己的服务器上面。

基本的实现思路如下:
1. 后台可以提供一个接口也可以,就是我们将当前的版本传过去,然后后台返回是否需要更新,如果需要,给出url,
2. 下载apk
3. 安装apk

具体实现:

1. 向服务器请求的结果如下

{
status: 1,
msg: "需要更新",
versionCode:1
updateUrl: "http://www.ejoooo.com/app/com.ejooo.jianli.apk"
}

后台已经帮我们判断了是否需要更新,我们只需要根据status的状态来判断是否做出进一步的操作。versionCode的作用是用来判断用户本地是否下载了最新的apk,避免重复下载。

2. 我是向后台请求数据后,弹出一个询问是否需要更新的对话框,点击确定操作后

Intent intent = new Intent(mContext.getApplicationContext(), DownLoadService.class);
                intent.putExtra(UpdateConstants.FIELD_APK_DOWNLOAD_URL, VALUE_DOWNLOAD_URL);
                intent.putExtra(UpdateConstants.FIELD_APK_NAME, appName);
                intent.putExtra(UpdateConstants.FIELD_APK_PATH, mContext.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).getPath());
mContext.startService(intent);

3.这里需要注意的是

DownLoadService 不可集成IntentService,不然写在IntentService里面的BroadCastRecieve接收不到广播。

public class DownLoadService extends Service {
    public static long DOWNLOAD_ID;
    private String downloadUrl;
    private String apkName;
    private String apkPath;
    /**
     * 安卓系统下载类
     **/
    DownloadManager manager;

    /**
     * 接收下载完的广播
     **/
    DownloadCompleteReceiver receiver;

    /**
     * 初始化下载器
     **/
    private void initDownManager() {

        manager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);

        receiver = new DownloadCompleteReceiver();

        List<String> list = FileUtils.GetFiles(apkPath, "apk", apkName, false);
        if (list.size() != 0) {
            installAPK(Uri.fromFile(new File(list.get(0))));
            return;
        }

        //设置下载地址
        DownloadManager.Request down = new DownloadManager.Request(
                Uri.parse(downloadUrl));

        // 设置允许使用的网络类型,这里是移动网络和wifi都可以
        down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE
                | DownloadManager.Request.NETWORK_WIFI);

        // 下载时,通知栏显示途中
        down.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);

        // 显示下载界面
        down.setVisibleInDownloadsUi(true);

        // 设置下载后文件存放的位置
        down.setDestinationInExternalFilesDir(this,
                Environment.DIRECTORY_DOWNLOADS, apkName + ".apk");

        // 将下载请求放入队列
        DOWNLOAD_ID = manager.enqueue(down);

        //注册下载广播
        registerReceiver(receiver, new IntentFilter(
                DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        downloadUrl = intent.getStringExtra(UpdateConstants.FIELD_APK_DOWNLOAD_URL);
        apkName = intent.getStringExtra(UpdateConstants.FIELD_APK_NAME);
        apkPath = intent.getStringExtra(UpdateConstants.FIELD_APK_PATH);
        // 调用下载
        initDownManager();

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {

        return null;
    }

    @Override
    public void onDestroy() {

        // 注销下载广播
        if (receiver != null)
            unregisterReceiver(receiver);

        super.onDestroy();
    }

    /**
     * 安装apk
     * @param apk
     */
    private void installAPK(Uri apk){
        Intent intent = new Intent();
        //执行动作
        intent.setAction(Intent.ACTION_VIEW);
        //执行的数据类型
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setDataAndType(apk, "application/vnd.android.package-archive");
        //不加下面这句话是可以的,查考的里面说如果不加上这句的话在apk安装完成之后点击单开会崩溃
        //android.os.Process.killProcess(android.os.Process.myPid());
        startActivity(intent);
    }

    // 接受下载完成后的intent
    class DownloadCompleteReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            //判断是否下载完成的广播
            if (intent.getAction().equals(
                    DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {

                //获取下载的文件id
                long downId = intent.getLongExtra(
                        DownloadManager.EXTRA_DOWNLOAD_ID, -1);

                //自动安装apk
                installAPK(manager.getUriForDownloadedFile(downId));

                //停止服务并关闭广播
                DownLoadService.this.stopSelf();

            }
        }

        /**
         * 安装apk文件
         */
        private void installAPK(Uri apk) {

            // 通过Intent安装APK文件

            Intent intent = new Intent();
            //执行动作
            intent.setAction(Intent.ACTION_VIEW);
            //执行的数据类型
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            intent.setDataAndType(apk, "application/vnd.android.package-archive");
            //不加下面这句话是可以的,查考的里面说如果不加上这句的话在apk安装完成之后点击单开会崩溃
            //android.os.Process.killProcess(android.os.Process.myPid());
            startActivity(intent);

        }

    }
}

4.如何实现避免用户重复下载的问题

具体的实现方法是通过文件查找的方法,查找下载目录下面是否有最新的apk。至于apk是否为最新的,就需要在下载的时候通过versionName+versionCode命名,更新的时候从无夫妻获取到最新的versionCode 与文件名称做比较即可。

 /**
     * 查找文件
     *
     * @param Path        文件夹路径
     * @param Extension   文件扩展名
     * @param IsIterative 是否进入子文件夹
     */
    public static List<String> GetFiles(String Path, String Extension, String fileName, boolean IsIterative) //搜索目录,扩展名,是否进入子文件夹
    {
        List<String> lstFile = new ArrayList<String>(); //结果 List
        File[] files = new File(Path).listFiles();
        if (files == null) {
            return lstFile;
        }
        for (int i = 0; i < files.length; i++) {
            File f = files[i];
            if (f.isFile()) {
                if (f.getPath().substring(f.getPath().length() - Extension.length()).equals(Extension)) { //判断扩展名
                    String name =files[i].getName();
                    if (files[i].getName().equals(fileName+".apk")) {
                        lstFile.add(f.getPath());
                    }
                }
                /*if (!IsIterative)
                    break;*/
            } else if (f.isDirectory() && f.getPath().indexOf("/.") == -1) //忽略点文件(隐藏文件/文件夹)
                GetFiles(f.getPath(), Extension, fileName, IsIterative);
        }
        return lstFile;
    }
发布了25 篇原创文章 · 获赞 14 · 访问量 49万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章