流程是这样,在远程服务器上存储了一个和android客户端类似的androidManifest.xml文件,对比客户端和服务器两个文件中的versionName,如果不一样,说明有新版本;
xml文件
:
<update> <version>90</version> <versionName>3.0.20</versionName> <name>fy.apk</name> <url>/res/a/fy.apk</url> </update>
public class UpdateService extends Service { private NotificationManager nm; private Notification notification; private RemoteViews views; private int notificationId = R.drawable.logo; UpdateManager um; private MyHandler myHandler; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); } @Override public void onCreate() { // TODO Auto-generated method stub super.onCreate(); um = new UpdateManager(getApplicationContext()); notificationId = getResources().getIdentifier("updateId", "id", getPackageName());//应用下指定应用资源id myHandler = new MyHandler(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.i("tcp", "UpdateService-onStartCommand"); update(); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); } private void update() { String checkUpdateTime = PublicUtil.getSharedValue(this, PublicUtil.SYSTEM_SETTINGS, PublicUtil.CHECKUPDATAETIME, ""); String currentTime = PublicUtil.getDateTime().split(" ")[0]; if(checkUpdateTime.equals(currentTime))return; int type = um.getUpdateType(); if(type>=1) PublicUtil.putSharedValue(this, PublicUtil.SYSTEM_SETTINGS, PublicUtil.CHECKUPDATAETIME, currentTime); Log.i("tcp","type=====" + type); if (type >= 2) { updateId = type - 2; creatNotification(); } } void creatNotification() { nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); notification = new Notification(); notification.icon = R.drawable.logo; try { notification.number = Integer.valueOf(mHashMap.get("number")); } catch (Exception e) { // TODO: handle exception } notification.flags = Notification.FLAG_AUTO_CANCEL; // notification.icon=android.R.drawable.stat_sys_download_done; notification.tickerText = getString(R.string.app_name) + "软件更新"; notification.when = System.currentTimeMillis(); notification.defaults = Notification.DEFAULT_LIGHTS; // 设置任务栏中下载进程显示的views views = new RemoteViews(getPackageName(), R.layout.update); Intent intent = new Intent(getApplicationContext(), UpdateActivity.class); System.out.println("==============" + updateId); intent.putExtra("updateId", updateId); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0); notification.setLatestEventInfo(this, "饭友", "饭友有新版本啦", contentIntent); // 将下载任务添加到任务栏中 notification.contentView = views; nm.notify(notificationId, notification); // nm. // 初始化下载任务内容views // Message message = myHandler.obtainMessage(2, 0); // myHandler.sendMessage(message); } class MyHandler extends Handler { // private Context context; // public MyHandler(Looper looper, Context c) { // super(looper); // this.context = c; // } @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg != null) { switch (msg.what) { case 0: creatNotification(); break; case 1: break; case 2: notification.contentView = views; nm.notify(notificationId, notification); break; } } } } }
class UpdateManager{ private HashMap<String, String> mHashMap; /** * 检查软件是否有更新版本 * * @return */ public int getUpdateType() { // 获取当前软件版本 int versionCode = getVersionCode(mContext); String versionName = getVersionName(mContext); System.out.println("versionCode==" + versionCode); // 把version.xml放到网络上,然后获取文件信息 InputStream inStream = null; try { URL url = new URL(PublicUtil.getWebRoot()+"/res/a/fy-update.xml"); HttpURLConnection urlCon = (HttpURLConnection)url.openConnection(); urlCon.setConnectTimeout(3000); urlCon.setReadTimeout(3000); inStream = urlCon.getInputStream(); } catch (Exception e) { // TODO: handle exception e.printStackTrace(); return -1; } // // 获取当前软件版本 // int versionCode = getVersionCode(mContext); // // 把version.xml放到网络上,然后获取文件信息 // InputStream inStream = ParseXmlService.class.getClassLoader().getResourceAsStream("version.xml"); // // 解析XML文件。 由于XML文件比较小,因此使用DOM方式进行解析 ParseXmlService service = new ParseXmlService(); try { mHashMap = service.parseXml(inStream); } catch (Exception e) { e.printStackTrace(); } if (null != mHashMap) { int serviceCode = Integer.valueOf(mHashMap.get("version")); // 版本判断 if (serviceCode > versionCode) { try{ String updateType = mHashMap.get("versionName"); PublicVariable.serverVersion = updateType; String[] code_s = updateType.split("\\."); String[] code_c = versionName.split("\\."); int type = 0; if(Integer.valueOf(code_c[0])<Integer.valueOf(code_s[0])){ type = 3; }else if(Integer.valueOf(code_c[1])<Integer.valueOf(code_s[1])){ type = 2; }else if(Integer.valueOf(code_c[2])<Integer.valueOf(code_s[2])){ type = 1; } PublicUtil.putSharedValue(mContext, PublicUtil.SYSTEM_SETTINGS, PublicUtil.UPDATECODE, type>0?type+"-"+updateType:""); return type; } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } } return 0; } }
点击下拉更新跳转到具体activity
public class UpdateActivity extends Activity implements OnClickListener { Button btn_update, btn_cancel, btn_exit; TextView tv_title; ProgressBar pb; int updateType; String updateVersion; private String mSavePath; private HashMap<String, String> mHashMap; private int progress; private boolean cancelUpdate; Handler mHandler; /* 下载中 */ private static final int DOWNLOAD = 1; /* 下载结束 */ private static final int DOWNLOAD_FINISH = 2; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.update_layout); findViews(); prepareData(); initViews(); NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); nm.cancel(R.id.updateId); } void findViews() { btn_update = (Button) findViewById(R.id.btn_update); btn_cancel = (Button) findViewById(R.id.btn_cancel); btn_exit = (Button) findViewById(R.id.btn_exit); tv_title = (TextView) findViewById(R.id.tv_title); pb = (ProgressBar) findViewById(R.id.update_progress); } void prepareData() { String[] updateCode = PublicUtil.getSharedValue(this, PublicUtil.SYSTEM_SETTINGS, PublicUtil.UPDATECODE, "").split( "-"); updateType = updateCode[0].equals("3")?1:0; updateVersion = updateCode[1]; mHashMap = UpdateManager.mHashMap; mHandler = new Handler() { public void handleMessage(android.os.Message msg) { switch (msg.what) { // 正在下载 case DOWNLOAD: // 设置进度条位置 pb.setProgress(progress); break; case DOWNLOAD_FINISH: // 安装文件 installApk(); pb.setVisibility(View.GONE); if (updateType == 0) finish(); break; default: break; } }; }; } void initViews() { btn_cancel.setVisibility(updateType == 0 ? View.VISIBLE : View.GONE); btn_exit.setVisibility(updateType == 1 ? View.VISIBLE : View.GONE); tv_title.setText("饭友更新至" + updateVersion + "正式版"); btn_cancel.setOnClickListener(this); btn_update.setOnClickListener(this); btn_exit.setOnClickListener(this); } @Override public void onClick(View v) { // TODO Auto-generated method stub switch (v.getId()) { case R.id.btn_cancel: cancelUpdate = true; finish(); break; case R.id.btn_update: pb.setVisibility(View.VISIBLE); v.setEnabled(false); btn_cancel.setText("取消更新"); new downloadApkThread().start(); break; case R.id.btn_exit: cancelUpdate = true; finish(); if (MoreActivity.activity != null) MoreActivity.activity.finish(); if (HomeTabActivity.activity != null) HomeTabActivity.activity.finish(); break; default: break; } } private class downloadApkThread extends Thread { @Override public void run() { try { // 判断SD卡是否存在,并且是否具有读写权限 if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { // 获得存储卡的路径 String sdpath = Environment.getExternalStorageDirectory() + "/"; mSavePath = sdpath + "download"; URL url = new URL(PublicUtil.getWebRoot() + mHashMap.get("url")); // 创建连接 HttpURLConnection conn = (HttpURLConnection) url .openConnection(); conn.connect(); // 获取文件大小 int length = conn.getContentLength(); // 创建输入流 InputStream is = conn.getInputStream(); File file = new File(mSavePath); // 判断文件目录是否存在 if (!file.exists()) { file.mkdir(); } File apkFile = new File(mSavePath, mHashMap.get("name")); FileOutputStream fos = new FileOutputStream(apkFile); int count = 0; // 缓存 byte buf[] = new byte[1024]; // 写入到文件中 do { int numread = is.read(buf); count += numread; // 计算进度条位置 progress = (int) (((float) count / length) * 100); // 更新进度 mHandler.sendEmptyMessage(DOWNLOAD); if (numread <= 0) { // 下载完成 mHandler.sendEmptyMessage(DOWNLOAD_FINISH); break; } // 写入文件 fos.write(buf, 0, numread); } while (!cancelUpdate);// 点击取消就停止下载. fos.close(); is.close(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }; /** * 安装APK文件 */ private void installApk() { File apkfile = new File(mSavePath, mHashMap.get("name")); if (!apkfile.exists()) { return; } // 通过Intent安装APK文件 Intent i = new Intent(Intent.ACTION_VIEW); i.setDataAndType(Uri.parse("file://" + apkfile.toString()), "application/vnd.android.package-archive"); startActivity(i); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == event.KEYCODE_BACK) { return true; } return super.onKeyDown(keyCode, event); } }
相关推荐
在"qt for android 更新APP"的场景下,我们讨论的是如何在Android应用程序内部实现更新功能。这通常涉及到以下几个关键知识点: 1. **自动检查更新**:应用启动时或在设定的时间间隔内,通过网络请求(通常是HTTP或...
Qt for Android实现自动更新app,安装apk文件,qml自动更新 通过调用修改Java函数来实现对私有数据的读写
Flutter下载更新App的方法示例 Flutter是一款跨平台的移动应用程序开发框架,通过使用Flutter可以快速构建高质量的移动应用程序。然而,在移动应用程序的开发过程中,更新应用程序是一个非常重要的步骤。那么,如何...
在移动应用开发中,"后台下载更新APP" 是一个常见的需求,它允许用户在不干扰当前操作的情况下,自动或手动启动应用更新下载过程。这一功能的实现涉及到多个技术点,包括服务(Service)、网络请求、文件下载管理...
本文将深入探讨如何利用`DownloadManager`来创建一个简单的、可靠的文件下载系统,以实现app的自动更新。 首先,我们需要了解`DownloadManager`的基本用法。`DownloadManager`是一个系统服务,可以处理长时间运行的...
这个"android 后台更新app demo"可能是一个示例项目,展示了如何在用户不直接交互的情况下进行应用的自动更新,并通过通知栏向用户反馈更新进度。让我们深入探讨一下这些相关技术。 首先,我们有“后台服务”...
在更新APP的场景中,Retrofit2.0可以用来发送GET或POST请求到服务器,获取最新的APK文件。首先,你需要定义一个服务接口,声明下载文件的API,例如: ```java public interface UpdateService { @GET("update/app....
从标签“苹果新政,禁止开发者在App中加入检查更新功能”来看,苹果公司可能已经更新了其审核指南,禁止开发者在App内直接实现检查更新的功能。这可能是为了防止用户频繁被提示升级,破坏用户体验。开发者应遵循App...
网上很多关于bootloader的例程,一直没找到利用U盘更新的,这里提供一个通过U盘更新APP程序的例程,测试环境是ALIENTEK STM32F407开发板。 其中值得注意的是U盘中断问题,更新完程序后要及时关闭中断跳转到APP后...
"ios-一句代码提示app更新.zip" 提供了一个简单易用的解决方案,通过一句代码即可实现检查并提示用户更新App的功能。下面我们将详细探讨这个解决方案及其背后的技术。 首先,这个项目利用了苹果的API接口,特别是`...
本篇将详细讲解如何在uniapp中实现APP的更新组件功能,以确保用户能够及时获取最新的应用版本。 一、uniapp简介 uniapp是基于Vue.js开发的多端统一开发框架,通过uni-app,开发者可以使用Vue.js语法编写代码,然后...
实现 android7、8 以上版本自动更新app 程序,仅供参考。
android 断点下载 并自动更新APP 百分百下载成功 支持大文件,里面接口基本已经写好,只需自定义了
洛达_AIROHA_1562M 更新APP,华强北AIRPODS 二代,洛达1562M方案的固件更新APK
独家首发最新更新app过毒过安全检测视频文字详细教程.txt
app-updater 主要负责后台下载更新App,无需担心下载时各种配置相关的细节,一键傻瓜式升级。 app-dialog 主要是提供常用的Dialog和DialogFragment,简化弹框提示,样式支持高度自定义。 > app-updater app-dialog ...
本文只要介绍HBuilder实现App资源在线升级更新。 梳理思路: 1.获取线上App版本号和当前App版本号 2.比对版本号,判断是否资源在线升级更新 3.是否下载最新安装包[可以静默下载或用户触发] 4.是否执行资源在线升级...
启动知道预留10秒,检测串口是否收到新文件, 收到之后即可写入FLASH,再跳转到新程序运行。 串口提示流程如下 ...开始更新固件...起始地址:0x8000147 固件更新完成! 开始执行FLASH用户代码=0x800A000
本文将深入探讨Android AppWidget的第四部分,主要关注如何更新AppWidget中的控件,以及相关的源码和工具。 **一、AppWidget更新机制** 1. **AppWidgetProvider**: 这是所有AppWidget的核心组件,它是一个...
ndroid 断点下载 并自动更新APP 百分百下载成功 支持大文件,里面接口基本已经写好,只需自定义了.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。