我们使用的app等总是不断的要更新换代,这样才能更的上用户的需求,自身的发展,每一款app都必须要有这个功能就是版本跟新,那么这个功能是如何做到的呢?主要包括有以下几个步骤:主要包括开发中版本的设置,如何检测本程序的版本,版本的更新判断和显示,新版本程序的安装。

一、首先来介绍下版本的基本知识。有版本名字+版本号

1.版本号(versioncode)是一个integer的值,一般大家在发布自己的第一个应用到市场的时候,版本取值为1(versionCode=1),这也是目前典型和普遍的做法。然后,每次发布更新版本时可以递增versionCode的值。

2.版本名字   版本名(versionName)一个值为String类型的属性,一般和VersionCode成对出现。VersionCode是方便程序开发者运行和维护Application而设置的一个有效的值。versionName是一个版本的描述,给用户看的,也是用户放在各个第3方平台上提供给使用者看的一个版本名,可以说是对VersionCode的解释和描述。一般格式可以为:1.1.2。

这两个值在安卓里面放在哪里呢?在bulid.gradle(app)里面versionCode 1,versionName "1.0"。这是我里面的,

3.用版本号判断是否升级,版本名用来判断更新的多少,幅度。

那么现在要做到一个版本更新是如何做到的呢?

1.首先把程序进行了修改,生成了apk,现在把新生成的apk传到每个用户手上,你拿不到用户的手机的,这个时候如何让用户及时更新呢?用户是不会主动去更新的,所以要强制用户更新。这个时候

如何做到呢,就是每一次App打开的时候都是去服务器请求下版本号(用户不知道),然后和手机版本号进行版本号校对,如果不一样,弹对话框提示用户更新。

2.当向服务器进行请求,服务器会给我们返回一串json的数据你拿不到用户的手机的,你拿不到用户的手机的

从服务器获取到一串json数据,里面包含最新程序的版本号和版本名、新版本信息等数据,需要自己解析到达对应的数据,因为服务器的数据不一样,所以这里的代码也不写!

下面开始具体一步一步开始代码操作,版本更新

一、首先开始校对版本,现在校对不了,因为没有服务器给我们发,但是我可以给一个死的版本号,然后给一个死的QQ地址。就行了

 1.网络请求+json解析就可以完成了

2.开始校对,看是否不一样,弹对话框提示用户更新

3.下载Apk,1.这里方法有很多(Reotrfit,其次写个线程+httpurlconnetion),不过现在用一个更成熟的东西DownloadManager,2.同时我们的下载应该是后台下载,不可能让用户守着我们下载,所以应该开启一条服务。3.下载时候应该有一个通知栏 4.下载在本地存放  5.安装

步骤就是以上这些了。现在主要介绍下DownloadManager使用,它能包含下载,通知栏更新,本地存放,所以使用它。但是DownloadManager在有些手机没法使用,主要是国产的手机会对原生的安卓系统进行阉割,我们使用的DownloadManager下载是靠的系统的一条服务,这样就没法使用了。下面看代码

1.因此首先我们需要对这个DownloadManager进行判断是否能够下载。在这里我封装了一个工具包

DownloadUtil,这样代码更加分离,好看。这个是里面的一个方法
public static boolean canDownloadState(Context ctx) {}
//这个是设置一个服务,获取系统下载的状态
 int state = ctx.getPackageManager().getApplicationEnabledSetting("com.android.providers.downloads");//判断能够使用DownloadManager下载,ture可以


public static boolean canDownloadState(Context ctx) {
        try {
int state = ctx.getPackageManager().getApplicationEnabledSetting("com.android.providers.downloads");
          //如果具足下面一个条件,这download不能用
            if (state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
                    || state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
                    || state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }




//这个是第一个工具包,用来判断DownloadManager下载是否可用和下载,安装的三个方法。


public class DownloadUtil {
    //判断能不能下载,能不能使用downloadManager下载,如果不行线程+Httpurlconnection下载
    public static boolean canDownloadState(Context ctx) {
        try {
            int state = ctx.getPackageManager().getApplicationEnabledSetting("com.android.providers.downloads");
          //如果具足下面一个条件,这download不能用
            if (state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
                    || state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
                    || state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    public static void download(Context context,String url)
    {
          if(canDownloadState(context))
        {
            //获取系统服务
            DownloadManager downloadManager = (DownloadManager)context.getSystemService(DOWNLOAD_SERVICE);
            //配置下载请求
            DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
/**设置用于下载时的网络状态*/
            request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
/**设置通知栏是否可见*/
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
/**设置漫游状态下是否可以下载*/
            request.setAllowedOverRoaming(false);
/**如果我们希望下载的文件可以被系统的Downloads应用扫描到并管理,
 我们需要调用Request对象的setVisibleInDownloadsUi方法,传递参数true.*/
            request.setVisibleInDownloadsUi(true);
/**设置文件保存路径*/
            request.setDestinationInExternalFilesDir(context, "apk", "qq.apk");
/**将下载请求放入队列, return下载任务的ID*/



            downloadManager.enqueue(request);
            //执行下载任务时注册广播监听下载成功状态
//            registerBroadcast();


        }else
            {
                httpupdate();
            }

    }
    public static void httpupdate()
    {

    }
    /**
     * 安装APK
     * @param context
     *
     */
    public static void installApk(Context context, Long id) {
        DownloadManager downloadManager=(DownloadManager)context.getSystemService(context.DOWNLOAD_SERVICE);
        Uri downloadfileuri=downloadManager.getUriForDownloadedFile(id);
        Log.e("msg",downloadfileuri.getPath()+"下载版本更新成功");
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_VIEW);
        //此处因为上下文是Context,所以要加此Flag,不然会报错
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setDataAndType(downloadfileuri, "application/vnd.android.package-archive");
        context.startActivity(intent);
    }



}


二、这个第二个工具包,获取判断版本名和版本号,用来判断版本号是否发生变化


1.获取版本名的方法

public static String getversionName(Context con)
    {
        PackageManager pm = con.getPackageManager();
        PackageInfo pi = null;//getPackageName()是你当前类的包名,0代表是获取版本信息
        try {
            pi = pm.getPackageInfo(con.getPackageName(), 0);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return pi.versionName;
    }


2、获取版本号:

public static int getVersionCode(Context con){
        //获取packagemanager的实例
        PackageManager pm = con.getPackageManager();
        PackageInfo pi = null;//getPackageName()是你当前类的包名,0代表是获取版本信息
        try {
            pi = pm.getPackageInfo(con.getPackageName(), 0);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            //抛异常说明没拿到东西
            return 0;
        }

        return pi.versionCode;
    }


3.判断版本号是否做了改变的方法public static boolean  idDifferentcode(Context context,int netcode) {
             if(netcode!=getVersionCode(context))
             {
              return true;
             }else
                 {
                     return false;
                 }
    }
//这个是封装了完整的版本的util包


public class Versionutil {
    /**
     * 1.获取版本的工具包
     * 2.获取版本名字
     * 3.获取版本号
     * 4.判断是否一致
     */
    //获取版本名
    public static String getversionName(Context con)
    {
        PackageManager pm = con.getPackageManager();
        PackageInfo pi = null;//getPackageName()是你当前类的包名,0代表是获取版本信息
        try {
            pi = pm.getPackageInfo(con.getPackageName(), 0);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return pi.versionName;
    }
    //获取版本号
    /*
 * 获取当前程序的版本号
 */
    public static int getVersionCode(Context con){
        //获取packagemanager的实例
        PackageManager pm = con.getPackageManager();
        PackageInfo pi = null;//getPackageName()是你当前类的包名,0代表是获取版本信息
        try {
            pi = pm.getPackageInfo(con.getPackageName(), 0);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            //抛异常说明没拿到东西
            return 0;
        }

        return pi.versionCode;
    }
    public static boolean  idDifferentcode(Context context,int netcode) {
             if(netcode!=getVersionCode(context))
             {
              return true;
             }else
                 {
                     return false;
                 }
    }
}

三、前面进行了判断DownloadManager是否可用,同时这个版本号是否需要更新,现在就可以弹对话框提示用户更新,然后下载,这里就要用到了DownloadManager.

1.DownloadManager是android2.3以后,系统下载的方法,是处理长期运行的HTTP下载的系统服务。客户端可以请求的URI被下载到一个特定的目标文件。客户端将会在后台与http交互进行下载,或者在下载失败,或者连接改变,重新启动系统后重新下载。还可以进入系统的下载管理界面查看进度。DownloadManger有两个内部类,Request 和Query。Request类可设置下载的一些属性。Query类可查询当前下载的进度,下载地址,文件存放目录等数据。简单的说这个DownloadManager是一个系统下载的方法,一个系统的服务,里面有两个类,一个是Request,一个是Query。其中Request用来请求下载,Query用来查询下载。
1。首先你要下载,那么首先要获取系统下载服务,在之前应该调用是否可以使用downloadManager,如果不行那么就使用public static void httpupdate(){},这个方法来下载把。//判断是够可用


if(canDownloadState(context)){}
//获取系统服务
            DownloadManager downloadManager = (DownloadManager)context.getSystemService(DOWNLOAD_SERVICE);
request.setDestinationInExternalFilesDir(context, "apk", "qq.apk");这个中方法第二个参数是放在哪里,第三个是名字。


//这个就是下载的完整代码

public static void download(Context context,String url)
    {
          if(canDownloadState(context))
        {
            //获取系统服务
            DownloadManager downloadManager = (DownloadManager)context.getSystemService(DOWNLOAD_SERVICE);
            //配置下载请求
            DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
/**设置用于下载时的网络状态*/
            request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
/**设置通知栏是否可见*/
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
/**设置漫游状态下是否可以下载*/
            request.setAllowedOverRoaming(false);
/**如果我们希望下载的文件可以被系统的Downloads应用扫描到并管理,
 我们需要调用Request对象的setVisibleInDownloadsUi方法,传递参数true.*/
            request.setVisibleInDownloadsUi(true);
/**设置文件保存路径*/
            request.setDestinationInExternalFilesDir(context, "apk", "qq.apk");
/**将下载请求放入队列, return下载任务的ID*/



            downloadManager.enqueue(request);
            //执行下载任务时注册广播监听下载成功状态
//            registerBroadcast();


        }else
            {
                httpupdate();
            }

    }
    public static void httpupdate()
    {

    }

三、现在开始添加权限

1.


<!--网络通信权限-->
<uses-permission android:name="android.permission.INTERNET"/>
<!--SD卡写入数据权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!--SD卡创建与删除权限-->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!--VISIBILITY_HIDDEN表示不显示任何通知栏提示的权限-->
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"/>
<!--DownloadManager-->
<uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER"/>



//这个是安装的代码,你需要给我一个安装包的apkid,那么我就可以进行安装了

public static void installApk(Context context, Long id) {
    DownloadManager downloadManager=(DownloadManager)context.getSystemService(context.DOWNLOAD_SERVICE);
    Uri downloadfileuri=downloadManager.getUriForDownloadedFile(id);
    Log.e("msg",downloadfileuri.getPath()+"下载版本更新成功");
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_VIEW);
    //此处因为上下文是Context,所以要加此Flag,不然会报错
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    intent.setDataAndType(downloadfileuri, "application/vnd.android.package-archive");
    context.startActivity(intent);
}

五、现在还差一个广播,广播写哪里呢?广播就是你需要在哪里下,就可以在哪里广播,那么我们在activty里面下,就可以把广播写在activty里,那么新建一个activty,DownLActivity

1.在xml文件中有一个button,点击button进行下载,toast弹出进行下载,成功以后在安装,首先按了按钮判断版本号是否符合,if(Versionutil.idDifferentcode(DownLActivity.this,5)){},我拿5去校对,肯定是可以下载的。然后进行下载 DownloadUtil.download(DownLActivity.this,"http://gdown.baidu.com/data/wisegame/f28ba370126f3605/QQ_744.apk");2.注册一条广播,注册一个下载完成的广播,一个筛选器,一个action,DownloadManager.ACTION_DOWNLOAD_COMPLETE;
3.从广播里面取出下载的apk的id值,通过这个id可以拿到下载的地址;DownloadManager downloadManager=(DownloadManager)context.getSystemService(context.DOWNLOAD_SERVICE);
//                 Uri downloadfileuri=downloadManager.getUriForDownloadedFile(id);
就是这两句话就可以拿到路径了


//这个是广播,有了广播下载就说明可以安装,就可以安装这到个软件了,ok了到这里的话
 IntentFilter filter=new IntentFilter();
        filter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
         registerReceiver(new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 long downloadApkId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1L);
                 DownloadUtil.installApk(DownLActivity.this,downloadApkId);
//                 DownloadManager downloadManager=(DownloadManager)context.getSystemService(context.DOWNLOAD_SERVICE);
//                 Uri downloadfileuri=downloadManager.getUriForDownloadedFile(id);


             }
         },filter);
    }
//这个activty的完整代码


public class DownLActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_down_l);
        Button but=(Button)findViewById(R.id.butdownload);
        but.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(Versionutil.idDifferentcode(DownLActivity.this,5))
                {
                    Toast.makeText(DownLActivity.this,"进行下载",Toast.LENGTH_SHORT).show();
                    DownloadUtil.download(DownLActivity.this,"http://gdown.baidu.com/data/wisegame/f28ba370126f3605/QQ_744.apk");
                }else
                {
                    Toast.makeText(DownLActivity.this,"不用下载",Toast.LENGTH_SHORT).show();
                }
            }
        });
        IntentFilter filter=new IntentFilter();
        filter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
         registerReceiver(new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 long downloadApkId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1L);
                 DownloadUtil.installApk(DownLActivity.this,downloadApkId);
//                 DownloadManager downloadManager=(DownloadManager)context.getSystemService(context.DOWNLOAD_SERVICE);
//                 Uri downloadfileuri=downloadManager.getUriForDownloadedFile(downloadApkId);


             }
         },filter);
    }

}


1.一共就一个activty,两个工具类,加个广播,就完成了简单的版本更新