Android APK版本更新下载

        今天做了下APK版本更新的功能。其实关于APK版本更新相关的文章网上挺多的,功能实现上也并不难。基本思路就是讲当前APK的版本号和服务器上保存的最新APK包的版本号进行对比,如果当前版本小于最新版本,则进行下载更新。流程图如下:


      

        引用的第三方jar包有okhttp,okio(为了支持okhttp)和gson:

compile 'com.squareup.okio:okio:1.5.0'
compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'com.google.code.gson:gson:2.3'
        PC端里APK版本列表的数据结构如下:

        APK版本列APK_VERSION

PK

字段名称

字段别名

字段类型

字段长度

是否允许为空

True

id

标识码

NUMBER

(10)

False

False

apk_name

apk名称

NVARCHAR2

500)

False

False

apk_version

apk版本

NVARCHAR2

100)

False

False

apk_size

apk文件大小(M)

NVARCHAR2

(50)

False

False

apk_path

apk打包文件存放路径

NVARCHAR2

2000)

False

False

app_time

apk数据记录时间

NVARCHAR2

20

False

False

app_desc

apk版本更新说明

NVARCHAR2

(500)

True

False

remark

备注

NVARCHAR2

(500)

True


        对应的Android端的数据抽象类为:
public class APKVersionBean {
    private String apkversion;
    private String apkname;
    private String apksize;
    private String apkpath;
    private String apptime;
    private String apkdesr;
    private String remark;

    public String getApkversion() {
        return apkversion;
    }

    public void setApkversion(String apkversion) {
        this.apkversion = apkversion;
    }

    ...
}

        
        首先是进行版本验证功能,每个APP版本设置是在AndroidManifest文件里,如下所示:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.diit.okhttptest"
    android:versionCode="1"
    android:versionName="测试版本">
        versionCode就是版本号,要获取它可以采用 getPackageManager的方法,代码为:
public int getVerCode(Context context){
    int verCode = -1;
    try {
        verCode = context.getPackageManager().getPackageInfo("com.diit.okhttptest", 0).versionCode;
    } catch (PackageManager.NameNotFoundException e) {
        // TODO Auto-generated catch block
        Log.e("版本号获取异常", e.getMessage());
    }
    return verCode;
}
      其中com.diit.okhttptest是系统的包名。

      当当前版本号小于最新版本号时候,弹出对话框,提示用户更新代码:
AlertDialog.Builder builder = new AlertDialog.Builder(
        activity);
builder.setTitle("版本更新");//对话框标题
builder.setMessage(apkDescribe);//对话框详细内容
builder.setPositiveButton(R.string.str_button_ok,
        new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                _downloadAsyn(downUrl);//点击确定时候进行下载
        }
        });
builder.setNegativeButton(R.string.str_button_cancel, null);
builder.setCancelable(false); //设置为false时候点击返回键获取屏幕边缘,对话框也无法取消
builder.show(); // 显示这个消息框
        显示的效果为:

       
        当点击现在更新按钮时候,进入下载的方法。在下载里首先也是弹出一个进度对话框,用来跟踪下载进度:
final ProgressDialog mProgress=new ProgressDialog(activity);//进度对话框
final Message message = updateHandler.obtainMessage();
mProgress.setIcon(R.drawable.ic_launcher_lc);//小图标
mProgress.setTitle("APK文件下载中,请稍候...");//进度对话框标题
mProgress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);//进度对话框设置为水平进度条
mProgress.setCancelable(false); // 设置允许取消
mProgress.show();
        效果为:

        
        这是进度对话框初始状态,然后可以根据下载情况进行进度赋值,代码为:
final Request request = new Request.Builder()
        .url(url)
        .build();
Call call = mOkHttpClient.newCall(request);
call.enqueue(new Callback()
{
    @Override
    public void onFailure(final Request request, final IOException e)
    {
        message.what = DOWNLOAD_FAIL;
        updateHandler.sendMessage(message);
        e.printStackTrace();
    }

    @Override
    public void onResponse(Response response)
    {
        InputStream is = null;
        byte[] buf = new byte[2048];
        int len = 0;
        FileOutputStream fos = null;
        try
        {
            long total=response.body().contentLength();//获取文件大小
            mProgress.setMax((int)total);//设置进度对话框总共数值大小
            long sum = 0;
            is = response.body().byteStream();
            updateFile = new File(updateDir, apkName);
            fos = new FileOutputStream(updateFile,false);
            while ((len = is.read(buf)) != -1)
            {
                sum+=len;
                int progress=(int)(sum*100/total);
                mProgress.setProgress((int)sum);//设置进度对话框当前完成数值大小
                fos.write(buf, 0, len);
            }
            fos.flush();
            mProgress.dismiss();
            if(sum>0){
                message.what = DOWNLOAD_COMPLETE;
                updateHandler.sendMessage(message);
            }
        }
      这里利用了OkHttp包进行文件下载,响应成功时候可以获取文件大小,再根据下载的进度实时更新下进度条和进度值,如图所示:

      当下载成功后,进入安装界面
Uri uri = Uri.fromFile(updateFile);
Intent installIntent = new Intent(Intent.ACTION_VIEW);
installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
installIntent.setDataAndType(uri,
        "application/vnd.android.package-archive");

activity.startActivityForResult(installIntent,requestcode);


      好了,大概功能就是这样,下面是我封装的包,代码为:
package com.diit.okhttptest;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AlertDialog;
import android.widget.Toast;

import com.squareup.okhttp.Call;
import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.CookieManager;
import java.net.CookiePolicy;

/**
 * Created by kaki on 2017/5/17.
 */
public class APKUpdateManager {
    private static APKUpdateManager mInstance;
    private final static int DOWNLOAD_COMPLETE = 0;
    private final static int DOWNLOAD_FAIL = 1;
    private final static int requestcode =100;
    private OkHttpClient mOkHttpClient;
    private String downUrl;
    private String apkDescribe;
    private String apkName;
    private File updateDir;
    private File updateFile;
    private Activity activity;


    public APKUpdateManager(APKVersionBean apkVersionBean, File updateDir, Activity activity){
        this.downUrl=apkVersionBean.getApkpath();
        this.apkDescribe=apkVersionBean.getApkdesr();
        this.apkName=apkVersionBean.getApkname();
        this.updateDir=updateDir;
        this.activity=activity;
    }

    public void APKUpdate(){
        mOkHttpClient = new OkHttpClient();
        //cookie enabled
        mOkHttpClient.setCookieHandler(new CookieManager(null, CookiePolicy.ACCEPT_ORIGINAL_SERVER));
        AlertDialog.Builder builder = new AlertDialog.Builder(
                activity);
        builder.setTitle("版本更新");//对话框标题
        builder.setMessage(apkDescribe);//对话框详细内容
        builder.setPositiveButton(R.string.str_button_ok,
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        _downloadAsyn(downUrl);//点击确定时候进行下载
                    }
                });
        builder.setNegativeButton(R.string.str_button_cancel, null);
        builder.setCancelable(false); //设置为false时候点击返回键获取屏幕边缘,对话框也无法取消
        builder.show(); // 显示这个消息框
    }

    private void _downloadAsyn(final String url)
    {
        final ProgressDialog mProgress=new ProgressDialog(activity);//进度对话框
        final Message message = updateHandler.obtainMessage();
        mProgress.setIcon(R.drawable.ic_launcher_lc);//小图标
        mProgress.setTitle("APK文件下载中,请稍候...");//进度对话框标题
        mProgress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);//进度对话框设置为水平进度条
        mProgress.setCancelable(false); // 设置允许取消
        mProgress.show();
        final Request request = new Request.Builder()
                .url(url)
                .build();
        Call call = mOkHttpClient.newCall(request);
        call.enqueue(new Callback()
        {
            @Override
            public void onFailure(final Request request, final IOException e)
            {
                message.what = DOWNLOAD_FAIL;
                updateHandler.sendMessage(message);
                e.printStackTrace();
            }

            @Override
            public void onResponse(Response response)
            {
                InputStream is = null;
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;
                try
                {
                    long total=response.body().contentLength();//获取文件大小
                    mProgress.setMax((int)total);//设置进度对话框总共数值大小
                    long sum = 0;
                    is = response.body().byteStream();
                    updateFile = new File(updateDir, apkName);
                    fos = new FileOutputStream(updateFile,false);
                    while ((len = is.read(buf)) != -1)
                    {
                        sum+=len;
                        int progress=(int)(sum*100/total);
                        mProgress.setProgress((int)sum);//设置进度对话框当前完成数值大小
                        fos.write(buf, 0, len);
                    }
                    fos.flush();
                    mProgress.dismiss();
                    if(sum>0){
                        message.what = DOWNLOAD_COMPLETE;
                        updateHandler.sendMessage(message);
                    }
                } catch (IOException e)
                {
                    message.what = DOWNLOAD_FAIL;
                    updateHandler.sendMessage(message);
                    e.printStackTrace();
                } finally
                {
                    try
                    {
                        if (is != null) {
                            is.close();
                        }
                    } catch (IOException e)
                    {
                    }
                    try
                    {
                        if (fos != null) {
                            fos.close();
                        }
                    } catch (IOException e)
                    {
                    }
                }

            }
        });
    }

    private Handler updateHandler = new Handler() {

        @SuppressWarnings("deprecation")
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {

                case DOWNLOAD_COMPLETE:

                    Uri uri = Uri.fromFile(updateFile);
                    Intent installIntent = new Intent(Intent.ACTION_VIEW);
                    installIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                    installIntent.setDataAndType(uri,
                            "application/vnd.android.package-archive");

                    activity.startActivityForResult(installIntent,requestcode);

                    break;
                case DOWNLOAD_FAIL:
                    Toast.makeText(activity,"APK文件下载失败,请稍候重试",Toast.LENGTH_LONG).show();
                    break;


            }
        }
    };

    private String getNameFromUrl(String url) {
        return url.substring(url.lastIndexOf("/") + 1);
    }
}
      
      在Activity里调用方法为:
int newversion=Integer.parseInt(apkVersionBean.getApkversion());
int version=getVerCode(this);
if(version<newversion) {
    APKUpdateManager apkUpdateManager = new APKUpdateManager(apkVersionBean, updateDir, this);
    apkUpdateManager.APKUpdate();
}
      
      安装后的回调函数为:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode){
        case requestcode:

            break;
    }
}

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
屏幕流镜像 屏幕流镜像是用于实时镜像和广播Android屏幕和音频的最强大的应用程序! 您可以通过媒体播放器,网络浏览器,Chromecast和UPnP / DLNA设备(智能电视或其他兼容设备)将屏幕“实时”分享到同一网络上的任何设备或电脑。 您可以为工作,教育或游戏制作强大的演示文稿。 您可以直播Twitch,Youtube Gaming,Facebook,Ustream以及任何其他互联网流行的流媒体服务器:完美播放您喜爱的游戏。 您还可以将其录制到视频文件中。 这是屏幕流镜像的完整版本。 完整版没有时间限制,也没有广告。 如果您想在购买之前确保该应用程序适用于您的设备,请在Play商店试用免费版:http://goo.gl/JbHKwQ。 可以使用以下功能: [✔]无root:在Android 5.0之前,您需要从计算机运行我们的启动工具以激活屏幕镜像。 [✔]镜像,屏幕共享媒体播放器和工具,如VLC,XBMC / KODI,OBS(开放广播软件)等...... [✔]镜像,屏幕共享与网络浏览器 [✔]广播到Twitch,Youtube(Youtube)游戏),Facebook,Ustream等... [✔]镜像,屏幕共享与UPnP / DLNA视频播放器,如XBMC / KODI [✔]镜像,屏幕共享与UPnP / DLNA设备,如智能电视,蓝光播放器,和其他兼容设备 [✔] Google Cast™Ready(Chromecast) [✔]流式计时器并在锁定屏幕时停止 [✔]流式传输时的相机叠加小部件 [✔]图像叠加 [✔]在广播 [✔]内部音频(ROOTED Android 4.4及以上版本)和麦克风流式传输 [✔]混合音频(内置+麦克风)流式传输时切换聊天预览( ROOTED Android 4.4及以上版本) [✔]录制 [✔]兼容网络绑定(wifi,蓝牙,USB) [✔]许多设置可以优化性能 [✔]可以进行任意数量的连接,因此多人可以连接同时 请阅读: 不要将评论用于报告问题或者如果您有疑问。 如果因为您无法使用该应用程序而在发表错误评论之前请联系我们[email protected],我们很乐意为您提供帮助。 我们无法通过评论为您提供帮助或与您联系。 如果您没有阅读说明,请不要评价不佳。 警告:如果您使用备用ROM(CyanogenMod,AOKP ...)以获得更好的结果,建议您将ROM更新到最新版本! 无根设备说明: 在Android 5.0之前,如果您的设备没有root,则需要使用我们的启动工具来激活屏幕镜像。 在这里下载启动工具:<> 您只需在第一次使用该应用程序时启动它,并仅在您的设备上再次运行它重新启动。 请仔细阅读应用程序或此处的说明: - 无根指示 - > http://mobzapp.com/mirroring/instructions.html - 常见问题 - > http://mobzapp.com/mirroring/faq.html 什么是新的 ✔添加了覆盖背景选项 ✔更新Android权限请求 ✔技术更新和修复

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值