android 实现检测版本,下载apk更新(附源码)

其实这不是什么难事了,都有热更新的技术了,只是记录一下,大神勿嘲笑。

先说下思路,首先要有更新的接口,只要进入app,就监测一下接口,是否更新,更新的话,检测本地版本是否低于接口返回的版本,低的话,就根据返回的路径下载apk更新。接口返回的字段起码有 更新标志、更新版本,更新描述,apk下载地址。

更新标志应该有三种状态,更新,询问更新,强制更新,可以启动一个Service(不要忘记在清单文件中注册)来进行检查更新以及下载的工作;

这下面就是 Service里的全部代码,也不是很难理解,重要的地方都有注释。写好Service后,在代码中 startService()启动就可以了。

这里面弹出了一个讯问框,需要在清单文件中 加入权限,  <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />,这是弹出全局讯问框的权限。

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Service;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.example.sdtz.wenmingweifang.R;
import com.example.sdtz.wenmingweifang.Tool.OkHttpUtil;
import com.example.sdtz.wenmingweifang.Util.App;
import com.example.sdtz.wenmingweifang.Util.MyUrl;

import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by sdtz on 2017/7/1.
 */
public class UpdateService extends Service {
    private ProgressBar mProgressBar;//进度条
    private TextView tv1;
    private TextView tv2;
    private String url = MyUrl.Httpurl;
    private String VersionCode;
    private String result;
    private App app;
    private String mSavePath;//apk保存地址
    private String mVersion_path;
    private String mVersion_name = "app.apk";//apk名
    private float length;
    private Dialog mDownloadDialog;//对话框
    private int mProgress;//进度值
    private static final int DOWNLOADING = 1;//apk下载中
    private static final int DOWNLOAD_FINISH = 2;//apk下载完毕
    private boolean mIsCancel = false;//是否取消下载标示符

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private Handler mUpdateProgressHandler = new Handler(){
        public void handleMessage(Message msg) {
            switch (msg.what){
                case DOWNLOADING:
                    // 设置进度条
                    mProgressBar.setProgress(mProgress);
                    tv1.setText( mProgress + "/100");
                    float len = length/1024/1024;//将length转换为M单位
                    float b = (float)(Math.round(len*100))/100;//保留两位小数点
                    tv2.setText( b+"M");
                    break;
                case DOWNLOAD_FINISH:
                    // 隐藏当前下载对话框
                    mDownloadDialog.dismiss();
                    // 安装 APK 文件
                    installAPK();
                    break;
                default:
                    break;
            }
        };
    };
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        try {
            VersionCode = getVersionName();
         /*   getJsonReuslt();*/
            new OkHttpUtil().getJson(MyUrl.appdown, new OkHttpUtil.HttpCallBack() {
                @Override
                public void onSusscess(String data) throws JSONException {
                    JSONObject jo1 = new JSONObject(data);
                    app = new App();
                    app.setVersion(jo1.getString("version").toString());
                    app.setDescription(jo1.getString("description").toString());
                    app.setUrl(MyUrl.Httpurl+jo1.getString("url").toString());
                    app.setUpdate_flag(jo1.getString("update_flag").toString());

                    mVersion_path = app.getUrl();
                    //手机当前版本
                    String phoneVersion = VersionCode.substring(0,VersionCode.lastIndexOf("."));
                    Double jiekou = Double.parseDouble(app.getVersion());
                    Double bendi = null;
                    try {
                        bendi = Double.parseDouble(getVersionName());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    Log.d("==","接口:"+jiekou+"本地:"+bendi+"::"+app.toString());
                    //本地版本 与 接口返回版本 不一致,并且 更新标志为1 ,则更新
                    if( !VersionCode.equals(app.getVersion()) && (jiekou>bendi) && app.getUpdate_flag().equals("1")){
                        Log.d("==","::进入");
                        showDialog(app.getDescription());
                    }else if( !VersionCode.equals(app.getVersion()) && (jiekou>bendi) && app.getUpdate_flag().equals("2")){
                        showDownloadDialog();
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }

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

    /*
     * 获取当前程序的版本号
     */
    private String getVersionName() throws Exception{
        //获取packagemanager的实例
        PackageManager packageManager = getPackageManager();
        //getPackageName()是你当前类的包名,0代表是获取版本信息
        PackageInfo packInfo = packageManager.getPackageInfo(getPackageName(), 0);
        return packInfo.versionName;
    }

    private void showDialog(String drc) {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this,AlertDialog.THEME_HOLO_LIGHT);
        builder.setMessage(drc);

        builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                showDownloadDialog();
            }
        });

        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
               dialogInterface.dismiss();
            }
        });

        AlertDialog alertDialog = builder.create();
        alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        alertDialog.setCanceledOnTouchOutside(true);

        alertDialog.show();

        alertDialog.getButton(alertDialog.BUTTON_POSITIVE).setTextColor(Color.GREEN);
        alertDialog.getButton(alertDialog.BUTTON_NEGATIVE).setTextColor(Color.RED);

    }

    /*
     * 开启新线程下载文件
     */
    private void downloadAPK() {

        new Thread(new Runnable() {
            @Override
            public void run() {
                try{//检查sd是否挂载
                    if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
                        String sdPath = Environment.getExternalStorageDirectory() + "/";
                        mSavePath = sdPath + "WenmingDownload";

                        File dir = new File(mSavePath);
                        if (!dir.exists())
                            dir.mkdir();
                        // 下载文件
                        HttpURLConnection conn = (HttpURLConnection) new URL(mVersion_path).openConnection();
                        conn.connect();
                        InputStream is = conn.getInputStream();
                        length = conn.getContentLength();
                        File apkFile = new File(mSavePath, mVersion_name);
                        FileOutputStream fos = new FileOutputStream(apkFile);

                        int count = 0;
                        byte[] buffer = new byte[1024];
                        while (!mIsCancel){
                            int numread = is.read(buffer);
                            count += numread;
                            // 计算进度条的当前位置
                            mProgress = (int) ((count/length) * 100);
                            // 更新进度条
                            mUpdateProgressHandler.sendEmptyMessage(DOWNLOADING);

                            // 下载完成
                            if (numread < 0){
                                mUpdateProgressHandler.sendEmptyMessage(DOWNLOAD_FINISH);
                                break;
                            }
                            fos.write(buffer, 0, numread);
                        }
                        fos.close();
                        is.close();
                    }
                }catch(Exception e){
                    e.printStackTrace();
                }
            }
        }).start();
    }

    /*
    * 下载到本地后执行安装
    */
    protected void installAPK() {
        File apkFile = new File(mSavePath, mVersion_name);
        if (!apkFile.exists())
            return;

        Intent intent = new Intent(Intent.ACTION_VIEW);
        Uri uri = Uri.parse("file://" + apkFile.toString());
        intent.setDataAndType(uri, "application/vnd.android.package-archive");
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        this.startActivity(intent);

    }
    /*
     * 显示正在下载对话框
     */
    protected void showDownloadDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("版本更新,下载中。。。");
        View view = LayoutInflater.from(this).inflate(R.layout.dialog_progress, null);
        mProgressBar = (ProgressBar) view.findViewById(R.id.id_progress);
        tv1 = (TextView) view.findViewById(R.id.tv1);
        tv2 = (TextView) view.findViewById(R.id.tv2);
        builder.setView(view);
        mDownloadDialog = builder.create();
        mDownloadDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        mDownloadDialog.show();

        // 下载文件
        downloadAPK();
    }

}

  

原文地址:https://www.cnblogs.com/andzhang/p/8311470.html

时间: 2024-08-29 05:21:54

android 实现检测版本,下载apk更新(附源码)的相关文章

ANDROID自定义视图——仿瀑布布局(附源码)

简介: 在自定义view的时候,其实很简单,只需要知道3步骤: 1.测量--onMeasure():决定View的大小 2.布局--onLayout():决定View在ViewGroup中的位置 3.绘制--onDraw():如何绘制这个View. 第3步的onDraw系统已经封装的很好了,基本不用我们来操心,只需要专注到1,2两个步骤就中好了. 第一步的测量,可以参考:(ANDROID自定义视图--onMeasure,MeasureSpec源码 流程 思路详解) 第二步的布局,可以参考:(AN

Android高仿QQ消息滑动删除(附源码)

大家都应该使用过QQ吧,他的消息中可以滑动删除功能,我觉得比较有意思,所以模仿写了一个,并且修改了其滑动算法.我先贴几个简单示范图吧 其实主要用的是算法以及对ListView的把控. 一下是适配器的类 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52

Android中AIDL实现进程通信(附源码下载)

AIDL概述 之前的博客<Android中通过Messenger与Service实现进程间双向通信>演示了如何通过Messenger实现与Service进行跨进程通信,即IPC.但用Messenger实现的IPC存在一点不足:Service内部维护着一个Messenger,Messenger内部又维护着一个Hanlder,当多个client向该Service发送Message时,这些Message需要依次进入Hanlder的消息队列中,Hanlder只能处理完一个Message之后,再从消息队

Android中常见Intent习惯用法-上篇(附源码下载)

Android中的Intent是一个非常重要的类,如果对Intent不是特别了解,可以参见博文<Android中Intent概述及使用>.如果对Intent Filter不是特别了解,可以参见博文<Android中Intent对象与Intent Filter过滤匹配过程详解>. 本文着重讲一下Android中一些常见的Intent的习惯用法,比如如何通过Intent发送短信.发送邮件.启动摄像机拍照录视频.设置闹铃.打开WIFI设置界面等等. 限于篇幅,本博文分为上下两篇,这是上篇

【Android数据存储】SQLite使用实例(附源码)(转载)

原文地址:http://blog.csdn.net/wirelessqa/article/details/8583101 java当中提供了相当多的封装好的类来执行对SqlLite的操作,如: SQLiteDatabase 作为数据库操作的类,类似于C#当中我们自己写的helper,PS(java对此还真是高度封装) SQLiteOpenHelper 作为作为维护和管理数据库的基类实例: 会员信息管理 功能:1.查看数据库 2.清空数据库 3.增加会员 4.删除会员 5.更新会员 6.查找会员

Android开发之拍照功能实现(附源码)

大家好,这是一个简单的拍照功能,很简单的界面,一个显示图像区域SurfaceView一个“拍照”按钮.直接上代码! 1.CameraDemoActivity.java(主界面) package org.winplus.camera; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.util.Date; import android.app.Activity;

转载—— android 瀑布流的实现详解,附源码

介绍 参考自:https://github.com/dodola/android_waterfall,因为原来的代码封装不好,所以,我根据源码的思路,重新写了一遍,所以有了现在这个项目:https://github.com/youxilua/waterfall4android 原作者表示: 试过在1万张可以流畅的滑动,不出现内存溢出情况 设计思路 之前的作者的自定义view 只有主滑动一层,其他的设置要在相应的活动设置,个人觉得,重用起来比较麻烦,所以决定封装一层.现在定义一个默认的瀑布流只需5

Android自动检测版本及自动升级

步骤: 1.检测当前版本的信息AndroidManifest.xml-->manifest-->android:versionName. 2.从服务器获取版本号(版本号存在于xml文件中)并与当前检测到的版本进行匹配,如果不匹配,提示用户进行升级,如果匹配则进入程序主界面. 3.当提示用户进行版本升级时,如果用户点击了确定,系统将自动从服务器上下载并进行自动升级,如果点击取消将进入程序主界面. 效果图:        获取当前程序的版本号: [java] view plaincopy /* *

Android UI开发: 横向ListView(HorizontalListView)及一个简单相册的完整实现 (附源码下载)

Android UI开发: 横向ListView(HorizontalListView)及一个简单相册的完整实现 (附源码下载) POSTED ON 2014年6月27日 BY 天边的星星 本文内容: 1.横向ListView的所有实现思路; 2.其中一个最通用的思路HorizontalListView,并基于横向ListView开发一个简单的相册: 3.实现的横向ListView在点击.浏览时item背景会变色,并解决了listview里setSelected造成item的选择状态混乱的问题.