android APK更新
菜鸟的博客请多多指教
最近做了一个新功能,更新APK的功能
1、更新APK是一个耗时的任务,我采用了一个服务来做,上次在网上看到服务是在主线程里面,自己也测试了下,数据是真的
所以下载动作还必须在服务里面开一个线程来处理下载任务,在写下载任务的时候,由于经验不够,中间出了很多错,下载要分下载开始,下载中,下载异常,下载结束,
2、在后台下载,对用户来说,是看不见的,无法与用户交流,所以在开启服务的时候我就初始化了一个通知,通知在服务开启是初始化,所以其实通知也是在UI线程中,所以想在下载线程中更新通知进度栏,必须通过机制,来更新通知栏的进度条,但是后来组长又给你我一个需求,在点击通知栏时,在更新界面弹出一个对话框,显示是否要停止更新,这里就涉及到一个新的问题,怎样在Service里面获取Activity呢,找了很多资料,最后找到了一个ActivityManager系统服务,他可以得到指定包的任务栈,得到栈顶的Activity,这样就可以在Service中获取Activity里面了
String MY_PKG_NAME = "com.example.sunny.text333"; int i=0; ActivityManager manager = (ActivityManager) MyApplication.getInstance().getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningTaskInfo> list = manager.getRunningTasks(100); for (ActivityManager.RunningTaskInfo info: list){ if(info.topActivity.getPackageName().equals(MY_PKG_NAME) || info.baseActivity.getPackageName().equals(MY_PKG_NAME)){ break; } i++; } ActivityManager.RunningTaskInfo info=list.get(i); String className = info.topActivity.getClassName();//得到栈顶的Activity Intent intent = null; try { intent = new Intent(this,Class.forName(className)); intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK| Intent.FLAG_ACTIVITY_SINGLE_TOP); Bundle bundle = new Bundle(); bundle.putString("flag","取消"); intent.putExtras(bundle); } catch (ClassNotFoundException e) { e.printStackTrace(); Log.e("没有找到Activity",""+className); } intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |Intent.FLAG_ACTIVITY_NEW_TASK); pendingIntent = PendingIntent.getActivity(this, 0,intent,PendingIntent.FLAG_UPDATE_CURRENT); notification.contentIntent =pendingIntent; Log.e("通知的Activity名称",""+className);
下载线程:
class DownloadThread extends Thread { String url; MyHandler handler; public DownloadThread(String url, MyHandler handler) { this.url = url; this.handler = handler; } @Override public void run() { FileOutputStream fos = null; InputStream io = null; try { handler.sendEmptyMessage(0); URL u = new URL(url); Log.e("URL","____________"+u); HttpURLConnection connection = (HttpURLConnection) u.openConnection(); connection.setConnectTimeout(30000); connection.setReadTimeout(30000); io = connection.getInputStream(); if (io != null) { File file = new File(Environment.getExternalStorageDirectory() + "/" + "mapp.apk"); byte[] buff = new byte[1024]; if (file.exists()) { file.delete(); } else { file.createNewFile(); } fos = new FileOutputStream(file); int readNum = 0; int lastPress = 0;//上一次的进度值 int press = 0;// int fileLength = 0; int count = 0;//记录文件的读取个数 while (isrunning) { readNum = io.read(buff); fileLength = connection.getContentLength(); count += readNum; press = (int) ((float) count / (float) (fileLength - 1) * 100.0);//下载总大小除以总的大小*100 BigDecimal bd = new BigDecimal(count); BigDecimal bd1 = new BigDecimal(fileLength - 1); if (readNum == -1 && bd.toPlainString().equals(bd1.toPlainString())) {// 下载完成 Log.e("sdas", "下载完成"); Message message = new Message(); message.obj = file; message.what = 2; handler.sendMessage(message); break; } else if (readNum == -1 && !bd.toPlainString().equals(bd1.toPlainString())) { Log.e("sdas", "下载失败"); handler.sendEmptyMessage(4); break; } else if (readNum > 0) { fos.write(buff, 0, readNum); // Log.e("sdas", "readNum:" + readNum); if (press - lastPress >= 1) { lastPress = press; // Log.e("sdas", "press:" + press); Message message = new Message(); message.what = 1; message.obj = press + ""; handler.sendMessage(message); } } } fos.flush(); fos.close(); io.close(); } } catch (MalformedURLException e) { handler.sendEmptyMessage(4); e.printStackTrace(); } catch (IOException e) { handler.sendEmptyMessage(4); e.printStackTrace(); } finally { try { if (fos != null) { fos.flush(); fos.close(); } if (io != null) { io.close(); } } catch (IOException e) { } } } }
MyHandler的代码:
class MyHandler extends Handler { @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (msg != null) { switch (msg.what) { case 0:// 初始化通知栏和进度条 views.setTextViewText(R.id.tvProcess, "开始下载……"); views.setTextColor(R.id.tvProcess, Color.BLACK); views.setProgressBar(R.id.app_down_progressBar, 100, 0, false); notification.defaults = Notification.DEFAULT_LIGHTS; notification.contentView = views; nm.notify(NOTIFICATIO_UPDATE_SOFT, notification); MyApplication.getInstance().setIsupdateing(true); break; case 1: int download_precent = Integer.parseInt(msg.obj.toString());// 获取下载进度 // 更新状态栏上的下载进度信息 views.setTextViewText(R.id.tvProcess, "已下载" + download_precent + "%"); views.setTextColor(R.id.tvProcess, Color.BLACK); views.setProgressBar(R.id.app_down_progressBar, 100, download_precent, false); notification.defaults = Notification.DEFAULT_LIGHTS; notification.contentView = views; nm.notify(NOTIFICATIO_UPDATE_SOFT, notification); MyApplication.getInstance().setIsupdateing(true); break; case 2: MyApplication.getInstance().setIsupdateing(false); /* if( unIntallapk()){ Log.e("文件卸载",""+unIntallapk()); }*/ Instanll((File) msg.obj); nm.cancel(NOTIFICATIO_UPDATE_SOFT); // 停止掉当前的服务 stopSelf(); break; case 3:// 停止下载 MyApplication.getInstance().setIsupdateing(false); // 停止掉当前的服务 nm.cancel(NOTIFICATIO_UPDATE_SOFT); stopSelf(); break; case 4:// 下载异常 MyApplication.getInstance().setIsupdateing(false); views.setTextViewText(R.id.tvProcess, "" + "已停止下载"); views.setTextColor(R.id.tvProcess, Color.BLUE); // 在任务栏不被用户手动删除 notification.flags = Notification.FLAG_AUTO_CANCEL; // 调用系统默认的声音提示以及震动 notification.defaults = Notification.DEFAULT_ALL; notification.contentView = views; nm.cancel(NOTIFICATIO_UPDATE_SOFT); nm.notify(NOTIFICATIO_UPDATE_SOFT, notification); break; default: break; } } } }