<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet href='http://feed.feedsky.com/styles/temp01.xsl' type='text/xsl' ?><!--这是一个由Feedsy提供技术支持的Feed，为了提高读者阅读的体验，以及满足用户美化自己Feed的需要，我们设计了多种精美的Feed模板，提供给大家选择，所有最终呈现出来的样式，皆由用户自愿选择使用，未经许可，任何团体和个人，请不要擅自修改样式或者盗用，这是对于用户选择权的尊重。--><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:fs="http://www.feedsky.com/namespace/feed" xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"><channel><atom:link href="http://feed.feedsky.com/gming" type="application/rss+xml" rel="self"></atom:link><fs:self_link href="http://feed.feedsky.com/gming" type="application/rss+xml"></fs:self_link><lastBuildDate>Thu, 17 May 2012 13:55:30 GMT</lastBuildDate><title>鸣的博客</title><description>关注互联网,Python,Google App Engine,记录杂七杂八的生活。</description><link>http://pipes.yahoo.com/pipes/pipe.info?_id=e4a5e8b966cd9d1f80fe58ccd235fa5f</link><pubDate>Sat, 19 May 2012 01:03:31 GMT</pubDate><item><title>Android打包成apk流程简析</title><link>http://item.feedsky.com/~feedsky/gming/~8811415/639996572/6423441/1/item.html</link><content:encoded>&lt;p&gt;最近研究了一下Android打包apk的流程，简要描述一下。&lt;/p&gt;
&lt;p&gt;我们可以跟随android的sdk目录下的tools/ant/build.xml文件的描述来一窥打包apk流程究竟。&lt;/p&gt;
&lt;p&gt;首先这是用ant打包的过程，eclipse打包流程应该大抵一样。用ant打包前，如果project不是用ant创建的，先需要执行android update project -p /path/to/project。该命令会在project目录下生成相应的配置文件。如build.xml（与sdk下的那个不同），project.properties，local.properties等。生成的几个文件都是项目相关的配置参数等。ant打包需要build.xml配置文件，project下的配置文件包含sdk/tools/ant/build.xml文件。&lt;/p&gt;
&lt;p&gt;project下的build.xml相对简单了，设定一些project属性，引用了project.properties，local.properties等文件。build.xml设定了ant的默认行为(target)是help。显示相应帮助。&lt;/p&gt;
&lt;p&gt;sdk/tools/ant/build.xml相对复杂很多，一共有1300+行。乍看很多，粗粗分析开来，一块一块也相对较为明朗。即便我对ant配置一知半解，也看个大概明白。&amp;lt;property&amp;gt;就是设定一些key-value的属性，&amp;lt;target&amp;gt;就是ant对应的目标，类似于Makefile的那个目标。&lt;/p&gt;
&lt;p&gt;这个build.xml相应地方做了良好的注释。这个文件内容分布大概如下：&lt;/p&gt;
&lt;p&gt;1.定义一些覆盖默认设置的属性。还是有一些挺有意思的属性值得一看的，比如android.package.excludes，设定该属性可以排除编译一部分代码。再比如version.code，version.name可以替换AndroidManifest.xml中的相关版本内容。&lt;/p&gt;
&lt;p&gt;2.自定义了一些任务。凭借我的揣测，这是ant提供的一些扩展，这些任务是通过${sdk.dir}/tools/lib/anttasks.jar这个jar包来导入定义的。定义了很多，列举一二，如com.android.ant.NewSetupTask，com.android.ant.AaptExecTask，com.android.ant.IfElseTask等等。&lt;/p&gt;
&lt;p&gt;3.其它属性。主要是编译流程用到的一些变量属性，包含输入目录，输出目录，工具位置等。这里可以看见一些经常看到用到的目录和工具。比如src自不用多说，还有gen目录，libs目录等。此处加一段故事，很久之前，我是用Eclipse好的project在带我的bear那里用ant编译有问题，问题在于我将外部的jar包放在了lib目录下，ant编译的时候会找不到这个jar包了，但是放在libs里就可以了，到了这就可以解释了，因为build.xml暗暗的定义了这个默认的文件夹的名字。再插一句最新的adt也支持放在libs中而不需要做多余路径设定了。&lt;/p&gt;
&lt;p&gt;4.宏定义。定义了一些多次用的流程为宏。比如do-only-if-not-library，如果不是android library project就怎样做。package-helper等等。&lt;/p&gt;
&lt;p&gt;5.Build过程的一些Target。第一个是nodeps，很简单是设定了一个属性，来设定targets间是否存在依赖关系。然后有-per-clean，clean清空bin，gen目录做了这么些事。（前面加-的target，从某种程度来说是private的target，因为输入ant -xxx的时候，-xxx会当作ant的参数，而不是build的目标）&lt;/p&gt;
&lt;p&gt;然后就涉及打包流程了。&lt;strong&gt;-setup&lt;/strong&gt;，做一些初始化工作，创建bin目录等，设定一些属性等。-build-setup，也是做一些build的初始化工作。然后是-per-build这个是空的，这个是用来给用户做一些自定义设定或者实现预留的，后面类似这样预留的无内容的部分我就不讲了。然后是&lt;strong&gt;-code-gen&lt;/strong&gt;，这个就有意思一些了，最为人熟知的android中的R文件就要生成了，生成R文件在这个过程做了定义，通过aapt程序（这个程序很有意思，这里略去不讲，没准下回会讲）生成R文件。-code-gen过程还有一些重量级的东西。比如生成用于进程通信的aidl文件相应类的生成，还有renderscript的生成。还有BuildConfig文件的生成。然后就是激动人心的compile编译过程了，就是&lt;strong&gt;javac&lt;/strong&gt;做编译，生成class文件。这里有些令人激动的事情。就是Android为了代码复用，提出了library project的概念，某种程度上还不错，但是扩展能力有限，还是有些坑爹的，而且有一些限制。此处再插故事一则，我有3个project，分别标记为a,b,c，a,b分别是library project，然后依赖是c=&amp;gt;b=&amp;gt;a（c依赖于b，b依赖于a），我想对b做代码混淆，但是出现一些依赖问题。因为android的现在的这个build过程并不把在前面-code-gen生成的依赖的子library的R文件编译到这个library自己的这里，所以在混淆b的时候，会出现a中的R无法找到的问题，因为a中的R会被便已到c中，很混乱吧。事情是这样，但是错误在自己，因为对android的library和整个project的打包流程不清楚，所以造成了上面的窘境。其实根本不用混淆b工程，因为b工程的class会最终放到c中，最后在c中混淆就行了。晕了。。。&lt;/p&gt;
&lt;p&gt;继续说打包流程，编译完了，然后就是&lt;strong&gt;-obfuscate&lt;/strong&gt;混淆过程了，混淆默认只在release模式下才进行，内部有一些判断。关于混淆的一些介绍，可以参见我的上一篇博文《&lt;a rel=&quot;nofollow&quot;&gt;ProGuard总结和混淆Android代码中遇到的问题的解决方法以及寻找getSomething游戏&lt;/a&gt;》。然后是-dex，&lt;strong&gt;转.class到.dex&lt;/strong&gt;过程。开发Android的都知道，Android没有用标准的jvm，而是自己专门为移动设备优化实现的dalvik vm。这个过程会把所有的.class文件打包到一个.dex文件中。&lt;/p&gt;
&lt;p&gt;至此，代码build过程就结束了。全都结束了吗？还没有，Android还有编译资源，再说还没打成apk包呢。&lt;/p&gt;
&lt;p&gt;跟资源处理有关的过程先是&lt;strong&gt;-crunch&lt;/strong&gt;这个过程就是对png图片做一些压缩处理。具体怎么处理的咱就不细究了，想知道的话可以研究源代码去。然后又到了激动人心的资源打包过程&lt;strong&gt;-package-resources&lt;/strong&gt;，这个过程就是用牛x的aapt，将所有res目录下的资源文件manifest等文件打包编译处理。这其中有一个对于.9.png的说明。我们知道.9.png的图片是带一圈透明画有黑点的图片。这个过程aapt会将.9.png处理，将透明带黑点写入二进制。和原来的图是不一样了的，逆向工程的时候对.9.png有很多限制。apktool的wiki上有相关说明。xda论坛上也有相关讨论。还有一点是将普通.png改为.9.png的后，ant全程打包是不会有问题的。但是aapt确实对这种情况做了抛出异常处理，所以我猜想是在crunch时做了什么处理，还未证实。&lt;/p&gt;
&lt;p&gt;资源文件也build好了，然后对于debug或release。就是&lt;strong&gt;打包成apk&lt;/strong&gt;。然后&lt;strong&gt;给apk签名&lt;/strong&gt;，签名方式上两种模式有些不同处理。debug会进行debug签名，release需要你提供你的签名文件等。然后或进行&lt;strong&gt;zipalign&lt;/strong&gt;操作，字节对齐。&lt;/p&gt;
&lt;p&gt;至此，整个过程就结束了。&lt;/p&gt;
&lt;p&gt;还有一些关于测试和安装卸载的target就不写了。&lt;/p&gt;
&lt;p&gt;（&lt;strong&gt;重点过程，加粗标识了，看一遍加粗部分，基本就能知道个大概了&lt;/strong&gt;）&lt;/p&gt;

&lt;h4&gt;相关阅读&lt;/h4&gt;
&lt;ul&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/11/28/Android-compatibility-package-fragment-loader-actionbar.html&quot;&gt;Android兼容包及Fragment, Loader, ActionBar简介&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/01/28/phonegap-source-code-analyzing-java-js-plugin-mechanism.html&quot;&gt;phoengap源码解析——插件机制，java和js代码互调用详解&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/01/16/android-tablet.html&quot;&gt;买了个Android平板——小破文章一篇&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/12/25/android-reader-txt.html&quot;&gt;Android阅读器相关资料（下-txt）&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/12/18/experience-android-4.0-nexus-s.html&quot;&gt;Nexus S体验Android4.0&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/12/24/android-reader-pdf.html&quot;&gt;Android阅读器开发相关资料（上-pdf）&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/04/27/proguard-summary-some-problem-answer.html&quot;&gt;ProGuard总结和混淆Android代码中遇到的问题的解决方法以及寻找getSomething游戏&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/02/6/fedora-16-x64-compile-android-4.0.3-source-code.html&quot;&gt;Fedora16_x64编译Android4.0.3源码&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/03/5/how-speed-your-android-programming.html&quot;&gt;加速Android开发，玩转Eclipse&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/01/25/phonegap-webapp-decompile-codereader.html&quot;&gt;PhoneGap，Web Application，反编译，代码阅读器——4in1游戏卡，寻觅童年游戏机快感&lt;/a&gt;&lt;/li&gt;
    
&lt;/ul&gt;
&lt;p&gt;本文网址:&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/05/17/android-package-apk-procedure.html&quot;&gt;http://www.qhm123.com/2012/05/17/android-package-apk-procedure.html&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/639996572/gming/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/gming/~8811415/639996572/6423441/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><category>how</category><pubDate>Thu, 17 May 2012 21:55:30 +0800</pubDate><guid isPermaLink="false">http://www.qhm123.com/?p=1444003</guid><fs:srclink>http://www.qhm123.com/2012/05/17/android-package-apk-procedure.html</fs:srclink><fs:srcfeed>http://pipes.yahoo.com/pipes/pipe.run?_id=e4a5e8b966cd9d1f80fe58ccd235fa5f&amp;_render=rss</fs:srcfeed><fs:itemid>feedsky/gming/~8811415/639996572/6423441</fs:itemid></item><item><title>ProGuard总结和混淆Android代码中遇到的问题的解决方法以及寻找getSomething游戏</title><link>http://item.feedsky.com/~feedsky/gming/~8811415/638149805/6423441/1/item.html</link><content:encoded>&lt;p&gt;先说点题外的，前一秒我心想干点什么呢，想到写篇博文吧，最近写的频率有点低了。另外标题有点长了。&lt;/p&gt;
&lt;p&gt;进正文。&lt;/p&gt;
&lt;p&gt;前些日子几次遇到ProGuard的问题，想偷个懒，没好好RTFM,后来通读了一下ProGuard的Manual，有点收获，总结一下。&lt;/p&gt;
&lt;p&gt;主要是读了Usage部分，&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://proguard.sourceforge.net/#manual/usage.html&quot;&gt;http://proguard.sourceforge.net/#manual/usage.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration:line-through;&quot;&gt;命令：java -jar proguard.jar options ... 或&amp;nbsp;java -jar proguard.jar @myconfig.pro(myconfig.pro是配置文件)。Android提供的ant脚本把这个包含了进去，ADT也相应做了处理，所以基本不会直接用到这个。proguard包含在android sdk的tools目录下。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration:line-through;&quot;&gt;options或者配置文件设定了proguard的参数，分为Input/Output Options，Input/Output Options，Shrinking Options，Optimization Options，Obfuscation Options，Preverification Options，General Options 这些可选的参数。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;从配置选项中其实可以看出，proguard有几部分的功能，Shrinking，Optimization，Obfuscation，Preverification。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1. Shrinking&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;就是缩减代码，他的工作是把代码中没被引用或者依赖的类、类成员删掉。可以通过Keep参数来设定保存。我之前就遇到这么一个问题，这里简称为&amp;ldquo;寻找getSomething游戏&amp;rdquo;（这个问题几乎会贯穿全文），我写了这么一段代码，大意如下：&lt;/p&gt;
&lt;pre&gt;public class JavascriptInterface {
    void getSomething(String something) {}
}

webview.addJavascriptObject(new JavascriptInterface(), &quot;jsi&quot;);
webview.loadUrl(&quot;javascript:window.jsi.getSomething(&quot;hello&quot;)&quot;);&lt;/pre&gt;
&lt;p&gt;就是通过js给java传个值。然后打包运行正常，再然后使用proguard处理打包，结果不正常，提示大意为object没有getSomething方法。&lt;/p&gt;
&lt;p&gt;出了什么问题呢，因为android的proguard默认配置是开启Shrinking的，所以结果是getSomething(String)方法被删掉了，我通过反编译打出来的apk包也证实了这一点。&lt;/p&gt;
&lt;p&gt;解决方法是，在配置文件中加入keep&lt;/p&gt;
&lt;p&gt;-keep public class yourpackagename.JavascriptInterface&lt;/p&gt;
&lt;p&gt;对于keep有几个类似的选项，下面的表格抄自：http://proguard.sourceforge.net/#manual/usage.html&lt;/p&gt;
&lt;table cellpadding=&quot;5&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;th&gt;Keep&lt;/th&gt;
&lt;td&gt;From being removed or renamed&lt;/td&gt;
&lt;td&gt;From being renamed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Classes and class members&lt;/td&gt;
&lt;td bgcolor=&quot;#E0E0E0&quot;&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;#keep&quot;&gt;&lt;code&gt;-keep&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td bgcolor=&quot;#E0E0E0&quot;&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;#keepnames&quot;&gt;&lt;code&gt;-keepnames&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Class members only&lt;/td&gt;
&lt;td bgcolor=&quot;#E0E0E0&quot;&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;#keepclassmembers&quot;&gt;&lt;code&gt;-keepclassmembers&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td bgcolor=&quot;#E0E0E0&quot;&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;#keepclassmembernames&quot;&gt;&lt;code&gt;-keepclassmembernames&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Classes and class members, if class members present&lt;/td&gt;
&lt;td bgcolor=&quot;#E0E0E0&quot;&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;#keepclasseswithmembers&quot;&gt;&lt;code&gt;-keepclasseswithmembers&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td bgcolor=&quot;#E0E0E0&quot;&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;#keepclasseswithmembernames&quot;&gt;&lt;code&gt;-keepclasseswithmembernames&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;我就不解释了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.&amp;nbsp;Optimization&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;代码优化，说是bytecode层级的优化，具体怎么优化的我就不知道，而且Android默认配置也没开起这个。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3.&amp;nbsp;Obfuscation&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这个就是传说中的混淆了，可以通过-dontobfuscate关闭（关闭为什么还用proguard呢？）什么是混淆呢，就是把类和类成员 （包括变量和函数）的名字替换成相应的随机字符，大大增加别人解包破解你代码的难度。混淆过程生成mapping文件，记录每个类和成员被替换称什么随机字符了，也可以自己提供一些生成随机字符的规则，这里提供了很多选项，很有意思。&lt;/p&gt;
&lt;p&gt;前面说道&amp;ldquo;寻找getSomething游戏&amp;rdquo;的例子，其实象刚才那样做并没有搞定这个问题，这里一个重要的概念是，&lt;strong&gt;单写一行keep并不能让proguard不做成员变量的混淆处理，而只是不被删掉&lt;/strong&gt;。所以getSomething作为一个类成员方法依然会被混淆，变成了一个随机字符，比如a，那么这句代码：webview.loadUrl(&quot;javascript:window.jsi.getSomething(&quot;hello&quot;)&quot;); 显然不再能正常使用了，因为它已经找不到getSomething了。&lt;/p&gt;
&lt;p&gt;过程中我反复解包，由于认为keep就可以防止混淆，觉得无解，因我解包发现每次getSomething都变成了a，所以进行了一种很狗屎的方法的尝试，将webview.loadUrl(&quot;javascript:window.jsi.&lt;strong&gt;getSomething&lt;/strong&gt;(&quot;hello&quot;)&quot;);换成webview.loadUrl(&quot;javascript:window.jsi.&lt;strong&gt;a&lt;/strong&gt;(&quot;hello&quot;)&quot;);，把getSomething直接写成了a。。。但是由于我的实际JavascriptInterface类里面还有一些别的东西，有些东西也会被混淆成a，所以居然连狗屎运都没有。&lt;/p&gt;
&lt;p&gt;后来我发现-useuniqueclassmembernames这个参数，顾名思义，可以让类成员使用唯一的名字，于是我给getSomething改成了后来混淆后的唯一的名字，终于在寻找getSomething的游戏中，找到了它，虽然它已经不叫getSomething了。。。&lt;/p&gt;
&lt;p&gt;还是觉得这个方法太屎了，胜之不武。&lt;/p&gt;
&lt;p&gt;关于keep有个复杂的语法，下面依然抄自ProGuard文档。&lt;/p&gt;
&lt;pre&gt;[&lt;strong&gt;@&lt;/strong&gt;&lt;em&gt;annotationtype&lt;/em&gt;] [[&lt;strong&gt;!&lt;/strong&gt;]&lt;strong&gt;public&lt;/strong&gt;|&lt;strong&gt;final&lt;/strong&gt;|&lt;strong&gt;abstract&lt;/strong&gt;|&lt;strong&gt;@&lt;/strong&gt; ...] [&lt;strong&gt;!&lt;/strong&gt;]&lt;strong&gt;interface&lt;/strong&gt;|&lt;strong&gt;class&lt;/strong&gt;|&lt;strong&gt;enum&lt;/strong&gt; &lt;em&gt;classname&lt;/em&gt;
    [&lt;strong&gt;extends&lt;/strong&gt;|&lt;strong&gt;implements&lt;/strong&gt; [&lt;strong&gt;@&lt;/strong&gt;&lt;em&gt;annotationtype&lt;/em&gt;] &lt;em&gt;classname&lt;/em&gt;]
[&lt;strong&gt;{&lt;/strong&gt;
    [&lt;strong&gt;@&lt;/strong&gt;&lt;em&gt;annotationtype&lt;/em&gt;] [[&lt;strong&gt;!&lt;/strong&gt;]&lt;strong&gt;public&lt;/strong&gt;|&lt;strong&gt;private&lt;/strong&gt;|&lt;strong&gt;protected&lt;/strong&gt;|&lt;strong&gt;static&lt;/strong&gt;|&lt;strong&gt;volatile&lt;/strong&gt;|&lt;strong&gt;transient&lt;/strong&gt; ...] &lt;strong&gt;&amp;lt;fields&amp;gt;&lt;/strong&gt; |
                                                                      (&lt;em&gt;fieldtype fieldname&lt;/em&gt;)&lt;strong&gt;;&lt;/strong&gt;
    [&lt;strong&gt;@&lt;/strong&gt;&lt;em&gt;annotationtype&lt;/em&gt;] [[&lt;strong&gt;!&lt;/strong&gt;]&lt;strong&gt;public&lt;/strong&gt;|&lt;strong&gt;private&lt;/strong&gt;|&lt;strong&gt;protected&lt;/strong&gt;|&lt;strong&gt;static&lt;/strong&gt;|&lt;strong&gt;synchronized&lt;/strong&gt;|&lt;strong&gt;native&lt;/strong&gt;|&lt;strong&gt;abstract&lt;/strong&gt;|&lt;strong&gt;strictfp&lt;/strong&gt; ...] &lt;strong&gt;&amp;lt;methods&amp;gt;&lt;/strong&gt; |
                                                                                           &lt;strong&gt;&amp;lt;init&amp;gt;(&lt;/strong&gt;&lt;em&gt;argumenttype,...&lt;/em&gt;&lt;strong&gt;)&lt;/strong&gt; |
                                                                                           &lt;em&gt;classname&lt;/em&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;em&gt;argumenttype,...&lt;/em&gt;&lt;strong&gt;)&lt;/strong&gt; |
                                                                                           (&lt;em&gt;returntype methodname&lt;/em&gt;&lt;strong&gt;(&lt;/strong&gt;&lt;em&gt;argumenttype,...&lt;/em&gt;&lt;strong&gt;)&lt;/strong&gt;)&lt;strong&gt;;&lt;/strong&gt;
    [&lt;strong&gt;@&lt;/strong&gt;&lt;em&gt;annotationtype&lt;/em&gt;] [[&lt;strong&gt;!&lt;/strong&gt;]&lt;strong&gt;public&lt;/strong&gt;|&lt;strong&gt;private&lt;/strong&gt;|&lt;strong&gt;protected&lt;/strong&gt;|&lt;strong&gt;static&lt;/strong&gt; ... ] &lt;strong&gt;*;&lt;/strong&gt;
    ...
&lt;strong&gt;}&lt;/strong&gt;]
&lt;/pre&gt;
&lt;p&gt;。。。&lt;/p&gt;
&lt;p&gt;我之前看了这段就跳过了。后来耐心看下还是很容易看懂的，而且这个部分后面有个说明。&lt;/p&gt;
&lt;p&gt;这些符号其实很常见了，&amp;ldquo;|&amp;rdquo; 表示或关系，&amp;ldquo;!&amp;rdquo;表示非，&amp;ldquo;[]&amp;rdquo;表示可选，&amp;ldquo;...&amp;rdquo;代表等等，黑色的部分是关键字。&lt;/p&gt;
&lt;p&gt;之前-keep public class yourpackagename.JavascriptInterface 这样写，注意语法有个花括号，里面是用来说明成员变量是否keep的，可以写一个范围，比如写&amp;lt;fields&amp;gt;就是所有字段不被混淆，&amp;lt;methods&amp;gt;就是所有方法不被混淆，＊就是所有都不被混淆。还可以单独指出哪个函数不被混淆，比如对于&amp;ldquo;寻找getSomething游戏&amp;rdquo;，可以这样写：&lt;/p&gt;
&lt;pre&gt;-keep public class yourpackagename.JavascriptInterface {
  void getSomething(java.lang.String)
}&lt;/pre&gt;
&lt;p&gt;这样，getSomething函数就不会被混淆了。这里一个值得注意的问题是，所有类都要写全称，就是包名.类名，String要写成java.lang.String，我最开始就只写了String，结果是还别混淆了，郁闷了很久。&lt;/p&gt;
&lt;p&gt;好了，&amp;ldquo;寻找getSomething游戏&amp;rdquo;完胜了。。。它再也不会找不到getSomething了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4.&amp;nbsp;Preverification&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;预验证，在载入类之前的验证，《&lt;span style=&quot;font-family:Menlo, monospace;font-size:11px;line-height:normal;white-space:pre-wrap;&quot;&gt;&lt;a rel=&quot;nofollow&quot;&gt;Android前向兼容的几个问题&lt;/a&gt;&lt;/span&gt;》里面说的大概是这个，Android的ProGuard配置也没有开启这个，我也不是很清楚，就不说了。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;还有很多选项，不在赘述，还是&lt;strong&gt;RTFM&lt;/strong&gt;吧！&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;

&lt;h4&gt;相关阅读&lt;/h4&gt;
&lt;ul&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/11/28/Android-compatibility-package-fragment-loader-actionbar.html&quot;&gt;Android兼容包及Fragment, Loader, ActionBar简介&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/01/28/phonegap-source-code-analyzing-java-js-plugin-mechanism.html&quot;&gt;phoengap源码解析——插件机制，java和js代码互调用详解&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/01/16/android-tablet.html&quot;&gt;买了个Android平板——小破文章一篇&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/11/21/Android-backward-compatibility-problem.html&quot;&gt;Android前向兼容的几个问题&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/12/25/android-reader-txt.html&quot;&gt;Android阅读器相关资料（下-txt）&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/12/18/experience-android-4.0-nexus-s.html&quot;&gt;Nexus S体验Android4.0&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/12/24/android-reader-pdf.html&quot;&gt;Android阅读器开发相关资料（上-pdf）&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/02/6/fedora-16-x64-compile-android-4.0.3-source-code.html&quot;&gt;Fedora16_x64编译Android4.0.3源码&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/03/5/how-speed-your-android-programming.html&quot;&gt;加速Android开发，玩转Eclipse&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/01/25/phonegap-webapp-decompile-codereader.html&quot;&gt;PhoneGap，Web Application，反编译，代码阅读器——4in1游戏卡，寻觅童年游戏机快感&lt;/a&gt;&lt;/li&gt;
    
&lt;/ul&gt;
&lt;p&gt;本文网址:&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/04/27/proguard-summary-some-problem-answer.html&quot;&gt;http://www.qhm123.com/2012/04/27/proguard-summary-some-problem-answer.html&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638149805/gming/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/gming/~8811415/638149805/6423441/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><category>summary</category><pubDate>Fri, 27 Apr 2012 20:33:44 +0800</pubDate><guid isPermaLink="false">http://www.qhm123.com/?p=1402003</guid><fs:srclink>http://www.qhm123.com/2012/04/27/proguard-summary-some-problem-answer.html</fs:srclink><fs:srcfeed>http://pipes.yahoo.com/pipes/pipe.run?_id=e4a5e8b966cd9d1f80fe58ccd235fa5f&amp;_render=rss</fs:srcfeed><fs:itemid>feedsky/gming/~8811415/638149805/6423441</fs:itemid></item><item><title>使用openvswitch配置xen的虚拟化网络，实现网络隔离的故事</title><link>http://item.feedsky.com/~feedsky/gming/~8811415/638149806/6423441/1/item.html</link><content:encoded>&lt;p&gt;这事本没想难易，结果是花掉了我好几个周末的时间才搞通。&lt;/p&gt;
&lt;p&gt;最开始对网络配置各种不懂，我偶有网络课程白学的想法。而且这次又玩虚幻，各种虚拟网络，各种配置，搞得头儿晕晕。实现的目的其实很简单：就是两台物理主机A、B，每台物理主机上各有采用Xen虚拟化的两个VM，可分别标记为A1，A2，B1，B2。可以让这4个虚拟机之间实现网络联通与隔离，消除掉物理主机的概念，好像所有虚拟机都运行在一台物理主机上一样。&lt;/p&gt;
&lt;p&gt;说一下我的实验环境，一台物理主机，然后采用Vmware虚拟了两个主机，然后每个主机再通过Xen虚拟两个虚拟机。有如兔子生娃，一生俩，俩生四。这样我就有了4个虚拟主机。&lt;/p&gt;
&lt;p&gt;（话说当初我的实验环境更为复杂，我搞到一台远程Windows主机，然后远程上去，在上面用Vmware建了个Centos的虚拟机，然后又用Xen虚拟了两个VM，搞得尤为复杂，后来遇到一些问题，遂搞到一台机器上了，这个稍后再说）&lt;/p&gt;
&lt;p&gt;有了实验环境后，就是安装一些软件，首先我使用的是Centos5.x系列的操作系统，然后使用了Xen3.x版本的Xen。（话说这玩应当初我尝试了N多版本，各种问题，各种装操作系统，和配置Xen环境，各种等待的过程）&lt;/p&gt;
&lt;p&gt;然后是Xen的虚拟化网络，Xen的虚拟化网络有三种方式，默认的bridge，还有route和nat（但是名字这我看了几个文档 &amp;nbsp;，各自介绍又有点区别）。&lt;/p&gt;
&lt;p&gt;基础知识我这就不说了（前面已经跑偏不少了），几种网络方式可以参看如下几个网址：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;http://wiki.kartbuilding.net/index.php/Xen_Networking#Overview_of_Networks_with_Xen&lt;/li&gt;
&lt;li&gt;http://wiki.xen.org/wiki/Xen_Networking&lt;/li&gt;
&lt;li&gt;http://wiki.xen.org/wiki/HostConfiguration/Networking&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;而且Xen的虚拟化网络搞出一堆设备、接口出来，如：eth0，peth0，vifx.x，veth，xenbr0等等。&lt;/p&gt;
&lt;p&gt;这些东西其实主要是通过xen的几个网络脚本搞出来的，在/etc/xen/scripts目录下，有一些网络脚本，例如network-bridge，桥接方式，主机用到的脚本，仔细研读这个脚本还是很有好处的，能了解xen初始化虚拟网的过程。&lt;/p&gt;
&lt;p&gt;有几篇博文不错，可以帮助理解，如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;http://blog.csdn.net/sahusoft/article/details/5996453&lt;/li&gt;
&lt;li&gt;https://sites.google.com/site/gnawux/Home/%E6%9C%AC%E4%BA%BA%E8%AF%91%E4%BD%9C/xen%E7%BB%84%E7%BD%91#network-bridge_%E8%84%9A%E6%9C%AC &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;好了，现在说openvswitch，这个是在查找网络隔离解决方案中，找到的，这个东西可以说是虚拟的交换机。&lt;/p&gt;
&lt;p&gt;这篇博文介绍了一下openvswitch：http://bengo.blog.51cto.com/4504843/791213，可以大体了解一下。openvswitch有个http://openvswitch.org/support/config-cookbooks/vlan-configuration-cookbook/这么个文档，于是我一下相中了它，这个功能整合我意，于是开始鼓捣openvswitch，又是各种配置，但是怎么配置都不行，虽说openvswitch官方声明支持xen，但是缺乏良好的文档来说明怎么和xen结合起来，或者说根本没有文档，我翻看了一些邮件列表，找到一两个相关的讨论，但是也都是没有结果。&lt;/p&gt;
&lt;p&gt;配置openvswitch虚拟网络，经常容易把xen的虚拟网络搞毁，终于偶有一次惊奇的发现使用openvswitch的虚拟网络，替换了linux bridge的网桥网络，一阵窃喜，不幸的是到隔了一周的时间，到下一个周末的时候，忘记上次是怎么配置的了，所以又是乱搞。搞了又搞，终于鼓捣成了，然后下一周又忘了，这过程中我几次想写个文，记录一下配置的过程，但是都没写，侥幸想这次应该不会忘了，于是就又忘了。但其实所谓忘了，不过是还没有了解其中的原理。后来驾轻就熟后，往往怎么搞都没有问题了。&lt;/p&gt;
&lt;p&gt;后来又遇到一个问题，前面提到了，就是交换机truck口的问题，之前是两台vmware虚拟机，而且一台还是远程的，网段还小有区别，虽然是在一个网段里，后来问老师，老师说这样会有问题，于是搞到一台机器上，终于成功成仁。（话说最开始卡在网络上的时候，我一度狂乱，一天给老师发了10封左右邮件，老师当时1封没回，我就1封接1封的发，有什么想法就发过去）&lt;/p&gt;
&lt;p&gt;写到这里我已经不想写什么解决方案，我发现这故事本身往往很精彩，而最后不过是几句话而已。&lt;/p&gt;
&lt;p&gt;于是，最后我无耻的将标题最后加了&amp;ldquo;的故事&amp;rdquo;三个字。&lt;/p&gt;
&lt;p&gt;未完，待续。。。&lt;/p&gt;

&lt;h4&gt;相关阅读&lt;/h4&gt;
&lt;ul&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/01/19/xen-virt-manager-intro.html&quot;&gt;xen,virt-manager简介&lt;/a&gt;&lt;/li&gt;
    
&lt;/ul&gt;
&lt;p&gt;本文网址:&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/04/6/use-openvswitch-config-xen-virtual-vlan.html&quot;&gt;http://www.qhm123.com/2012/04/6/use-openvswitch-config-xen-virtual-vlan.html&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638149806/gming/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/gming/~8811415/638149806/6423441/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><category>how</category><pubDate>Fri, 06 Apr 2012 22:32:23 +0800</pubDate><guid isPermaLink="false">http://www.qhm123.com/?p=1300040</guid><fs:srclink>http://www.qhm123.com/2012/04/6/use-openvswitch-config-xen-virtual-vlan.html</fs:srclink><fs:srcfeed>http://pipes.yahoo.com/pipes/pipe.run?_id=e4a5e8b966cd9d1f80fe58ccd235fa5f&amp;_render=rss</fs:srcfeed><fs:itemid>feedsky/gming/~8811415/638149806/6423441</fs:itemid></item><item><title>加速Android开发，玩转Eclipse</title><link>http://item.feedsky.com/~feedsky/gming/~8811415/638149807/6423441/1/item.html</link><content:encoded>&lt;p&gt;&lt;strong&gt;有用的快捷键&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CTRL+SHIFT+O&amp;mdash;&amp;mdash;整理Import，发现有一堆类没有导入吗，那么试试这个&lt;/li&gt;
&lt;li&gt;CTRL+1&amp;mdash;&amp;mdash;快速修正，发现有个红叉叉吗，那么试试这个&lt;/li&gt;
&lt;li&gt;CTRL+SHIFT+T&amp;mdash;&amp;mdash;想打开一个类文件吗，那么试试这个（你还在去你的project树中去一个一个查找吗？）&lt;/li&gt;
&lt;li&gt;CTRL+E&amp;mdash;&amp;mdash;你打开了一堆文件，想切换到某个打开的文件吗，那么试试这个（你还在去你的tabs栏中一个一个查找吗？）&lt;/li&gt;
&lt;li&gt;CTRL + F11&amp;mdash;&amp;mdash;你不想每次费力的去点击运行按钮吗，那么试试这个&lt;/li&gt;
&lt;li&gt;CTRL + SHIFT + F&amp;mdash;&amp;mdash;乱哄哄的代码对齐，空行，你不能忍受了吗？那么试试这个&lt;/li&gt;
&lt;li&gt;Ctrl+O&amp;mdash;&amp;mdash;你还在用Ctrl+F查找定位函数吗？那么试试这个吧&lt;/li&gt;
&lt;li&gt;Ctrl+T&amp;mdash;&amp;mdash;想快速看看这个类的继承关系吗？那么试试这个&lt;/li&gt;
&lt;li&gt;Ctrl+/（或者Ctrl+Shift+C）&amp;mdash;&amp;mdash;你还在输入//来吧暂时不用的代码注释掉吗？那么试试这个&lt;/li&gt;
&lt;li&gt;Alt+/&amp;mdash;&amp;mdash;智能提示，你不知道吗？&lt;/li&gt;
&lt;li&gt;Alt+Shift+R&amp;mdash;&amp;mdash;名字起的不好，想改改？试试这个&lt;/li&gt;
&lt;li&gt;Alt+Shift+T&amp;mdash;&amp;mdash;与上一个类似的重构功能还有什么，试试这个&lt;/li&gt;
&lt;li&gt;Alt+&amp;larr;,Alt+&amp;rarr;&amp;mdash;&amp;mdash;刚才编辑哪了？试试这个&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;text-align:left;&quot;&gt;以上都是我常用的快捷键，包好用，应该还有一些，现在想不起来了。&lt;/p&gt;
&lt;p style=&quot;text-align:left;&quot;&gt;&lt;strong&gt;代码模版&lt;/strong&gt;&lt;/p&gt;
&lt;p style=&quot;text-align:left;&quot;&gt;当你输入if或者for这种句子的时候，是否会自动补全，选择后一段代码就出来了呢，然后可以在预定位置输入替换词。这个就是代码模板了。&lt;/p&gt;
&lt;p style=&quot;text-align:left;&quot;&gt;比如我们常常打日志，然后要输入Log.d(TAG, &quot;xxxxx&quot;);其中xxxxx是要替换的内容，那么你还在一个字一个字的输入吗？添加一个模版，比如定义名字为logd，那么当你输入完logd，然后自动补全，看，Log.d(TAG, &quot;&quot;);已经出来了哦，而且光标不是定位在末尾哦，而是在两个冒号中间哦，直接输入要输出的日志就好了哦，超级方便的吧。&lt;/p&gt;
&lt;p style=&quot;text-align:left;&quot;&gt;如何添加：打开Preferences/Java/Editor/Templates，然后就可以添加了相应的模版就好了，比如logd的模版是：Log.d(TAG, &quot;${cursor}&quot;);&lt;/p&gt;
&lt;p style=&quot;text-align:left;&quot;&gt;抛砖引玉了。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;快速的移动、操作&amp;mdash;&amp;mdash;Vrapper&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;你用Vim吗，那么你应该尝试一下Vrapper。Vrapper提供了基本的Vim编辑器特性，光标的快速移动，迅速定位到你想要的位置，区块。行首，句首，句中，按字，按字符，按行，F，迅速移动，定位到所需代码处，然后进行相应的操作。如果是Vim党，那就不用我多说了（尽管不是所有features都支持，但是基本够用，详见下面网址的官方介绍）&lt;/p&gt;
&lt;p&gt;我一直在寻找Eclipse与Vim的结合品，目前Vrapper是基于Eclipse插件机制相对较为稳定、好用、轻量的一个。我已经使用了10个月左右，倾情推荐。&lt;/p&gt;
&lt;p&gt;网址：&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://vrapper.sourceforge.net/home/&quot;&gt;http://vrapper.sourceforge.net/home/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;正则&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;正则无处不在，如果你精通它，那么查找、替换的速度将提升一个数量级。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;条例清晰，&lt;/strong&gt;&lt;span style=&quot;color:#ff0000;font-weight:bold;&quot;&gt;如流水一般&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color:#000000;&quot;&gt;显然，这是王道，混乱的代码是侵蚀时间的毒瘤，修复bug是最浪费时间，也是减慢开发速度的毒虫。&lt;/span&gt;当脑袋想清楚一切的逻辑后，这有助于减少bug，便于增加新的feature。如流水一般，清晰，透明，顺畅。总结一个字，爽。&lt;/p&gt;

&lt;h4&gt;相关阅读&lt;/h4&gt;
&lt;ul&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/11/28/Android-compatibility-package-fragment-loader-actionbar.html&quot;&gt;Android兼容包及Fragment, Loader, ActionBar简介&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/01/28/phonegap-source-code-analyzing-java-js-plugin-mechanism.html&quot;&gt;phoengap源码解析——插件机制，java和js代码互调用详解&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/01/16/android-tablet.html&quot;&gt;买了个Android平板——小破文章一篇&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/11/21/Android-backward-compatibility-problem.html&quot;&gt;Android前向兼容的几个问题&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/12/25/android-reader-txt.html&quot;&gt;Android阅读器相关资料（下-txt）&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/12/18/experience-android-4.0-nexus-s.html&quot;&gt;Nexus S体验Android4.0&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/12/24/android-reader-pdf.html&quot;&gt;Android阅读器开发相关资料（上-pdf）&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/04/27/proguard-summary-some-problem-answer.html&quot;&gt;ProGuard总结和混淆Android代码中遇到的问题的解决方法以及寻找getSomething游戏&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/02/6/fedora-16-x64-compile-android-4.0.3-source-code.html&quot;&gt;Fedora16_x64编译Android4.0.3源码&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/01/25/phonegap-webapp-decompile-codereader.html&quot;&gt;PhoneGap，Web Application，反编译，代码阅读器——4in1游戏卡，寻觅童年游戏机快感&lt;/a&gt;&lt;/li&gt;
    
&lt;/ul&gt;
&lt;p&gt;本文网址:&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/03/5/how-speed-your-android-programming.html&quot;&gt;http://www.qhm123.com/2012/03/5/how-speed-your-android-programming.html&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638149807/gming/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/gming/~8811415/638149807/6423441/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><category>how</category><pubDate>Mon, 05 Mar 2012 21:50:43 +0800</pubDate><guid isPermaLink="false">http://www.qhm123.com/?p=1194044</guid><fs:srclink>http://www.qhm123.com/2012/03/5/how-speed-your-android-programming.html</fs:srclink><fs:srcfeed>http://pipes.yahoo.com/pipes/pipe.run?_id=e4a5e8b966cd9d1f80fe58ccd235fa5f&amp;_render=rss</fs:srcfeed><fs:itemid>feedsky/gming/~8811415/638149807/6423441</fs:itemid></item><item><title>我为什么写博客</title><link>http://item.feedsky.com/~feedsky/gming/~8811415/638149808/6423441/1/item.html</link><content:encoded>&lt;p&gt;很多时候没有为什么，写就是了。写与不写的区别就是：写就留下了，不写就忘却了。&lt;/p&gt;

&lt;p&gt;本文网址:&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/02/28/why-i-blogging.html&quot;&gt;http://www.qhm123.com/2012/02/28/why-i-blogging.html&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638149808/gming/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/gming/~8811415/638149808/6423441/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><category>why</category><pubDate>Tue, 28 Feb 2012 23:16:50 +0800</pubDate><guid isPermaLink="false">http://www.qhm123.com/?p=1159008</guid><fs:srclink>http://www.qhm123.com/2012/02/28/why-i-blogging.html</fs:srclink><fs:srcfeed>http://pipes.yahoo.com/pipes/pipe.run?_id=e4a5e8b966cd9d1f80fe58ccd235fa5f&amp;_render=rss</fs:srcfeed><fs:itemid>feedsky/gming/~8811415/638149808/6423441</fs:itemid></item><item><title>如何花费1分钟写一篇博文</title><link>http://item.feedsky.com/~feedsky/gming/~8811415/638149809/6423441/1/item.html</link><content:encoded>动手写，然后少写点，就像这样。注：这是一片正经的How文，你仔细反复读一句。

&lt;p&gt;本文网址:&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/02/26/how-take-1-minute-write-a-blog.html&quot;&gt;http://www.qhm123.com/2012/02/26/how-take-1-minute-write-a-blog.html&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638149809/gming/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/gming/~8811415/638149809/6423441/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><category>how</category><pubDate>Sun, 26 Feb 2012 22:54:50 +0800</pubDate><guid isPermaLink="false">http://www.qhm123.com/?p=1144030</guid><fs:srclink>http://www.qhm123.com/2012/02/26/how-take-1-minute-write-a-blog.html</fs:srclink><fs:srcfeed>http://pipes.yahoo.com/pipes/pipe.run?_id=e4a5e8b966cd9d1f80fe58ccd235fa5f&amp;_render=rss</fs:srcfeed><fs:itemid>feedsky/gming/~8811415/638149809/6423441</fs:itemid></item><item><title>Fedora16_x64编译Android4.0.3源码</title><link>http://item.feedsky.com/~feedsky/gming/~8811415/638149810/6423441/1/item.html</link><content:encoded>&lt;p&gt;这个勉强算是How，但是我无法准确的说出Fedora16编译Android4.0.3源码的整个过程，按步骤一步一步的该怎么做，因为我的编译过程是跌跌撞撞的，并且一些细节我可能现在写的时候也忽略甚至遗忘，我只是想分享编译Anrdoid源码过程中遇到的一些问题的解答，官方给出的编译流程对于Linux是针对Ubuntu发行版的，Fedora细节上有一些不同，以下内容大多并非原创，只是摘自网络，大多来自&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://groups.google.com/group/android-building&quot;&gt;android-building group&lt;/a&gt;，更多问题或许可以在那找到答案。&lt;/p&gt;
&lt;p&gt;准备工作，在编译源码之前，建议还是到&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://source.android.com/source/index.html&quot;&gt;andriod open source project&lt;/a&gt;上去看看，那里可以了解到一些基本的知识，尽管实践起来Fedora的一些细节可能不同，但是对于一些注意事项，基本的理解还是有好处的。另一方面，建议不要下载最新版本的android源码，而是下载稳定的branch，比如android-4.0.3_r1，这样可能会更顺畅一些。&lt;/p&gt;
&lt;p&gt;在编译之前我们需要做一些准备，下载必要的开发包，这个链接&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://rootzwiki.com/topic/8037-compile-android-on-fedora-1516-by-xoomdev/&quot;&gt;http://rootzwiki.com/topic/8037-compile-android-on-fedora-1516-by-xoomdev/&lt;/a&gt;，说明了针对Fedora发行版的Linux操作系统该怎么做一些准备。&lt;/p&gt;
&lt;p&gt;我简要叙述一下，&lt;/p&gt;
&lt;p&gt;下载&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.oracle.com/technetwork/java/javase/downloads/index.html&quot;&gt;sun-java-jdk6&lt;/a&gt;，注意一定不要使用openjdk，如果使用openjdk之后的编译会出现问题。&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;cd ~/Downloads
sudo sh jdk-6u27-linux-amd64.rpm
sudo ln -s /usr/java/default/bin/javah /usr/bin/javah&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;然后安装必要的开发包&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;sudo yum install -y zip curl gcc gcc-c++ flex bison gperf glibc-devel.{x86_64,i686} &amp;#92;&lt;/pre&gt;
&lt;pre&gt;zlib-devel.{x86_64,i686} ncurses-devel.i686 libX11-devel.i686 libstdc++.i686 libsx-devel &amp;#92;&lt;/pre&gt;
&lt;pre&gt;readline-devel.i686 libXrender.i686 libXrandr.i686

sudo yum install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev &amp;#92;&lt;/pre&gt;
&lt;pre&gt;gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev ia32-libs x11proto-core-dev &amp;#92;&lt;/pre&gt;
&lt;pre&gt;libx11-dev lib32readline5-dev lib32z-dev libX11-devel.i686&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;然后安装make3.81，(注意，Fedora16的make是3.82，编译Android会出现问题，所以需要降级安装3.81)&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;sudo yum downgrade make --releasever=13&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;但是按照这种降级方法我也没有安装成功，最后我选择了下载3.81版本的源码自己编译安装的，方法&lt;/p&gt;
&lt;p&gt;从&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.gnu.org/prep/ftp.html&quot;&gt;http://www.gnu.org/prep/ftp.html&lt;/a&gt;下载&quot;make-3.81.tar.gz到/tmp目录&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;su
cd /usr/local
tar -zxvf /tmp/make-3.81.tar.gz
cd ./make-3.81
./configure
./sh build.sh
./make install&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;然后配置PATH环境变量&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;PATH=$PATH:/usr/local/make-3.81 
export PATH&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;（当然为了永久生效，可以放到~/.bashrc）&lt;/p&gt;
&lt;p&gt;但是这样并没有好，Fedora16上一些包的版本和Android源码不太兼容，需要对Android源码作出一些更改，&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;https://groups.google.com/forum/#!msg/android-building/gIC_t7GXzQ4/1l7Se9Mb910J&quot;&gt;https://groups.google.com/forum/#!msg/android-building/gIC_t7GXzQ4/1l7Se9Mb910J&lt;/a&gt;这个链接给出了大部分方法，&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;1. in ./build/core/combo/HOST_linux-x86.mk
        replace : HOST_GLOBAL_CFLAGS += -D_FORTIFY_SOURCE=0
        with    : HOST_GLOBAL_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0

2. in ./development/tools/emulator/opengl/host/renderer/Android.mk
        add : LOCAL_LDLIBS += -lX11

3. in ./external/gtest/include/gtest/internal/gtest-param-util.h b/
include/gtest/internal/gtest-param-util.h
        after : [CODE]#include &amp;lt;vector&amp;gt;[/CODE]
        add : [CODE]#include &amp;lt;stddef.h&amp;gt;
                #include &amp;lt;cstddef&amp;gt;[/CODE]

4. in ./external/gtest/src/Android.mk
        replace (this is done in 2 places with the same line) :[CODE]LOCAL_CFLAGS += -O0[/CODE]
        with : [CODE]LOCAL_CFLAGS += -O0 -Wno-missing-field-initializers[/CODE]

5. in ./external/llvm/llvm-host-build.mk
        add : [CODE]LOCAL_LDLIBS := -lpthread -ldl[/CODE]

6. in ./external/mesa3d/src/glsl/linker.cpp
        after : [CODE]#include &amp;lt;climits&amp;gt;[/CODE]
        add : [CODE]#include &amp;lt;stddef.h&amp;gt;[/CODE]

7. in ./external/oprofile/libpp/format_output.h
        replace : [CODE]mutable counts_t &amp;amp; counts;[/CODE]
        with : [CODE]counts_t &amp;amp; counts;[/CODE]

8. in ./frameworks/compile/slang/slang_rs_export_foreach.cpp
        replace (line 249 - be careful, there are 2 line the same, the other
one is required) : [CODE]llvm::StringRef ParamName = PVD-&amp;gt;getName();[/CODE]
        with :[CODE] // llvm::StringRef ParamName = PVD-&amp;gt;getName();[/CODE]&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;另外我编译的过程还遇到了&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;host SharedLib: libGLES_CM_translator (out/host/linux-x86/obj/lib/libGLES_CM_translator.so)
/usr/bin/ld: skipping incompatible /usr/lib64/libGL.so when searching for -lGL
/usr/bin/ld: cannot find -lGLcollect2: ld 返回 1
make: *** [out/host/linux-x86/obj/lib/libGLES_CM_translator.so] Error 1
make: *** Waiting for unfinished jobs&amp;hellip;.&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;解决方法是&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;sudo yum install libgle.i686 libgle.x86_64 libgle-devel.i686 libgle-devel.x86_64 yum install mesa-libGL-devel.i686&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;又遇到&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre&gt;Java: CtsVerifier 
(out/target/common/obj/APPS/CtsVerifier_intermediates/classes) 
cts/apps/CtsVerifier/src/com/android/cts/verifier/PassFailButtons.java: 
191: onCreateDialog(int,android.os.Bundle) in android.app.Activity 
cannot implement onCreateDialog(int,android.os.Bundle) 
in com.android.cts.verifier.PassFailButtons.PassFailActivity; 
attempting to assign weaker access privileges; 
was public private static &amp;lt;T extends android.app.Activity &amp;amp; 
PassFailActivity&amp;gt; 
                           ^ 
1 error 
make: *** 
[out/target/common/obj/APPS/CtsVerifier_intermediates/classes-full- debug.jar]&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;有人说是使用openjdk，没有使用sun-jdk的原因，但是我使用的确实是sun-jdk，我采取了有人说的方案，从PassFailActivity接口中删除掉Dialog onCreateDialog(int id, Bundle args)&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;有了这些修补后，就可以正式开始编译了，&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;source build/envsetup.sh&lt;/p&gt;
&lt;p&gt;lunch full-eng（注：这个属于没有设备专有驱动的配置，实际的机器比如Nexus S，你要到官网下载相应的驱动包，具体见&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://source.android.com/source/building-devices.html&quot;&gt;这里&lt;/a&gt;）&lt;/p&gt;
&lt;p&gt;make -j4（注：-jN可以加快编译速度，但是数值不要过大，推荐值是电脑CPU线程的1或2倍）&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;相关阅读&lt;/h4&gt;
&lt;ul&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/11/28/Android-compatibility-package-fragment-loader-actionbar.html&quot;&gt;Android兼容包及Fragment, Loader, ActionBar简介&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/01/28/phonegap-source-code-analyzing-java-js-plugin-mechanism.html&quot;&gt;phoengap源码解析——插件机制，java和js代码互调用详解&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/01/16/android-tablet.html&quot;&gt;买了个Android平板——小破文章一篇&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/11/21/Android-backward-compatibility-problem.html&quot;&gt;Android前向兼容的几个问题&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/12/25/android-reader-txt.html&quot;&gt;Android阅读器相关资料（下-txt）&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/12/18/experience-android-4.0-nexus-s.html&quot;&gt;Nexus S体验Android4.0&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/12/24/android-reader-pdf.html&quot;&gt;Android阅读器开发相关资料（上-pdf）&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/04/27/proguard-summary-some-problem-answer.html&quot;&gt;ProGuard总结和混淆Android代码中遇到的问题的解决方法以及寻找getSomething游戏&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/03/5/how-speed-your-android-programming.html&quot;&gt;加速Android开发，玩转Eclipse&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/01/25/phonegap-webapp-decompile-codereader.html&quot;&gt;PhoneGap，Web Application，反编译，代码阅读器——4in1游戏卡，寻觅童年游戏机快感&lt;/a&gt;&lt;/li&gt;
    
&lt;/ul&gt;
&lt;p&gt;本文网址:&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/02/6/fedora-16-x64-compile-android-4.0.3-source-code.html&quot;&gt;http://www.qhm123.com/2012/02/6/fedora-16-x64-compile-android-4.0.3-source-code.html&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638149810/gming/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/gming/~8811415/638149810/6423441/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><category>how</category><pubDate>Mon, 06 Feb 2012 14:45:51 +0800</pubDate><guid isPermaLink="false">http://www.qhm123.com/?p=1118010</guid><fs:srclink>http://www.qhm123.com/2012/02/6/fedora-16-x64-compile-android-4.0.3-source-code.html</fs:srclink><fs:srcfeed>http://pipes.yahoo.com/pipes/pipe.run?_id=e4a5e8b966cd9d1f80fe58ccd235fa5f&amp;_render=rss</fs:srcfeed><fs:itemid>feedsky/gming/~8811415/638149810/6423441</fs:itemid></item><item><title>思考有的时候就是意淫</title><link>http://item.feedsky.com/~feedsky/gming/~8811415/638149811/6423441/1/item.html</link><content:encoded>&lt;p&gt;前几天写了《&lt;a rel=&quot;nofollow&quot;&gt;拾掇旧玩应&amp;mdash;&amp;mdash;那些年，我独自做过的小站&lt;/a&gt;》，我发现大部分我的项目都烂尾了。我发现我总是偶尔想到一个想法，然后开始行动，然后过程中又冒出新的想法，然后又突然觉得无趣，然后就萎靡，然后就罢手了。&lt;/p&gt;
&lt;p&gt;就在最近这两天我又烂尾了一个Android的项目，当我想好这个项目的一切想法，我想好了它的需求，并且为它想好了一个专门设计的网站，想好了一些文案，并且在做的过程中偶尔兴奋，我刚做出一个较为完整的alpha版本，写了一点单独的推广的网站，但是它还是烂尾了。就像我之前做过的一个Android项目，再之前做过的一个Android项目一样。&lt;/p&gt;
&lt;p&gt;记得曾经写过《&lt;a rel=&quot;nofollow&quot;&gt;目标&lt;/a&gt;》中说&amp;ldquo;我想到我经常穿梭于Web上的各种链接，我时常的目的是打开Google，用它搜索点什么，然而我最初的目的就随着我一次一次点击链接而渐渐远去。&amp;rdquo;。&lt;/p&gt;
&lt;p&gt;我时常觉得，做出一个完整的产品是很艰难的，视觉，文案，代码，想法，推广。有的时候我只能完成初始想法和部分代码的部分，然而视觉和文案则让我费心费力，我一直认为做出一个完整的东西是需要花费完成一个东西两倍甚至更多的精力的。&lt;/p&gt;
&lt;p&gt;有的时候我又觉得，我更喜欢做Web，因为Web无论做的怎么样我都可以把它挂到网上去，然后迅速改进重构，但是Android软件或者说软件，你怎么能忍心发布一个很惨的状况的东西出去。下载与安装是一个门槛，而Web点开就可以看到你的东西，尽管你的初期版本可能很是丑陋用户迅速离去，但是当你发布新版的时候Web用户再次看一眼的代价并不大，而软件不好用的话，很可能用户再也不会选择你，因为这玩应相对代价要更大一些，所以第一版必须足够好。&lt;/p&gt;
&lt;p&gt;很多时候，我在想大众需求是个什么东西，我一直觉得我是个小众的人，也喜欢小众的品味，当长尾概念烂大街的时候，你会觉得小众的聚集就是大众，然而我却发现我每一个大众的想法都被别人做掉了，所以有的时候无知者无畏，难得糊涂，据说人们只能看到一面的月球。&lt;/p&gt;
&lt;p&gt;我想，思考有的时候就是意淫。&lt;/p&gt;
&lt;p&gt;接下来，我该不会借由着什么想法去做一些东西了，就比如就在今天我又想到一些。记得《&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://book.douban.com/subject/5320866/&quot;&gt;重来&lt;/a&gt;》里写&amp;ldquo;你的头脑中有ebay的创意和你实际去创见ebay那一点关系也没有的&amp;rdquo;，或许说半毛钱关系都没有。我这样说后我又觉得这些东西不做有点可惜，但是再远了一点想，也许它们又会烂尾。&lt;/p&gt;
&lt;p&gt;或许是我想要的太多，想做的太多，比如我想做个记者，想做警察，想徒步旅行，想做产品，想做程序员，想做交互，想做生意，想做老师等等。单从我现在所从事的编程而言，我想做后端，想做前端，想做移动，单从后端来说，我想做Python，想做Java，想做Erlang，想做Hadoop，想做PHP，想做MongoDB，想做Redis，想做C，想做云计算，想做数据挖掘，从前端来说，我想做CoffeeScript，想做HTML5，想做JS，想做jQuery，想做NodeJS，想做CSS，从移动来说，我想做Android，想做iOS，想做PhoneGap，想做WP7。&lt;/p&gt;
&lt;p&gt;我想我已经疯了。&lt;/p&gt;
&lt;p&gt;我又想到刚才的话，思考有的时候就是意淫。&lt;/p&gt;
&lt;p&gt;所以接下来一段时间内，我可能会不再折腾这些东西了，我想参与一个开源的项目，贡献代码。&lt;/p&gt;
&lt;p&gt;再一个，我的博客的内容方向可能发生转变，我原来的分类是why-写为什么，how-写怎么做，what-写是什么，when-写随想，summary-写总结。新的方向可能是重在how，而且不是原来的大how，原来喜欢写比较大、通用的主题，现在想写一些小的、特别的主题，比重应该是how：when：why大概是8：1：1的样子。&lt;/p&gt;
&lt;p&gt;更重要的是，我要加强一个信念，&amp;ldquo;没有什么是我做不来的！&amp;rdquo;&lt;/p&gt;
&lt;p&gt;据说很多事情应该立即行动，所以我就要开始了！&lt;/p&gt;
&lt;p&gt;然而每次情绪高昂的时候，我都喜欢泼冷水，我记得我写的《&lt;a rel=&quot;nofollow&quot;&gt;犯贱&lt;/a&gt;》一文，也许我会再次犯贱。&lt;/p&gt;
&lt;p&gt;如果泼冷水真的能让我清醒，那么在凛冽的寒风中猛烈的泼我吧~&lt;/p&gt;

&lt;h4&gt;相关阅读&lt;/h4&gt;
&lt;ul&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/06/19/object.html&quot;&gt;目标&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/01/22/recent-make-website-thinks-questions.html&quot;&gt;最近做一个网站过程中产生的一些想法和疑问&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/02/15/always-think-wish-to-exceed.html&quot;&gt;我做了一些非常艰难的决定&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2010/11/22/talk-about-blog-post-frequency.html&quot;&gt;谈博客更新频率&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2010/10/15/why-me-start-blogging.html&quot;&gt;我为什么写博客&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/10/27/longer-than-half-year.html&quot;&gt;比半年更久一点&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/02/21/hard-to-write.html&quot;&gt;七天憋出六个字&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2010/06/15/heart-strong.html&quot;&gt;内心的强大&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2010/05/22/about-time-think.html&quot;&gt;关于时间的思考&lt;/a&gt;&lt;/li&gt;
    
&lt;/ul&gt;
&lt;p&gt;本文网址:&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/02/5/think-is-psycholagny.html&quot;&gt;http://www.qhm123.com/2012/02/5/think-is-psycholagny.html&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638149811/gming/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/gming/~8811415/638149811/6423441/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><category>when</category><pubDate>Sun, 05 Feb 2012 17:54:08 +0800</pubDate><guid isPermaLink="false">http://www.qhm123.com/?p=1112047</guid><fs:srclink>http://www.qhm123.com/2012/02/5/think-is-psycholagny.html</fs:srclink><fs:srcfeed>http://pipes.yahoo.com/pipes/pipe.run?_id=e4a5e8b966cd9d1f80fe58ccd235fa5f&amp;_render=rss</fs:srcfeed><fs:itemid>feedsky/gming/~8811415/638149811/6423441</fs:itemid></item><item><title>拾掇旧玩应——那些年，我独自做过的小站</title><link>http://item.feedsky.com/~feedsky/gming/~8811415/638149812/6423441/1/item.html</link><content:encoded>&lt;p&gt;这两天拾掇了一下以前写的小网站，有的年久失修已经不能用了，有的简单到弱爆了，都是gae上的东西，用python的，web&amp;nbsp;framework有的是webapp，有的是django，后期主要用django，这里主要回顾一下这几个东西。另外，拾掇的过程中充满尴尬与对自己陈旧代码的鄙视，心想怎么代码写的如此垃圾，过程中还发生了种种烦心的事情，这里一并写下。&lt;/p&gt;
&lt;p&gt;在gae上做的第一个玩应叫做&amp;ldquo;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://keepsogo.qhm123.com/&quot;&gt;Keep so Go！&lt;/a&gt;&amp;rdquo;，忘了写了多久，可能1天左右，是个很简单的玩应，也很让人摸不着头脑。玩应的介绍就是，&amp;ldquo;如果网页不被关闭，那么你的在线时常会被不断累加，然后进行排行&amp;rdquo;，这个东西的灵感现在想想多半来自小的时候玩游戏挂机的经历，亦或是QQ挂机，这个说不准了。只写了1天然后就终止了，本也就是练手的小东西，自然没有传播，用户有2个，一个显然是我，另一个是后来在you8g注册域名被别人悄然发现的。需要注册的东西，还是很难获取初期用户的，除非有知名人事的推动与宣传，像当年&amp;ldquo;知乎&amp;rdquo;的邀请码相当难搞，大家趋之若鹜。视觉上，我忘了抄袭了哪的视觉，总之不是我的原创，虽然很简陋，就那个黑条。代码上，真心写的很烂，web框架用的是webapp，总共没多少python代码，200多行，感觉用python代码，这小玩应，写的代码行数越多，越显得低端。看svn的记录，代码是2010年10月写的，剩下应该没有什么了。&lt;/p&gt;
&lt;p&gt;第二个应该就是&amp;ldquo;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://aicolor.sinaapp.com/&quot;&gt;爱颜色&lt;/a&gt;&amp;rdquo;（现在是在sae上的版本），时间与第一个应该差不多，文案是&amp;ldquo;选择你最爱的颜色，选择你当前心情的颜色，分享最爱的颜色，对颜色进行解说，通过颜色寻找朋友。&amp;rdquo;，想法来源是有个挺出名的国外的关于颜色的网站，现在想不起来了，这个是整合了新浪微博的，用了新浪微博的API，信息流会自动同步到微博上。视觉上最早应该是自己的原创，已经不记得长什么样子了，但是提交新浪微博审核的时候，被说界面太丑陋，然后我采用了我博客上的那套css，后来才通过。这个也1年多了，很早以前，由于新浪微博api调整过，然后这个&amp;ldquo;爱颜色&amp;rdquo;就不能用了，我也没想改，但是网站处于不能访问的状态，于是我把与新浪微博相关的东西全部注释掉了，然后一直苟延残喘至今，近两天我修复了新浪微博交互的问题，并且把&amp;ldquo;爱颜色&amp;rdquo;移植到了sae上。在gae上的现在虽然可以运行，但是还是有很多问题，然后我在gae上可运行的状态上，进行的sae版本移植，然后在sae版本上修复了算是挺大量的东西，然后gae版本作为一个branch躺在那里。&amp;ldquo;爱颜色&amp;rdquo;是用的django web&amp;nbsp;framework，而众所周知django在gae上的兼容性并不是很好，我当初使用了google维护的django&amp;nbsp;helper，但也早就停止维护，gae上的django和django最大不同是model层，而我model层当初未完全封装，向外暴漏了好多gae自己的东西，当然当初也想不到会有一天用纯粹一点的django来写，sae上的django算是纯粹一些，不像gae很多不能用。但是移植过程中遇到超多细节问题，而且python不想编译强类型语言，很多问题不到运行时还是挺难发现的，想很多类型问题，我很是无语。一个糟糕的问题是新浪微博的认证过程必须在有外网地址的情况下才能测试，所以我只能部署到真实环境才能测试，于是不停的部署啊，不停的发现问题。看来还是写点单元测试靠谱点啊，于是动手写。磕磕碰碰折腾了小两天时间，每次一部署或者svn提交，我就刷眼微博，关注下方寒战事，终于移植完成，修复了大量错误，并且赶紧了大量代码，有的时候觉得重写都比这块，但是修正代码过程发现我的代码的拙略，改后稍好一点，维护代码总是比捋起袖子从头干起费劲纠结一些。我想起了《&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://book.douban.com/subject/1467587/&quot;&gt;UNIX编程艺术&lt;/a&gt;》中写的&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;正如Brian Kernighan曾经说过的：&amp;ldquo;计算机编程的本质就是控制复杂度&amp;rdquo;，排错占用了大部分额的开发时间，弄出一个拿得出手的可用系统，通常与其说出自才华横溢的设计成果，还不如说是跌跌撞撞的结果。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;另外，又想起在修正gae版本的时候，遇到域名过期，突然不能访问了，想这是咋了，想了会才意识到域名过期啦。。。&lt;/p&gt;
&lt;p&gt;然后就是&amp;ldquo;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://micolog-tribe.qhm123.com/&quot;&gt;Micolog部落&lt;/a&gt;&amp;rdquo;了，这个是我用时最多，也是我稍微满意，稍微有点用户，也通过这个网站想了很多，学到很多的一个玩应。曾经写过《&lt;a rel=&quot;nofollow&quot;&gt;最近做一个网站过程中产生的一些想法和疑问&lt;/a&gt;》，那里简介写到&amp;ldquo;2010年11月06日动手，由于我不是美工，加之之前站点UI的失败，为此我特意看了几本Web设计的书。最终借用了Wordpress的Motion主题。开发平台使用Google App Engine，语言Python，框架Django，RCS使用Git，GitHub托管。主要利用平常的闲暇时间开发。&amp;rdquo;时间来看，这个也1年多了，而且我最近打算基于这个做点扩展。这个网站我修改了好多次，对于注册环节我那篇博文里说过，注册我改了能有5次左右。开发时间总共加起来可能并没有多少，但是为这个我想了很多事情。用户量依然很少，但是也算是个突破，有80左右个人，并且当初还有点小意思，有几个活跃用户，我算是最大的活跃用户了吧，我在想当一个东西的创始人不在活跃的时候，那么多半这个东西就完了。后来怎么没有在搞，&amp;ldquo;&lt;strong&gt;墙&lt;/strong&gt;&amp;rdquo;，堵住了micolog的用户，我这个基于micolog的聚合站也就黄了。&lt;/p&gt;
&lt;p&gt;然后就是沉寂了，很久没写出什么，过程中有一些小东西，大多是在别的东西基础上做的二次开发，而且都是未完成品，做完一个东西的时间是代码第一次完工时间的一倍。&lt;/p&gt;
&lt;p&gt;&amp;ldquo;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://noodle.qhm123.com/&quot;&gt;面条&lt;/a&gt;&amp;rdquo;，我觉得这个名字很有爱，名字叫什么无所谓了，这其实是显示豆瓣书影音收藏轨迹的一个东西，并没有100%完成，但是可以用，在豆瓣ID那输入自己的豆瓣ID，然后点选书影音组合，然后点&amp;ldquo;点&amp;rdquo;，可以显示自己的书影音收藏。&lt;/p&gt;
&lt;p&gt;&amp;ldquo;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://the10000.qhm123.com/about&quot;&gt;the10000&lt;/a&gt;&amp;rdquo;，名字来源是《&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://book.douban.com/subject/3688489/&quot;&gt;异类&lt;/a&gt;》这本书，想法来源同是这本书和&amp;ldquo;Dan计划：重新定义人生的10000个小时&amp;rdquo;，标语用的是v2ex下面的那个&amp;ldquo;Do have a faith in what you're doing&amp;rdquo;，这个东西的玩法是：用户在上面写下一个自己要实现的目标，然后自己记录自己为这个目标做了什么，做了多少小时，距离达到10000小时还差多久，你已经为你的梦想努力了多少小时。我第一个用户的目标是做这个网站10000小时，然而我做的一个扯淡的行动是，在我做了5个小时左右后，就再也没动过他。这个网站另一个很扯的地方是也采用了邀请码注册机制，而且未登录用户神马也看不到，所以我想到了这个是在知乎刚出那会做的，依然是前面所说的。忘了说了，这个是基于v2ex进行的二次开发。&lt;/p&gt;
&lt;p&gt;&quot;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://wiki.qhm123.com/&quot;&gt;Wiki&lt;/a&gt;&quot;，基于nancywiki做了一点二次开发，我之前博文写过一直想写个wiki，弄个我wiki，但是现在不做了。&lt;/p&gt;
&lt;p&gt;再有就是写过一些micolog的插件。写过一个Android的烂玩应。&lt;/p&gt;
&lt;p&gt;再有就是&quot;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://shopbook.sinaapp.com/&quot;&gt;网上书店&lt;/a&gt;&quot;，这个最初不是GAE上的，是之前学校写的网上书店，花了一会时间移植到SAE上，网上书店用的是Django写的，移植到SAE上很方便，但是网上书店用到了pylucene，SAE上没法搞，所以搜索和相关用pylucene做的推荐没法用，我主要写的后端，前端是一个同学写的，前端页面我基本没写，都交给同学了。这应该是我第一个纯Django的项目，之前在GAE上有一些不同和限制，写这个时候觉得Django开发是快，很爽，我们很快在我宿舍写完了。数据是豆瓣API搞下来的，用了memcache。总的来说挺糙的，不过和同学一起写还是有点意思的。&lt;/p&gt;
&lt;p&gt;本来想配图，但是配图太麻烦，太讨厌配图了，我采集到了花瓣上，地址这里，&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://huaban.com/boards/170195/&quot;&gt;http://huaban.com/boards/170195/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;写于两天前，这两天纠结在libvirt和xen上了。&lt;/p&gt;

&lt;p&gt;本文网址:&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/01/31/play-with-old-things.html&quot;&gt;http://www.qhm123.com/2012/01/31/play-with-old-things.html&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638149812/gming/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/gming/~8811415/638149812/6423441/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><category>summary</category><pubDate>Tue, 31 Jan 2012 12:01:01 +0800</pubDate><guid isPermaLink="false">http://www.qhm123.com/?p=1051547</guid><fs:srclink>http://www.qhm123.com/2012/01/31/play-with-old-things.html</fs:srclink><fs:srcfeed>http://pipes.yahoo.com/pipes/pipe.run?_id=e4a5e8b966cd9d1f80fe58ccd235fa5f&amp;_render=rss</fs:srcfeed><fs:itemid>feedsky/gming/~8811415/638149812/6423441</fs:itemid></item><item><title>phoengap源码解析——插件机制，java和js代码互调用详解</title><link>http://item.feedsky.com/~feedsky/gming/~8811415/638149813/6423441/1/item.html</link><content:encoded>&lt;p&gt;看了眼phonegap的android实现的源码，其实还是挺简单的。出乎意料的是，我原以为js这套api的封装是使用addJavascriptInterface这个接口完成的，但是它是用了一种奇异的方法来实现的。我们一步一步慢慢说。&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://docs.phonegap.com/en/1.3.0/index.html&quot;&gt;http://docs.phonegap.com/en/1.3.0/index.html&lt;/a&gt;这个链接是phonegap的js api，可以看到api是分模块的，有Accelerometer，Camera，Capture，Compass，Connection，Contacts，Device，File，Geolocation，Media，Notification，Storage，Events，而每一个模块恰好是phonegap的一个plugin。而每一个plugin恰好大体对应一个java文件和一个js文件。在实际用phonegap开发的时候，我们引用的phonegap.js是经过编译整合后的文件，源码的framework/build.xml中有如下一段可以说明：&lt;/p&gt;
&lt;pre&gt;&amp;lt;!-- Create uncompressed JS file --&amp;gt;
&amp;lt;concat destfile=&quot;assets/www/phonegap-${version}.js&quot;&amp;gt;
 &amp;lt;fileset dir=&quot;assets/js&quot; includes=&quot;phonegap.js.base&quot; /&amp;gt;
 &amp;lt;fileset dir=&quot;assets/js&quot; includes=&quot;*.js&quot; /&amp;gt;
&amp;lt;/concat&amp;gt;&lt;/pre&gt;
&lt;p&gt;插件机制对应的java代码，主要在com.phonegap.api这个包里，所有的api对应模块的java实现都扩展了Plugin类，并且在src/com/phonegap/api/PluginManager.java中有public String exec(final String service, final String action, final String callbackId, final String jsonArgs, final boolean async)；方法，此方法里面调用plugin.execute方法，相应的plugin插件实现了execute方法，进行具体操作。对应js代码，插件机制以及公有基础的东西主要phonegap.js.base文件，每个单独的模块文件实现具体的操作。js代码里也有相应定义，&lt;br /&gt;
/**&lt;br /&gt;
* Execute a PhoneGap command.  It is up to the native side whether this action is synch or async.&lt;br /&gt;
* The native side can return:&lt;br /&gt;
*      Synchronous: PluginResult object as a JSON string&lt;br /&gt;
*      Asynchrounous: Empty string &quot;&quot;&lt;br /&gt;
* If async, the native side will PhoneGap.callbackSuccess or PhoneGap.callbackError,&lt;br /&gt;
* depending upon the result of the action.&lt;br /&gt;
*/&lt;br /&gt;
public String exec(final String service, final String action, final String callbackId, final String jsonArgs, final boolean async)；&lt;br /&gt;
可以看到api操作还提供了同步异步两种模式。这里的一些东西到这里可能还不是很明朗，稍后了解了java和js互掉的原理后就清楚了。&lt;/p&gt;
&lt;p&gt;但是这里，特别的对于Events有些特别，java与js交互上是不同于其它模块的方法且相对简单的，所以先说这个。在src/com/phonegap/DroidGap.java文件中可以看到，所有js的回调事件都是通过loadUrl然后执行一段javascript脚本来实现的，如&lt;/p&gt;
&lt;p&gt;生命周期回调：this.appView.loadUrl(&quot;javascript:try{PhoneGap.fireDocumentEvent('resume');}catch(e){};&quot;);&lt;br /&gt;
按钮响应：this.appView.loadUrl(&quot;javascript:PhoneGap.fireDocumentEvent('backbutton');&quot;);&lt;/p&gt;
&lt;p&gt;assets/js/phonegap.js.base相应代码为：&lt;/p&gt;
&lt;pre&gt;PhoneGap.fireDocumentEvent = function(type, data) {
    var e = document.createEvent('Events');
    e.initEvent(type);
    if (data) {
        for (var i in data) {
            e[i] = data[i];
        }
    }
    document.dispatchEvent(e);
};&lt;/pre&gt;
&lt;p&gt;好了，&lt;strong&gt;开始最重要的部分了&lt;/strong&gt;。phonegap使用的java与js互相调用的原理。phonegap实现的模型刚也说了，有同步和异步两种。js实现的api，所以是js先会调用java代码，然后再返回给js。对于同步的而言，就是js调用java，然后java返回一个结果作为返回值。对于异步的而言，可能js掉了很多java代码，但是立即返回，然后java代码执行结束后再回调js代码，这里就涉及到js调java，然后java再调用js。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;对于js调用java：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;js调用java的入口是通过在js中调用prompt方法，这很奇怪吧，这个方法本来是让浏览器弹出个输入框的。我当初找了好久也没发现phonegap到底怎么搞得的让js调用java的代码，后来看到一会觉得该是这个方法，但是这是一个浏览器的客户端自己的东西，而且怪异的是浏览器并没有弹出输入框，后来终于发现。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt;在DroidGap.java中有个hack，重载了WebviewClient的onJsPrompt方法&lt;/span&gt;&lt;/strong&gt;，然后执行了自己的逻辑。 也就是js调用prompt的时候，java端浏览器代码接受到这个，然后在响应的处理函数中根据传过来的参数，实现了一些特别的逻辑。可以从这个方法的注释上看出一二。&lt;/p&gt;
&lt;pre&gt;/**
* Tell the client to display a prompt dialog to the user.
* If the client returns true, WebView will assume that the client will handle the prompt dialog
* and call the appropriate JsPromptResult method.
* Since we are hacking prompts for our own purposes, we should not be using them for this
* purpose, perhaps we should hack console.log to do this instead!
@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
...
}&lt;/pre&gt;
&lt;p&gt;方法里面的代码就如刚所说会根据传过来的参数，做相应处理，它会先判断是不是本地网页的请求，如果是，然后分几种情况。&lt;/p&gt;
&lt;pre&gt;// Calling PluginManager.exec() to call a native service using
prompt(this.stringify(args), &quot;gap:&quot;+this.stringify([service, action, callbackId, true]));
gap:
// Polling for JavaScript messages
gap_poll:
// Calling into CallbackServer
gap_callbackServer:
// PhoneGap JS has initialized, so show webview(This solves white flash seen when rendering HTML)
gap_init:&lt;/pre&gt;
&lt;p&gt;分别是，如果是prompt传过来的是gap:这样开头的字符串，那么就执行相应的java调用，&lt;strong&gt;Calling PluginManager.exec() to call a native service using prompt(this.stringify(args), &quot;gap:&quot;+this.stringify([service, action, callbackId, true]))&lt;/strong&gt;。gap_poll:和gap_callbackServer:是稍后要说到的java回调js使用的，gap_init:初始化处理相关的代码。如果其它情况，则构造一个Android的AlertDialog显示。&lt;/p&gt;
&lt;p&gt;然后phonegap就是这样，通过设置setWebChromeClient和setWebViewClient，重载了一些实现，控制了浏览器行为，实现了自己的很多逻辑。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;对于java回调js：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color:#ff0000;&quot;&gt; phonegap实现了一个回调服务器，服务器就是负责回调js代码的，服务器有一个js代码的队列&lt;/span&gt;&lt;/strong&gt;，在src/com/phonegap/CallbackServer.java文件中&lt;/p&gt;
&lt;pre&gt;/**
* The list of JavaScript statements to be sent to JavaScript.
*/
private LinkedList javascript;&lt;/pre&gt;
&lt;p&gt;服务器保存要回调的js的代码，供js客户端取回，这里java端是服务器端，js端是客户端，服务器端不可能请求客户端做啥，是b／s模型，所以phonegap实现了两种服务模型，一种是轮询，一种是XHR异步回调，也就是Ajax的模型。src/com/phonegap/CallbackServer.java是回调服务器的代码所在处。从类的注释中可以看到。&lt;/p&gt;
&lt;pre&gt;This class provides a way for Java to run JavaScript in the web page that has loaded PhoneGap.
The CallbackServer class implements an XHR server and a polling server with a list of JavaScript statements
that are to be executed on the web page.&lt;/pre&gt;
&lt;p&gt;CallbackServer提供的这两种模型，一种是XHR，一种是轮询，轮询很简单了，callbackserver服务器端，有一个保存回调js的列表，前面所说，然后每隔一段时间客户端的js会询问一次服务器，是否有需要回调的js，如果有则调用，然后每隔一段时再查询一次服务器。而基于XHR的，其实这个就是ajax用的机制了，js发起一个异步请求，然后服务器会在返回数据之前保持住这个连接，当返回数据就位后，服务器给请求客户端返回数据，然后关闭连接。然后客户端接受并且处理。&lt;/p&gt;
&lt;p&gt;刚说了服务器端的代码实现，现在来看一下客户端js的相关代码。&lt;/p&gt;
&lt;pre&gt;/**
* Internal function that uses XHR to call into PhoneGap Java code and retrieve any JavaScript
* code that needs to be run. This is used for callbacks from Java to JavaScript.
*/
PhoneGap.JSCallback = function() {
...
xmlhttp.open(&quot;GET&quot;, &quot;http://127.0.0.1:&quot;+PhoneGap.JSCallbackPort+&quot;/&quot;+PhoneGap.JSCallbackToken , true);
xmlhttp.send();
}&lt;/pre&gt;
&lt;p&gt;这个是XHR模型的代码，客户端js使用xhr请求服务器来获取js代码，进行回调。&lt;/p&gt;
&lt;pre&gt;/**
 * Internal function that uses polling to call into PhoneGap Java code and retrieve
 * any JavaScript code that needs to be run.  This is used for callbacks from Java to JavaScript.
 */
PhoneGap.JSCallbackPolling = function() {
...
    var msg = prompt(&quot;&quot;, &quot;gap_poll:&quot;);
    if (msg) {
        setTimeout(function() {
            try {
                var t = eval(&quot;&quot;+msg);
            }
            catch (e) {
                console.log(&quot;JSCallbackPolling: Message from Server: &quot; + msg);
                console.log(&quot;JSCallbackPolling Error: &quot;+e);
            }
        }, 1);
        setTimeout(PhoneGap.JSCallbackPolling, 1);
    }
    else {
        setTimeout(PhoneGap.JSCallbackPolling, PhoneGap.JSCallbackPollingPeriod);
    }
}&lt;/pre&gt;
&lt;p&gt;这个是轮询方式的，可以看到客户端每隔PhoneGap.JSCallbackPollingPeriod段时间，就请求一次服务器（通过prompt(&quot;&quot;, &quot;gap_poll:&quot;);）。&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;至此js和java互调用，phonegap的plugin插件机制和api的实现原理就清楚了。另外phonegap源码的注释是很不错的。&lt;/p&gt;


&lt;h4&gt;相关阅读&lt;/h4&gt;
&lt;ul&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/01/25/phonegap-webapp-decompile-codereader.html&quot;&gt;PhoneGap，Web Application，反编译，代码阅读器——4in1游戏卡，寻觅童年游戏机快感&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/11/28/Android-compatibility-package-fragment-loader-actionbar.html&quot;&gt;Android兼容包及Fragment, Loader, ActionBar简介&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/01/16/android-tablet.html&quot;&gt;买了个Android平板——小破文章一篇&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/11/21/Android-backward-compatibility-problem.html&quot;&gt;Android前向兼容的几个问题&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/12/25/android-reader-txt.html&quot;&gt;Android阅读器相关资料（下-txt）&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/12/18/experience-android-4.0-nexus-s.html&quot;&gt;Nexus S体验Android4.0&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2011/12/24/android-reader-pdf.html&quot;&gt;Android阅读器开发相关资料（上-pdf）&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/04/27/proguard-summary-some-problem-answer.html&quot;&gt;ProGuard总结和混淆Android代码中遇到的问题的解决方法以及寻找getSomething游戏&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/02/6/fedora-16-x64-compile-android-4.0.3-source-code.html&quot;&gt;Fedora16_x64编译Android4.0.3源码&lt;/a&gt;&lt;/li&gt;
    
    &lt;li&gt;&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/03/5/how-speed-your-android-programming.html&quot;&gt;加速Android开发，玩转Eclipse&lt;/a&gt;&lt;/li&gt;
    
&lt;/ul&gt;
&lt;p&gt;本文网址:&lt;a rel=&quot;nofollow&quot; target=&quot;_blank&quot; href=&quot;http://www.qhm123.com/2012/01/28/phonegap-source-code-analyzing-java-js-plugin-mechanism.html&quot;&gt;http://www.qhm123.com/2012/01/28/phonegap-source-code-analyzing-java-js-plugin-mechanism.html&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/638149813/gming/feedsky/s.gif?r=http://item.feedsky.com/~feedsky/gming/~8811415/638149813/6423441/1/item.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;</content:encoded><category>why</category><pubDate>Sat, 28 Jan 2012 11:45:35 +0800</pubDate><guid isPermaLink="false">http://www.qhm123.com/?p=1071302</guid><fs:srclink>http://www.qhm123.com/2012/01/28/phonegap-source-code-analyzing-java-js-plugin-mechanism.html</fs:srclink><fs:srcfeed>http://pipes.yahoo.com/pipes/pipe.run?_id=e4a5e8b966cd9d1f80fe58ccd235fa5f&amp;_render=rss</fs:srcfeed><fs:itemid>feedsky/gming/~8811415/638149813/6423441</fs:itemid></item></channel></rss>
