首先我们要导入Trinea/Android-common 包,里面有封装好的下载类和安装apk类,可以方便的获取下载状态,下载地址:https://github.com/Trinea/android-common
首先声明权限:
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
先写一个service类来定时访问服务器获取新版本号,并弹出对话框提示
andoridManifest注册下面要写的服务:
- <service android:name=".CheckVersion">
- package com.example.download_test;
-
- import org.json.JSONObject;
-
- import cn.trinea.android.common.util.DownloadManagerPro;
- import cn.trinea.android.common.util.PackageUtils;
- import android.app.Activity;
- import android.app.AlertDialog;
- import android.app.AlertDialog.Builder;
- import android.app.DownloadManager;
- import android.app.Notification;
- import android.app.NotificationManager;
- import android.app.PendingIntent;
- import android.app.ProgressDialog;
- import android.app.Service;
- import android.content.Context;
- import android.content.DialogInterface;
- import android.content.Intent;
- import android.graphics.Paint.Join;
- import android.net.Uri;
- import android.os.Handler;
- import android.os.IBinder;
- import android.os.Message;
- import android.widget.Toast;
-
- public class CheckVersion extends Service {
- NotificationManager mNotificationManager;//声明通知栏manager
- public static DownloadManager downloadManager;//用于给别的类获取id用的超全局下载管理类
- //用来标志现在是否已经有对话框浮出的状态
- boolean boxFlag=false;
- //下载文件的路径
- public static String URL = "http://192.168.1.112:8080/auto_serve/weichat.apk";
- //获取新版本号的地址
- public static String VERSION_URL = "http://192.168.1.112:8080/auto_serve/version_code.txt";
- //声明进度条对话框
- ProgressDialog mReadProcessDia=null;
- //设置最大进度
- public final static int MAX_READPROCESS = 100;
- //设置用于弹出对话框的activity对象
- public Context context = MainActivity.SUPERCONTEXT;
-
- /**
- * 在检测到新版本时,和点击了确定更新按钮后,显示对话框的handler
- * @author Administrator
- *
- */
- class versionHandler extends Handler{
- @Override
- public void handleMessage(Message msg) {
- // TODO Auto-generated method stub
-
- //如果收到的是更新进度条的message
- if(msg.arg1==222){
- System.out.println("收到进度"+msg.arg2);
- //进度条对话框更新进度
- mReadProcessDia.setProgress(msg.arg2);
-
- return;
- }
-
- //如果收到的是提示更新的message
- Toast.makeText(getApplicationContext(), "发现新版本", Toast.LENGTH_SHORT).show();
-
- //蹦出通知对话框
- if(boxFlag==false){
- AlertDialog.Builder normalDia =new AlertDialog.Builder(context);
- normalDia.setIcon(R.drawable.ic_launcher);
- normalDia.setTitle("新版本提示");
- normalDia.setCancelable(false);
- normalDia.setMessage("有新版本了,是否更新");
- normalDia.setPositiveButton("确定", new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- System.out.println("点击了确定");
- boxFlag=true;//禁止弹出新的对话框
- //初始化进度条对话框
- mReadProcessDia=new ProgressDialog(context);
- mReadProcessDia.setProgress(0);
- mReadProcessDia.setIndeterminate(false);
- mReadProcessDia.setCancelable(false);//设置进度条对话框是否可以被点没,如果为true,相当于后台下载,完毕后不受影响
- mReadProcessDia.setTitle("下载进度");
- mReadProcessDia.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
- mReadProcessDia.setMax(MAX_READPROCESS);
- mReadProcessDia.show();
- new Thread(downloadRunnable).start();//启动下载子线程
-
-
- }
- });
-
- normalDia.setNegativeButton("取消", new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- System.out.println("点击了取消");
- boxFlag=false;//后面可以继续弹出新对话框
- }
- });
- if(boxFlag==false){
- normalDia.create().show();
- boxFlag=true;//禁止再弹出对话框
- }
- }
-
-
-
-
- if(mNotificationManager==null){//通知栏提示只显示一次
- mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
- //设置通知栏的图标
- int icon = R.drawable.ic_launcher;
- //通知栏的浮现文本
- CharSequence tickerText = "发现新版本";
- long when = System.currentTimeMillis();
- Notification notification = new Notification(icon, tickerText, when);
- //定义下拉通知栏时要展现的内容信息
- Context context = getApplicationContext();
- CharSequence contentTitle = "汽车报价大全发现新版本";
- CharSequence contentText = "点击此处自动更新";
- Intent notificationIntent = new Intent(CheckVersion.this, MainActivity.class);
- PendingIntent contentIntent = PendingIntent.getActivity(getApplicationContext(), 0,notificationIntent, 0);
- notification.setLatestEventInfo(context, contentTitle, contentText,contentIntent);
- //用mNotificationManager的notify方法通知用户生成标题栏消息通知
- mNotificationManager.notify(1, notification);
-
- }
- }
-
- }
-
-
- //声明handler
- versionHandler handler1 = new versionHandler();
-
- //下载子线程的方法
- Runnable downloadRunnable = new Runnable() {
- public void run() {
- System.out.println("下载线程已启动");
- downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
- //设置下载地址
- String apkUrl = URL;
- DownloadManager.Request request = new DownloadManager.Request(Uri.parse(apkUrl));
- //设置下载路径和文件名,不要忘了开启写存储设备权限
- request.setDestinationInExternalPublicDir("Trinea", "MeiLiShuo.apk");//表示设置下载地址为sd卡的Trinea文件夹,文件名为MeiLiShuo.apk。其他设置下载路径接口为setDestinationUri,setDestinationInExternalFilesDir,setDestinationToSystemCache。其中setDestinationToSystemCache仅限系统app使用。
- //魅族手机在通知栏不会有提示,其他的好像都行
- request.setTitle("汽车报价正在下载");//设置下载中通知栏提示的标题
- request.setDescription("新版2.0");//设置下载中通知栏提示的介绍
- request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);//表示下载进行中和下载完成的通知栏是否显示。默认只显示下载中通知。VISIBILITY_VISIBLE_NOTIFY_COMPLETED表示下载完成后显示通知栏提示。VISIBILITY_HIDDEN表示不显示任何通知栏提示,这个需要在AndroidMainfest中添加权限android.permission.DOWNLOAD_WITHOUT_NOTIFICATION.
- //request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);//表示下载允许的网络类型,默认在任何网络下都允许下载。有NETWORK_MOBILE、NETWORK_WIFI、NETWORK_BLUETOOTH三种及其组合可供选择。如果只允许wifi下载,而当前网络为3g,则下载会等待。
- //request.setAllowedOverRoaming(boolean allow)移动网络情况下是否允许漫游。
- //request.setMimeType("application/cn.trinea.download.file");//设置下载文件的mineType。因为下载管理Ui中点击某个已下载完成文件及下载完成点击通知栏提示都会根据mimeType去打开文件,所以我们可以利用这个属性。比如上面设置了mimeType为application/cn.trinea.download.file,我们可以同时设置某个Activity的intent-filter为application/cn.trinea.download.file,用于响应点击的打开文件。
- //request.addRequestHeader(String header, String value)// 添加请求下载的网络链接的http头,比如User-Agent,gzip压缩等
-
- //获取该下载的标示id
- long downloadId = downloadManager.enqueue(request);
- DownloadManagerPro downloadManagerPro = new DownloadManagerPro(downloadManager);
- //用于更新进度条的方法,一秒更新五次
- while(1==1){
- try {
- Thread.sleep(200);//设置更新频率
-
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- //获得下载进度信息
- int[] bytesAndStatus = downloadManagerPro.getBytesAndStatus(downloadId);
- //[0]是已经下载的大小,[1]是总大小,[2]是网络环境,2是联网,4是断网
- int progress = 0;
- try {//可能会有除以0异常
- progress = bytesAndStatus[0]/(bytesAndStatus[1]/100);
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- Message message = Message.obtain();
- message.arg1=222;
- message.arg2=progress;
- handler1.sendMessage(message);//发送给handler更新进度条
- //如果下载完毕,关闭进度条和该线程
- if(bytesAndStatus[0]==bytesAndStatus[1]){
- mReadProcessDia.cancel();
- break;
- }
- }
- };
- };
-
- @Override
- /**
- * 一旦该服务启动,就不停的联网获取新版本号
- */
- public int onStartCommand(Intent intent, int flags, int startId) {
- // TODO Auto-generated method stub
- System.out.println("服务开启");
-
- new Thread(){
- @Override
- public void run() {
- // TODO Auto-generated method stub
- while(1==1){//不停地联网检查有无新版本并和现有版本比较
- try {
- //从服务器获取json并解析出新版本号,这里可以灵活处理
- String versionJson = GetCarBrands.net(VERSION_URL, null, null);
- JSONObject jsonObject = new JSONObject(versionJson);
- int newVersion = jsonObject.getInt("version");
- //请灵活处理
-
- System.out.println("新版本是"+newVersion);
- //获取现在的版本号
- int oldVersion = PackageUtils.getAppVersionCode(getApplicationContext());
- System.out.println("旧版本是"+oldVersion);
- if(newVersion>oldVersion){
- System.out.println("该更新了!!!");
- Message message = Message.obtain();
- message.arg1=1;
- if(boxFlag==false)//如果现在可以弹出对话框,就向handler发出更新ui的通知
- handler1.sendMessage(message);
- }
- } catch (Exception e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- try {
- Thread.sleep(90000);//设置访问服务器获取版本号的频率
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- }.start();
- return super.onStartCommand(intent, flags, startId);
- }
-
- @Override
- public IBinder onBind(Intent intent) {
- // TODO Auto-generated method stub
- return null;
- }
-
-
- }
然后android-common为我们提供了一个广播接收器,这个接收器专门用于收取下载完毕的广播,所以我们把下载完毕后调用的功能写在这里面
- package com.example.download_test;
-
- import cn.trinea.android.common.util.PackageUtils;
- import android.app.AlertDialog;
- import android.app.DownloadManager;
- import android.app.ProgressDialog;
- import android.app.Service;
- import android.content.BroadcastReceiver;
- import android.content.Context;
- import android.content.DialogInterface;
- import android.content.Intent;
- import android.net.Uri;
-
- public class CompleteReceiver extends BroadcastReceiver {
- //设置用于弹出对话框的activity <pre name="code" class="java"> //设置用于弹出对话框的activity
- <span style="white-space:pre"> </span>
- <span style="white-space:pre"> </span>@Override //收到下载完毕的广播
- <span style="white-space:pre"> </span>public void onReceive(final Context context, Intent intent) {
- <span style="white-space:pre"> </span>// TODO Auto-generated method stub
- <span style="white-space:pre"> </span>//获得被下载文件的标示id
- <span style="white-space:pre"> </span>long completeDownloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
- <span style="white-space:pre"> </span>System.out.println(completeDownloadId+"下载完毕");
- <span style="white-space:pre"> </span>//从别的类那里获得管理器
- <span style="white-space:pre"> </span>DownloadManager downloadManager = CheckVersion.downloadManager;
- <span style="white-space:pre"> </span>//根据下载id获得下载后的路径
- <span style="white-space:pre"> </span>final Uri path = downloadManager.getUriForDownloadedFile(completeDownloadId);
- <span style="white-space:pre"> </span>System.out.println("下载存储uri是"+path);//file:///storage/emulated/0/Trinea/MeiLiShuo-7.apk
- <span style="white-space:pre"> </span>//将路径uri转换成String
- <span style="white-space:pre"> </span>final String pathString = path.toString().substring(7,path.toString().length());
- <span style="white-space:pre"> </span>System.out.println("下载路径是"+ pathString);//: /storage/emulated/0/Trinea/MeiLiShuo-7.apk
- <span style="white-space:pre"> </span>
- <span style="white-space:pre"> </span>//安装要放在子线程进行
- <span style="white-space:pre"> </span>final Thread installThread = new Thread(){
- <span style="white-space:pre"> </span>public void run() {
- <span style="white-space:pre"> </span>//返回-3是路径错误,不用添加任何权限,软件会自动申请root
- <span style="white-space:pre"> </span>//PackageUtils.installSilent静默安装,会请求获得root权限
- <span style="white-space:pre"> </span>//PackageUtils.installNormal普通安装
- <span style="white-space:pre"> </span>System.out.println("错误码:::"+PackageUtils.installNormal(context,pathString));
- <span style="white-space:pre"> </span>System.out.println("安装成功");
- <span style="white-space:pre"> </span>
- <span style="white-space:pre"> </span>};
- <span style="white-space:pre"> </span>};
- <span style="white-space:pre"> </span>
- <span style="white-space:pre"> </span>//下载完毕后弹出个对话框,点确定开始安装
- <span style="white-space:pre"> </span>AlertDialog.Builder normalDia =new AlertDialog.Builder(context);
- normalDia.setIcon(R.drawable.ic_launcher);
- normalDia.setTitle("下载完毕");
- normalDia.setCancelable(false);
- normalDia.setMessage("下载完毕,是否安装");
- normalDia.setPositiveButton("确定", new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- System.out.println("点击了确定");
- <span style="white-space:pre"> </span> installThread.start();//启动安装子线程
- <span style="white-space:pre"> </span>
- }
- });
- normalDia.setNegativeButton("取消", new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- System.out.println("点击了取消");
- }
- });
- normalDia.create().show();
- <span style="white-space:pre"> </span>}
还需要在主线程开启上面的服务就好了,并且在activity中注册上面写的接收器
- /** 注册下载成功的广播接受者 **/
- completeReceiver = new CompleteReceiver();
- registerReceiver(completeReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
- </pre><pre name="code" class="java">//启动检查版本的服务
- <span style="white-space:pre"> </span>Intent intent = new Intent(this,CheckVersion.class);
- <span style="white-space:pre"> </span>startService(intent);
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。