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;
    }
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Device Info HW是适用于Android设备的硬件和软件信息应用程序。 它正在尝试检测智能手机的组件,以提供有关设备硬件的完整信息。 现在支持检测LCD,触摸屏,相机,传感器,内存,闪存,音频,NFC,充电器,W-FI和电池;如果可能的话,则适用于您的设备。 我认为应用程序对于构建内核或android的用户和开发人员而言非常有趣和有用。 应用程序具有快速导航,新颖的设计,还支持深色主题。 您可以按选项卡切换或使用导航面板。许多项目都是可单击的,您可以转到另一个选项卡或菜单。 设备信息硬件组件 LCD –型号,有时甚至是厂商。对于某些平台,检测需要root用户。 您也可以在LCD测试中检查颜色。 触摸屏–型号,您可以检查多点触摸测试中支持多少手指。 相机–某些平台的型号,供应商,分辨率也可以自动对焦。 如果无法检测到,有时会提供支持的摄像机列表。 硬件信息(按相机型号)和软件(按API)。 对于默认使用5.1+的camera2 api,如果您授予了摄像头许可,则将使用旧api。 设备中有关SoC的详细信息。 CPU:型号,核心,群集,系列,abi,调速器,频率。 GPU:型号,厂商,opengl,频率,扩展列表。 单击时钟速度以打开CPU监视器。 系统:有关固件版本的完整信息。 内存:输入lpddr和工作频率。 闪存:芯片和供应商emmc或ufs(scsi)。 您可以转到内存选项卡,查看内存和存储的使用情况。 电池:基本信息,某些设备还提供其他信息: –放电速度是电流消耗。 –充电速度是充电电流减去电流消耗。 –来自内核的配置文件。仅供参考,仅适用于出厂电池。 –模型。 热量:由温度传感器测得的温度。 传感器:基本传感器的可用性和测试。与我的应用程序“传感器测试”互动。 驱动程序:您可以找到设备中使用的其他芯片。 分区:分区列表及其大小。 PMIC:应用于组件的功率调节器电压的列表。 输入设备:输入设备列表。 应用程序:您可以快速找到应用程序并查看有关它的信息,还提供了系统应用程序的列表。 设备信息硬件附加选项: –显示芯片的i2c地址。 –打开mtk和xiaomi的工程菜单。 –高通,mtk,HiSilicon的CPU代号列表。 –显示具有root访问权限的内核命令行。 设备数据库 您可以找到其他设备的信息,比较并检查类似的驱动程序。它可以在以下网页上找到:http://deviceinfohw.ru 也可以上传设备信息。请参阅信息中心。 设备信息硬件专业版 主题 同时支持明暗主题,选择自己喜欢的主题。 在免费版本中,测试仅需2周即可变暗。 报告 您可以创建包含有关设备信息的报告。 它将保存在html文件中。 您可以打开它或通过共享按钮发送到电子邮件。 请参见示例: http : //www.deviceinfohw.ru/data/report_example.html i2c清单 按总线分组的i2c设备列表。 当智能手机具有许多i2c设备时,此功能很有用。 一些免费标签已被删除。 App Defender可保护您的副本。 这也支持开发以改善应用程序。 支持的平台: 完整:高通,联发科,Exynos,Rockchip,HiSilicon 基本:英特尔,展讯等 低端:某些具有android 7.0+ 注意: –并非所有设备都能读取驱动程序信息,这取决于供应商,供应商。如果需要帮助,请上传设备信息。 –在某些版本为7.0+的设备上,已禁用sysfs读取,并且某些信息不可用。尝试使用root。 如果您想为自己的语言翻译应用程序,或者有有趣的想法或发现错误,请给我写电子邮件或论坛。 要求: – Android 4.0.3及更高版本 权限: –需要INTERNET才能上传设备信息。仅用于手动上传。 –要获取旧相机API的相机软件特征,必须使用CAMERA。 –有关Wi-Fi连接的信息,需要ACCESS_WIFI_STATE。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值