- 浏览: 1237523 次
- 性别:
- 来自: 广州
-
文章分类
- 全部博客 (353)
- java基础 (40)
- tapestry (16)
- gwt (14)
- ajax (7)
- linux (8)
- ubuntu (18)
- eclipse (6)
- dojo (2)
- javascript (7)
- maven (4)
- 日常生活 (29)
- web2.0 (2)
- jsonrpc (1)
- compass (1)
- lucene (0)
- spring (10)
- cluster (3)
- 数据结构 (2)
- sqlserver (1)
- tomcat (2)
- swing (1)
- servlet (1)
- hibernate (1)
- firefox (1)
- Java-Puzzlers (1)
- Wicket (2)
- mysql (10)
- windows (5)
- Webwork (1)
- struts2 (1)
- Seam (2)
- jboss (1)
- idea (6)
- 分布计算 (3)
- Python-Django (7)
- Hadoop (1)
- 工具 (3)
- Tokyo Tyrant (2)
- Comet (1)
- android (115)
- 音乐 (6)
- cxf (1)
- mqtt (1)
最新评论
-
hesai_vip:
学习了,感谢
gradlew wrapper使用下载到本地的gradle.zip文件安装。 -
imknown:
姚瑶大坏蛋 写道我也遇到了这个,用你这个方法,导致下拉刷新不起 ...
解决android-Ultra-Pull-To-Refresh下拉刷新组件中嵌套ViewPager的一个bug -
姚瑶大坏蛋:
我也遇到了这个,用你这个方法,导致下拉刷新不起作用了,你遇到过 ...
解决android-Ultra-Pull-To-Refresh下拉刷新组件中嵌套ViewPager的一个bug -
寐语者:
LeaderElection(String zookeeper ...
使用Zookeeper来为你的程序加上Leader Election的功能。 -
fyc0109:
博主, 安装了一部分还是报这个错误!FAILURE: Buil ...
gradlew wrapper使用下载到本地的gradle.zip文件安装。
移动客户端应用相对于Webapp的最大一个问题是做不到Online bug fix。如果全量发出去一个版本出现一个critical bug,紧急或者有安全漏洞的问题。这时你就会哭爹喊娘了。 如果是Webapp你可能最多花个1,2个小时紧急发布上线,但是app呢,打包,跪求市场发布几百个渠道,周么还发不了,app配置升级,你还不能配置强制升级, 就算配置提示升级,用户心里肯定想,老子他妈的前两天刚升级最新版,怎么又要升,而且升级要流量,这时候会去点升级按钮的用户肯定少得可怜。这时候你就能体会到server side发布的美好。所以这里有两个问题需要解决,1是安卓是否有能力做到打补丁,2是如何设计才能精确的把补丁推送到线上有问题的app。
1. 淘宝Dexposed框架 (https://github.com/alibaba/dexposed)
如果你是撸机高手,你一定听过安卓神器Xposed框架,Xposed框架是一款可以在不修改APK的情况下影响程序运行(修改系统)的框架服务,基于它可以制作出许多功能强大的模块。什么你没听过,那赶紧谷歌下,你会发现你的安卓机可玩性大大提高。其实Xposed也是安卓的一个开源框架https://github.com/rovo89/Xposed https://github.com/rovo89/XposedBridge,Dexposed是啥?名字为啥这么像?Dexposed是安卓系统下的一款强大的无侵入性的AOP框架,当然他是基于Xposed的。之前在特卖会安卓代码中也有使用过Aspectj来写一些埋点代码,但是之后大家都渐渐的放弃了使用Aspectj来写埋点代码了, 这里有几个原因,一个Aspectj的有着特殊的语法,有入门门槛,你还要学习怎么使用Aspectj,另外一个原因是它有自己的编译器,app打包的时候还需要编译下Aspjectj代码,会注入他自己的代码,所以他是有侵入性的,而且编译耗时比较长,编译出来的代码你也是不能调试的。Xposed提供的是无侵入性的,而且AOP就是用的java代码。只要使用他的几个api即可。他有几个典型的使用场景:
a. Classic AOP programming (大家常用的aop编程)
b. Instrumentation (for testing, performance monitoring and etc.) 用于测试,性能监控等等
c. Online hot patch to fix critical, emergent or security bugs 为安卓应用线上打补丁,用来解决一些严重的,紧急的或者安全漏洞的bug。
d. SDK hooking for a better development experience
下面来看看如果写一些AOP的代码:
1. Attach a piece of code before and after all occurrences of Activity.onCreate(Bundle).
2. Replace the original body of the target method.
不过这个框架目前对android 5.0系统还不支持,他提供一个函数来检测你的android系统是否支持Dexposed,DexposedBridge.canDexposed(context)。 你需要把补丁包打包成一个apk, 然后通过下面的代码来加载补丁包:
综上所述:安卓是可以通过淘宝的Dexposed框架来实现打补丁包的,不过目前这个项目还处理初期阶段对android 5.0系统支持有限,可能某些定制rom可能也会有问题。不过我相信这个框架会越来越好的,作者也说了会加上对5.0系统的支持。 需要深入的读者可以移步到Dexposed的github地址:https://github.com/alibaba/dexposed。
2. 如何精确及时的推送补丁
要做到精确投放,就要考虑bug的产生有哪几种因素和那些维度。这样我们就能精准投放,而不是投放给了那些不需要补丁的用户,这样可能让没问题的用户打补丁之后反而产生问题。 以下是可能存在的一些因素和维度:
1. 版本, 这个是最主要的因素, 我们经常需要就是为某个版本打补丁。
2. android系统版本,某些安卓系统上有兼容性问题。
3. 机型,某些机型有兼容性的问题。
4. Rom,某些Rom才有的问题。
5. 手机制造商, 比如小米。
6. mid, 可能为某个或者某些用户打补丁。
7. 渠道号, 为某些渠道的用户打补丁。
8. 地区,为某些地区的用户打补丁。
9. 分仓,为在某个分仓的用户打补丁。
当然上面的因素可以有一个或者多个合并。比如我要推送补丁到某个版本上的小米手机。我们在启动信息埋点中会上传用户的这些信息,后端就可以通过这些因素来定位要推送补丁的群体。我们会有一个补丁接口返回补丁的下载链接,补丁的匹配因素和这个补丁的crc或者md5。我们会把这些信息保存在客户端的数据库中,因为可能当用户升级到下一个版本时就不需要在加载这些补丁了。 所以我们在加载这些补丁的时候需要验证这个补丁是否适当当前app。当然如果想要及时推把补丁推送到客户端手中,我们可以使用push来推,而不是当用户打开app的时候来检测。下面是大概的流程。
注意: 这里漏了对patch apk验证的过程,这个很重要,首先对apk的md5验证, 然后最重要的需要对apk文件的签名进行验证,apk签名验证最好是放到ndk中实现, 后面的文章讲到具体实现的时候会讲到。
3. 代码示例
本代码示例主要是展示为以一个被除数不能为0这样的一个有bug的代码打补丁。有问题的代码如下:
下面的代码为补丁包代码。我们主要是替换doDivideLogic的方法。补丁包这里为一个独立的android project项目,当然你需要把依赖的主项目的class文件打包为一个jar文件作为依赖。比如如下代码的MainActivity。补丁的代码如下:
发现一个问题:在加载补丁包的时候需要调用DexposedBridge.canDexposed(context)方法才能加载成功。看了下源码,原来是在这方法里面加载so文件。
这个代码示例,我们是把补丁包app-patch.apk放到项目的assets,然后拷贝到sdcard中进行装载,如果是真实的项目的话应该是从网上下载补丁包,然后加载。代码可以从下面的链接下载:
DexposedSample.zip
DexposedSamplePatch.zip
Sample运行视频
1. 淘宝Dexposed框架 (https://github.com/alibaba/dexposed)
如果你是撸机高手,你一定听过安卓神器Xposed框架,Xposed框架是一款可以在不修改APK的情况下影响程序运行(修改系统)的框架服务,基于它可以制作出许多功能强大的模块。什么你没听过,那赶紧谷歌下,你会发现你的安卓机可玩性大大提高。其实Xposed也是安卓的一个开源框架https://github.com/rovo89/Xposed https://github.com/rovo89/XposedBridge,Dexposed是啥?名字为啥这么像?Dexposed是安卓系统下的一款强大的无侵入性的AOP框架,当然他是基于Xposed的。之前在特卖会安卓代码中也有使用过Aspectj来写一些埋点代码,但是之后大家都渐渐的放弃了使用Aspectj来写埋点代码了, 这里有几个原因,一个Aspectj的有着特殊的语法,有入门门槛,你还要学习怎么使用Aspectj,另外一个原因是它有自己的编译器,app打包的时候还需要编译下Aspjectj代码,会注入他自己的代码,所以他是有侵入性的,而且编译耗时比较长,编译出来的代码你也是不能调试的。Xposed提供的是无侵入性的,而且AOP就是用的java代码。只要使用他的几个api即可。他有几个典型的使用场景:
a. Classic AOP programming (大家常用的aop编程)
b. Instrumentation (for testing, performance monitoring and etc.) 用于测试,性能监控等等
c. Online hot patch to fix critical, emergent or security bugs 为安卓应用线上打补丁,用来解决一些严重的,紧急的或者安全漏洞的bug。
d. SDK hooking for a better development experience
下面来看看如果写一些AOP的代码:
1. Attach a piece of code before and after all occurrences of Activity.onCreate(Bundle).
// Target class, method with parameter types, followed by the hook callback (XC_MethodHook). DexposedBridge.findAndHookMethod(Activity.class, "onCreate", Bundle.class, new XC_MethodHook() { // To be invoked before Activity.onCreate(). @Override protected void beforeHookedMethod(MethodHookParam param) throws Throwable { // "thisObject" keeps the reference to the instance of target class. Activity instance = (Activity) param.thisObject; // The array args include all the parameters. Bundle bundle = (Bundle) param.args[0]; Intent intent = new Intent(); // XposedHelpers provide useful utility methods. XposedHelpers.setObjectField(param.thisObject, "mIntent", intent); // Calling setResult() will bypass the original method body use the result as method return value directly. if (bundle.containsKey("return")) param.setResult(null); } // To be invoked after Activity.onCreate() @Override protected void afterHookedMethod(MethodHookParam param) throws Throwable { XposedHelpers.callMethod(param.thisObject, "sampleMethod", 2); } });
2. Replace the original body of the target method.
DexposedBridge.findAndHookMethod(Activity.class, "onCreate", Bundle.class, new XC_MethodReplacement() { @Override protected Object replaceHookedMethod(MethodHookParam param) throws Throwable { // Re-writing the method logic outside the original method context is a bit tricky but still viable. ... } });
不过这个框架目前对android 5.0系统还不支持,他提供一个函数来检测你的android系统是否支持Dexposed,DexposedBridge.canDexposed(context)。 你需要把补丁包打包成一个apk, 然后通过下面的代码来加载补丁包:
File cacheDir = getExternalCacheDir(); if(cacheDir != null){ String fullpath = cacheDir.getAbsolutePath() + File.separator + "patch.apk"; PatchResult result = PatchMain.load(this, fullpath, null); if (result.isSuccess()) { Log.e("Hotpatch", "patch success!"); } else { Log.e("Hotpatch", "patch error is " + result.getErrorInfo()); } }
综上所述:安卓是可以通过淘宝的Dexposed框架来实现打补丁包的,不过目前这个项目还处理初期阶段对android 5.0系统支持有限,可能某些定制rom可能也会有问题。不过我相信这个框架会越来越好的,作者也说了会加上对5.0系统的支持。 需要深入的读者可以移步到Dexposed的github地址:https://github.com/alibaba/dexposed。
2. 如何精确及时的推送补丁
要做到精确投放,就要考虑bug的产生有哪几种因素和那些维度。这样我们就能精准投放,而不是投放给了那些不需要补丁的用户,这样可能让没问题的用户打补丁之后反而产生问题。 以下是可能存在的一些因素和维度:
1. 版本, 这个是最主要的因素, 我们经常需要就是为某个版本打补丁。
2. android系统版本,某些安卓系统上有兼容性问题。
3. 机型,某些机型有兼容性的问题。
4. Rom,某些Rom才有的问题。
5. 手机制造商, 比如小米。
6. mid, 可能为某个或者某些用户打补丁。
7. 渠道号, 为某些渠道的用户打补丁。
8. 地区,为某些地区的用户打补丁。
9. 分仓,为在某个分仓的用户打补丁。
当然上面的因素可以有一个或者多个合并。比如我要推送补丁到某个版本上的小米手机。我们在启动信息埋点中会上传用户的这些信息,后端就可以通过这些因素来定位要推送补丁的群体。我们会有一个补丁接口返回补丁的下载链接,补丁的匹配因素和这个补丁的crc或者md5。我们会把这些信息保存在客户端的数据库中,因为可能当用户升级到下一个版本时就不需要在加载这些补丁了。 所以我们在加载这些补丁的时候需要验证这个补丁是否适当当前app。当然如果想要及时推把补丁推送到客户端手中,我们可以使用push来推,而不是当用户打开app的时候来检测。下面是大概的流程。

注意: 这里漏了对patch apk验证的过程,这个很重要,首先对apk的md5验证, 然后最重要的需要对apk文件的签名进行验证,apk签名验证最好是放到ndk中实现, 后面的文章讲到具体实现的时候会讲到。
3. 代码示例
本代码示例主要是展示为以一个被除数不能为0这样的一个有bug的代码打补丁。有问题的代码如下:
public void doDivide(View view) { doDivideLogic(); } public void doDivideLogic() { BigDecimal num1 = new BigDecimal(etNum1.getText().toString()); BigDecimal num2 = new BigDecimal(etNum2.getText().toString()); BigDecimal result = num1.divide(num2); //这里num2不能为零。 tvResult.setText(String.valueOf(result)); }
下面的代码为补丁包代码。我们主要是替换doDivideLogic的方法。补丁包这里为一个独立的android project项目,当然你需要把依赖的主项目的class文件打包为一个jar文件作为依赖。比如如下代码的MainActivity。补丁的代码如下:
/** * Created by denny on 2015/7/20. */ public class DivideLogicPatch implements IPatch { @Override public void handlePatch(PatchParam patchParam) throws Throwable { Class<?> cls = null; try { cls= patchParam.context.getClassLoader() .loadClass("sample.dexposed.vip.com.dexposedsample.MainActivity"); } catch (ClassNotFoundException e) { e.printStackTrace(); return; } DexposedBridge.findAndHookMethod(cls, "doDivideLogic", new XC_MethodReplacement(){ @Override protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable { Field etNum1Field = XposedHelpers.findField(MainActivity.class, "etNum1"); EditText etNum1 = (EditText) etNum1Field.get(methodHookParam.thisObject); Field etNum2Field = XposedHelpers.findField(MainActivity.class, "etNum2"); EditText etNum2 = (EditText) etNum2Field.get(methodHookParam.thisObject); Field tvResultField = XposedHelpers.findField(MainActivity.class, "tvResult"); TextView tvResult = (TextView) tvResultField.get(methodHookParam.thisObject); String val = etNum2.getText().toString(); if (val != null && "0".equals(val)) { //被除数是否为0判断。 tvResult.setText("被除数不能为0"); }else { BigDecimal num1 = new BigDecimal(etNum1.getText().toString()); BigDecimal num2 = new BigDecimal(val); BigDecimal result = num1.divide(num2); tvResult.setText(String.valueOf(result)); } return null; } }); } }
发现一个问题:在加载补丁包的时候需要调用DexposedBridge.canDexposed(context)方法才能加载成功。看了下源码,原来是在这方法里面加载so文件。
这个代码示例,我们是把补丁包app-patch.apk放到项目的assets,然后拷贝到sdcard中进行装载,如果是真实的项目的话应该是从网上下载补丁包,然后加载。代码可以从下面的链接下载:
DexposedSample.zip
DexposedSamplePatch.zip
Sample运行视频
发表评论
-
安卓各种长知识的技术文章,不断更新
2015-10-27 18:24 863http://blog.udinic.com/2015/09 ... -
发现一个android sdk更新神速的镜像
2015-09-02 11:26 1003mirrors.dormforce.net:80 //(栋力无 ... -
gradle项目中怎么集中管理你的依赖库
2015-08-16 11:30 766项目结构 引用root --gradleScript ... -
解决android-Ultra-Pull-To-Refresh下拉刷新组件中嵌套ViewPager的一个bug
2015-08-02 00:15 17129在项目中使用了android-Ultra-Pull-To-Re ... -
android有质量的面试题
2015-03-17 14:31 1017https://github.com/android-cn/i ... -
提高Android Studio的gradle编译速度。
2015-03-12 14:12 4463发现用Android Studio的make和直接使用comm ... -
gradlew wrapper使用下载到本地的gradle.zip文件安装。
2015-03-12 01:26 15533使用gradlew来build项目时,有时候老是需要下载gra ... -
gradlew wrapper设置代理下载gradle
2015-02-27 18:25 46381. HTTP Only Proxy configuratio ... -
认识mqtt
2015-01-30 11:43 1144http://www.hivemq.com/mqtt-esse ... -
Google的Android性能模式
2015-01-14 14:44 813http://www.infoq.com/cn/news/20 ... -
反对Fragment的理由,顺便叫你如果创建自己的自定义view
2014-12-18 17:08 1183下面这篇文章讲了反对Fragment的理由,顺便叫你如果创建自 ... -
获取status bar的高度
2014-12-16 19:52 1339public static int getStatus ... -
最新的appCompat support library中,actionbar的自定义view不能占用全部的宽度
2014-12-02 23:22 1014<style name="AppTheme&q ... -
ScrollTricks实现StickHeader效果
2014-11-06 19:07 1174https://code.google.com/p/roman ... -
AppCompat v21 — Material Design for Pre-Lollipop Devices!
2014-10-23 11:03 946http://android-developers.blogs ... -
国内Android Sdk Manager不能更新的问题。
2014-09-15 15:49 1015加hosts 引用203.208.46.146 dl.goo ... -
在Centos上安装android sdk遇到的问题。
2014-09-15 12:00 1429安装好android sdk后, 打包时老是会有下面的问题。 ... -
Android的一些制作图表按钮的工具
2014-09-09 16:36 1582Android Button Maker Android P ... -
DESIGNER'S GUIDE TO DPI
2014-08-29 14:37 501强烈建议美工看看, 对于移动app的多密度屏幕的支持 http ... -
java,android中https请求调用使用安全的方式
2014-08-20 17:07 4128那遇到这种情况,怎么处理呢?有以下两种方案: 1)按照以上 ...
相关推荐
stm32+esp8266+mqtt/onenet智能家居
Android开发不用存储权限进行拍照,得到拍照后的图片效果。有一点难度,关键是存储路径的定义。
j
反向Lora提高画面细节。
小秘书(凤凰电话管理系统)【纽曼声卡版小秘书】,主要用来做为来电自动录音功能。
基于SpringBoot的疫情居家检测管理系统,系统包含三种角色:管理员、用户、医生,主要功能如下。 【用户功能】 1. 首页:获取系统信息。 2. 论坛:参与居民讨论和分享信息。 3. 公告:查看社区发布的各类公告。 4. 医保信息:了解医疗保障相关信息。 5. 个人中心:管理个人信息,查看预约和就诊历史。 【管理员功能】 1. 首页:查看系统整体。 2. 个人中心:管理管理员的个人信息。 3. 管理员管理:维护系统管理员的账户信息。 4. 医生管理:添加、编辑和删除医生信息。 5. 用户管理:查看和管理系统用户的信息。 6. 预约管理:审核和管理用户对医生的预约服务。 7. 就诊历史管理:查看和管理用户的就诊历史记录。 8. 健康信息管理:记录和查看用户的健康信息。 9. 药品管理:管理系统内的药品种类。 10. 药品入库管理:记录和管理药品的入库情况。 11. 药品使用管理:记录和管理药品的使用情况。 12. 医保信息管理:管理医保相关信息。 13. 论坛管理:审核和回复用户在论坛上的帖子。 14. 公告管理:发布、编辑和管理公告信息。 15. 基础数据管理:管理系统的基础数据。 16. 轮播图信息:管理系统首页的轮播图展示。 【医生功能】 1. 首页:查看医生个人信息。 2. 个人中心:管理医生的个人信息。 3. 预约管理:查看和管理用户对医生的预约服务。 4. 就诊历史管理:查看和管理用户的就诊历史记录。 5. 健康信息管理:记录和查看用户的健康信息。 6. 药品管理:管理系统内的药品种类。 7. 药品入库管理:记录和管理药品的入库情况。 8. 药品使用管理:记录和管理药品的使用情况。 9. 医保信息管理:管理医保相关信息。 10. 论坛管理:审核和回复用户在论坛上的帖子。 11. 公告管理:发布、编辑和管理公告信息。 12. 轮播图信息:管理系统首页的轮播
基于python的Opencv项目实战.zip
鸿蒙开发画廊效果功能,中间大,两边小的浏览效果,难度不小,进行了一定的封装。很好看的画廊效果
win32汇编环境,网络编程入门之十九
linux
【HD-RK3576-PI】定制用户升级固件
内容概要:本文是关于大规模L1正则化线性分类优化方法和软件比较的补充材料,由台湾大学计算机科学系的研究团队撰写。文章详细介绍了GLMNET算法的核心公式推导及其具体实现步骤,包括如何计算L¯j(0; X˜),以及如何维护关键变量以减少计算量。此外,文中对比了多种求解器(如CDN、IPM、TRON等)在不同数据集上的性能,涵盖达到特定停止准则所需时间、迭代次数及每次迭代的平均成本。研究结果显示,在大多数数据集上,CDN方法表现最优,但在极严格的条件下,IPM方法表现更好。对于L1和L2正则化的逻辑回归,文中指出L1正则化在某些数据类型上可能提供更好的准确性,但训练时间较长,因此推荐先尝试L2正则化用于分类任务,而L1正则化更适合特征选择。 适合人群:对机器学习算法尤其是正则化技术有一定了解的数据科学家和研究人员。 使用场景及目标:①需要进行大规模线性分类问题的优化;②比较不同优化方法和工具包在实际应用中的效果;③理解L1和L2正则化在逻辑回归中的区别及其适用情况。 其他说明:本文提供了详细的数学推导和实验结果分析,有助于深入理解各种优化方法的工作原理及其优劣。读者可以通过这些内容选择最适合自身需求的算法和工具包。
西电A测或通院微控温度仿真控制系统的proteus文件
华为ONT使能2.0工具
basalt_top
无极调速数控车床主轴箱装配CAD图.rar
乳液涂料生产流程图.rar
训练集数据