﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-xiaomage234-随笔分类-ios &amp;android</title><link>http://www.blogjava.net/xiaomage234/category/54416.html</link><description>生命本就是一次凄美的漂流，记忆中放不下的，永远是孩提时代的那一份浪漫与纯真！</description><language>zh-cn</language><lastBuildDate>Thu, 18 Aug 2016 12:01:25 GMT</lastBuildDate><pubDate>Thu, 18 Aug 2016 12:01:25 GMT</pubDate><ttl>60</ttl><item><title>数据交换格式FlatBuffers介绍</title><link>http://www.blogjava.net/xiaomage234/archive/2016/08/18/431623.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 18 Aug 2016 08:26:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/08/18/431623.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/431623.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/08/18/431623.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/431623.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/431623.html</trackback:ping><description><![CDATA[from:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0831/3395.html<br /><br /><p style="box-sizing: border-box; border: 0px; margin: 10px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;"><strong style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px;">编辑推荐：</strong><a href="http://gold.xitu.io/" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">稀土掘金</a>，这是一个针对技术开发者的一个应用，你可以在掘金上获取最新最优质的技术干货，不仅仅是Android知识、前端、后端以至于产品和设计都有涉猎，想成为全栈工程师的朋友不要错过！</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">原文：<a href="http://www.csdn.net/article/2015-08-31/2825579" _src="http://www.csdn.net/article/2015-08-31/2825579" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">http://www.csdn.net/article/2015-08-31/2825579</a>&nbsp;</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">JSON&#8212;&#8212;大家可能都知道它是几乎所有现代服务器都使用的轻量级数据交换格式。它体量轻，可读性强，通常比老式的、不友好的XML开发起来更加便捷友好。JSON是不依赖于开发语言的数据格式，但是在解析数据并将其转换到如Java对象时，会消耗我们的时间和存储资源。</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">几天前，Facebook宣布，其Android应用程序大幅提升了数据处理性能。这是由于几乎在全部应用程序中放弃了JSON数据格式，用FlatBuffers取而代之了。阅读<a href="https://code.facebook.com/posts/872547912839369/improving-facebook-s-performance-on-android-with-flatbuffers/" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">这篇文章</a>可以获得关于FlatBuffers的基础知识，学会如何从JSON转换到FlatBuffers。</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">虽然这东西是非常有前景的，但是乍一看其实现过程不是一下子就能明白的。而且Facebook也没有说得很详细。这就是为什么我要写这篇文章，在其中展示我们是如何使用Flatbuffers开展工作的。</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 25px; text-align: center; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background: radial-gradient(closest-side at center center, #ffffff 70%, #fbfcfd 85%, #f4f7fa 100%) #ffffff;"></p><h2>FlatBuffers</h2><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">总之，<a href="https://github.com/google/flatbuffers" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">FlatBuffers</a>是Google专门为游戏开发而创建的跨平台序列化库，就像Facebook所展示的那样，它在Android平台上遵循快速响应UI的<a href="https://www.youtube.com/watch?v=CaMTIgxCSqU" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">16ms规则</a>。</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">但是，在把所有数据迁移到FlatBuffers之前，你要确定确实需要这样做。因为，这样做有时对性能的影响是潜移默化的，而且<a href="https://publicobject.com/2014/06/18/im-not-switching-to-flatbuffers/" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">数据安全性</a>要比计算速度上几十毫秒的差异更重要。</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">什么使得Flatbuffers如此奏效？</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;"><br style="box-sizing: border-box;" /></p><ul list-paddingleft-2"="" style="box-sizing: border-box; border: 0px; margin: 0px 0px 10px 25px; padding: 0px; list-style: none; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; line-height: 32px; background-color: #ffffff;"><li style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; list-style: disc;"><p style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; line-height: 1.7;">由于是以二进制形式缓存，访问序列化数据时也无需数据解析过程。即使对于层次化数据也不需要解析。多亏不需要初始化解析器（初始化意味着要建立复杂的字段映射）和解析数据，这些都是需要花费时间的。</p></li><li style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; list-style: disc;"><p style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; line-height: 1.7;">Flatbuffers数据不需要分配比自身使用缓冲区还要多的内存。我们不必像在JSON中那样为解析数据的整个层次分配额外对象。</p></li></ul><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">要获得正宗的数据，就再读一读<a href="https://code.facebook.com/posts/872547912839369/improving-facebook-s-performance-on-android-with-flatbuffers/" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">Facebook</a>上关于FlatBuffers迁移问题的文章，还有<a href="http://google.github.io/flatbuffers/" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">Google</a>自己的文档。</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;"><br style="box-sizing: border-box;" /></p><h2>实现</h2><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">本文将介绍在Android应用程序中使用Flatbuffers的最简单方法：</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;"><br style="box-sizing: border-box;" /></p><ul list-paddingleft-2"="" style="box-sizing: border-box; border: 0px; margin: 0px 0px 10px 25px; padding: 0px; list-style: none; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; line-height: 32px; background-color: #ffffff;"><li style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; list-style: disc;"><p style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; line-height: 1.7;">JSON数据在应用程序之外的某个地方被转换成FlatBuffer格式的文件（例如，将二进制数据以文件的形式提交，还可以从API直接返回FlatBuffer二进制文件）。</p></li><li style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; list-style: disc;"><p style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; line-height: 1.7;">在flatc (FlatBuffer编译器)的帮助下，手工生成数据模型（Java类）。</p></li><li style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; list-style: disc;"><p style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; line-height: 1.7;">JSON文件存在一定的局限性（不能使用null字段，日期格式也被解析为字符串）。</p></li></ul><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;"><br style="box-sizing: border-box;" /></p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">将来，我们或许会提出更复杂的解决方案。</p><h2>FlatBuffers编译器</h2><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">首先，我们需要flatc，即flatbuffers编译器。该编译器可以从Google所属的源代码构建，源代码位于<a href="https://github.com/google/flatbuffers" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">Flatbuffers资源库</a>中。我们下载并克隆它。整个构建过程在<a href="https://google.github.io/flatbuffers/md__building.html" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">FlatBuffers构建文档</a>中都做了描述。如果你是Mac用户的话，需要这样来构建：</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;"><br style="box-sizing: border-box;" /></p><ol list-paddingleft-2"="" style="box-sizing: border-box; border: 0px; margin: 0px 0px 1em 30px; padding: 0px; color: #333333; font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 24px; background-color: #ffffff;"><li style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; list-style: decimal;"><p style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; line-height: 1.7;">在\{extract directory}\build\XcodeFlatBuffers.xcodeproj路径下，打开已下载的源代码。</p></li><li style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; list-style: decimal;"><p style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; line-height: 1.7;">点击Play按钮或&#8984; + R，运行flatc scheme（默认情况下应该是被选中的）。</p></li><li style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; list-style: decimal;"><p style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; line-height: 1.7;">flatc可执行文件就会在项目的根目录下出现。</p></li></ol><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;"><br style="box-sizing: border-box;" /></p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">现在，我们可以使用<a href="https://google.github.io/flatbuffers/md__compiler.html" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">schema编译器</a>了，该编译器能够把给定的schema（在Java、C#、Python、GO和C++语言中的schema）生成为模型类，还可以把JSON转换成Flatbuffer的二进制文件。</p><h2>Schema文件</h2><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">接着，我们必须准备schema文件，该文件定义了要进行序列化和反序列化的数据结构。这个schema将用于flatc创建Java模型，把JSON转换成FlatBuffers的二进制文件。</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">这里是JSON文件的一部分。</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">完整版本在<a href="https://github.com/frogermcs/FlatBuffs/blob/master/flatbuffers/repos_json.json" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">这里</a>。这是略微修改后的版本，可以从Github API调用：<a href="https://api.github.com/users/google/repos" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">https://api.github.com/users/google/repos</a>&nbsp;。</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">Flatbuffer schema是编写得很好的<a href="https://google.github.io/flatbuffers/md__schemas.html" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">文档</a>，所以就不深入探讨这个问题了。另外，本文中的schema不会很复杂。我们所要做的仅仅是创建3张表：ReposList, Repo和User，并定义root_type。这是schema的重要组成部分。</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">完整的schema文件在<a href="https://github.com/frogermcs/FlatBuffs/blob/master/flatbuffers/repos_schema.fbs" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">这里</a>。</p><h2>FlatBuffers数据文件</h2><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">真棒，我们现在要做的是把repos_json.json转换成FlatBuffers二进制文件，生成能够以Java风格表示数据的Java模型（此处操作所需的全部文件都在我们的<a href="https://github.com/frogermcs/FlatBuffs/tree/master/flatbuffers" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">代码库</a>中）：</p><blockquote style="box-sizing: border-box; border-width: 0px 0px 0px 4px; border-left-color: #999999; margin: 0px 0px 22px; padding: 10px 15px; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-image: initial; background-color: #f5f5f5;">$ ./flatc -j -b repos_schema.fbs repos_json.json<br style="box-sizing: border-box;" /></blockquote><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">如果一切顺利，会产生下列文件：</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;"><br style="box-sizing: border-box;" /></p><ul list-paddingleft-2"="" style="box-sizing: border-box; border: 0px; margin: 0px 0px 10px 25px; padding: 0px; list-style: none; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; line-height: 32px; background-color: #ffffff;"><li style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; list-style: disc;"><p style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; line-height: 1.7;">repos_json.bin（要将重命名它为 repos_flat.bin）</p></li><li style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; list-style: disc;"><p style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; line-height: 1.7;">Repos/Repo.java</p></li><li style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; list-style: disc;"><p style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; line-height: 1.7;">Repos/ReposList.java</p></li><li style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; list-style: disc;"><p style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; line-height: 1.7;">Repos/User.java</p></li></ul><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;"><br style="box-sizing: border-box;" /></p><h2>Android应用程序</h2><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">现在来创建示例程序，在实践中来看看Flatbuffers格式是如何起作用的。这是截图：</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;"><img src="http://www.jcodecraeer.com/uploads/20150831/1441001920184864.png" title="1441001920184864.png" alt="blob.png" style="box-sizing: border-box; border: 0px; vertical-align: middle; margin: 0px; padding: 0px; max-width: 100%; height: auto;" /></p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">在UI部分，ProgressBar仅用于显示不恰当的数据处理对用户界面顺畅度的影响。</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">应用文件看起来是这个样子：app/build.gradle</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">当然，在本例中不是必须要用Rx或ButterKnife这样的视图注入利器，但是为什么不让应用更细致一些呢？？</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">我们把repos_flat.bin 和 repos_json.json文件放到res/raw/目录下。<a href="https://github.com/frogermcs/FlatBuffs/blob/master/app/src/main/java/frogermcs/io/flatbuffs/utils/RawDataReader.java" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">RawDataReader</a>是工具类，它帮助我们读取Android应用中的原始文件。</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">最后，把Repo，ReposList和User这三张表对应的模型类代码放到项目源代码中。</p><h2>FlatBuffers库</h2><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">使用Java语言编程过程中，FlatBuffers提供了可以直接处理这种数据格式的库，也这是<a href="https://github.com/frogermcs/FlatBuffs/blob/master/app/libs/flatbuffers-java-1.2.0-SNAPSHOT.jar" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">flatbuffers-java-1.2.0-SNAPSHOT.jar文件</a>。如果你想手工生成该文件，需要下载FlatBuffers源代码，再到目录java/下，用Maven生成该库：</p><blockquote style="box-sizing: border-box; border-width: 0px 0px 0px 4px; border-left-color: #999999; margin: 0px 0px 22px; padding: 10px 15px; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; background-image: initial; background-color: #f5f5f5;">$ mvn install</blockquote><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">现在将.jar文件放到Android项目的app/libs/目录下。</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">好了，当务之急是实现MainActivity类，这是完整源代码。</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">我们最为关注的两个方法是：</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;"><br style="box-sizing: border-box;" /></p><ul list-paddingleft-2"="" style="box-sizing: border-box; border: 0px; margin: 0px 0px 10px 25px; padding: 0px; list-style: none; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; line-height: 32px; background-color: #ffffff;"><li style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; list-style: disc;"><p style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; line-height: 1.7;">parseReposListJson(String reposStr) - 这个方法初始化Gson解析器，并把JSON字符串转换成Java对象。</p></li><li style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; list-style: disc;"><p style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; line-height: 1.7;">loadFlatBuffer(byte[] bytes) &nbsp;- 这个方法将字节（repos_flat.bin文件）转换成Java对象。</p></li></ul><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;"><br style="box-sizing: border-box;" /></p><h2>使用FlatBuffers的结果</h2><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">现在让我们把JSON和FlatBuffers在加载时间和资源消耗方面的差异形象化。测试是在带有Android M（beta版）的Nexus 5上进行的。</p><h3>加载时间</h3><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">测量的过程是将其他文件转换为Java源文件，对所有（90个）元素进行迭代。</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;"><br style="box-sizing: border-box;" /></p><ul list-paddingleft-2"="" style="box-sizing: border-box; border: 0px; margin: 0px 0px 10px 25px; padding: 0px; list-style: none; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; line-height: 32px; background-color: #ffffff;"><li style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; list-style: disc;"><p style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; line-height: 1.7;">使用JSON：JSON文件（大小：478kB）平均加载时间200ms（时间区间：180ms～250ms）；</p></li><li style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; list-style: disc;"><p style="box-sizing: border-box; border: 0px; margin: 0px; padding: 0px; line-height: 1.7;">使用FlatBuffers：FlatBuffers二进制文件（大小：352kB）平均加载时间5ms（时间区间：3ms～10ms）。</p></li></ul><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;"><br style="box-sizing: border-box;" /></p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">记得<a href="https://www.youtube.com/watch?v=CaMTIgxCSqU" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">16ms规则</a>吗？我们在UI线程中调用这些方法的原因就是要看看在这种情况下界面表现如何：</p><h3>JSON数据加载效果：</h3><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;"><img src="http://www.jcodecraeer.com/uploads/20150831/1441001991283149.gif" title="1441001991283149.gif" alt="json.gif" style="box-sizing: border-box; border: 0px; vertical-align: middle; margin: 0px; padding: 0px; max-width: 100%; height: auto;" /></p><h3>FlatBuffers数据加载效果：</h3><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;"><img src="http://www.jcodecraeer.com/uploads/20150831/1441002021369858.gif" title="1441002021369858.gif" alt="flatbuffers.gif" style="box-sizing: border-box; border: 0px; vertical-align: middle; margin: 0px; padding: 0px; max-width: 100%; height: auto;" /></p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">看出区别了吗？JSON数据的加载过程中， ProgressBar停顿了一会，界面不是那么顺畅（加载时间超过了16ms）。</p><h3>内存分配、CPU等资源</h3><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">还有什么想要测量的吗？也许应该测量一下<a href="http://android-developers.blogspot.com/2015/07/get-your-hands-on-android-studio-13.html" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">Android Studio 1.3</a>，还有那些新特性。例如，内存分配跟踪器（Allocation Tracker），内存状态查看器（Memory Viewer）和方法跟踪器（Method Tracer）。</p><h3>源代码</h3><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">这里所讲解项目的完整源代码都在Github<a href="https://github.com/frogermcs/FlatBuffs" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">代码库</a>中。你不需要接触整个FlatBuffers项目，所需的内容全都在flatbuffers/目录下。</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">（ 翻译/张挥戈 &nbsp;友情审校/白云鹏）</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">文章来源：<a href="http://frogermcs.github.io/flatbuffers-in-android-introdution/" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">froger_mcs dev blog</a></p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">作者简介：</p><p style="box-sizing: border-box; border: 0px; margin: 0px 0px 15px; padding: 0px; line-height: 1.7; color: #333333; font-family: &quot;lucida grande&quot;, &quot;lucida sans unicode&quot;, lucida, helvetica, &quot;Hiragino Sans GB&quot;, &quot;Microsoft YaHei&quot;, &quot;WenQuanYi Micro Hei&quot;, sans-serif; font-size: 16px; background-color: #ffffff;">Miroslaw Stanek，Azimo Money Transfer公司移动项目负责人，Android和iOS平台程序员，视频游戏玩家，冰雪运动爱好者。个人博客：<a href="http://frogermcs.github.io/" target="_blank" style="box-sizing: border-box; color: #0f9932; text-decoration: none; border: 0px; margin: 0px; padding: 0px; transition-duration: 0.2s; transition-property: opacity; background-color: transparent;">http://frogermcs.github.io</a>。</p><div></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/431623.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-08-18 16:26 <a href="http://www.blogjava.net/xiaomage234/archive/2016/08/18/431623.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android 开发者应该使用 FlatBuffers 替代 JSON ?</title><link>http://www.blogjava.net/xiaomage234/archive/2016/08/18/431622.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 18 Aug 2016 08:17:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/08/18/431622.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/431622.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/08/18/431622.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/431622.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/431622.html</trackback:ping><description><![CDATA[from:http://www.oschina.net/news/75092/android-flatbuffers-json<br /><br /><p style="margin: 0px 0px 15pt; padding: 0px; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;">你可能会问，既然我们已经有很标准的JSON以及转换库比如GSON和Jackson，为什么还要使用新的工具呢？</p><p style="margin: 0px 0px 15pt; padding: 0px; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;">不妨先试一下FlatBuffers，然后你就会发现它比JSON快得多。</p><p style="margin: 0px 0px 15pt; padding: 0px; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">FlatBuffers是什么？</strong></p><p style="margin: 0px 0px 15pt; padding: 0px; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;"><a textvalue="FlatBuffers" target="_blank" href="https://google.github.io/flatbuffers/index.html#flatbuffers_overview" style="margin: 0px; padding: 0px; color: #3e62a6; outline: 0px;">FlatBuffers</a>是一个高效的跨平台序列化类库，可以在C++、C#、C、Go、Java、JavaScript、PHP和Python中使用。是<strong style="margin: 0px; padding: 0px;">Google</strong>开发的，是为了应用在游戏开发，以及其他注重性能的应用上。</p><p style="margin: 0px 0px 15pt; padding: 0px; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">为什么要使用FlatBuffers？</strong></p><ul list-paddingleft-2"="" style="margin: 0.5em 0px 0.5em 1.5em; padding: 0px; list-style-position: inside; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;"><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px; display: inline;"><strong style="margin: 0px; padding: 0px;">不需要解析/拆包就可以访问序列化数据</strong>&nbsp;&#8212; FlatBuffers与其他库不同之处就在于它使用二进制缓冲文件来表示层次数据，这样它们就可以被直接访问而不需解析与拆包，同时还支持数据结构进化（前进、后退兼容性）。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px; display: inline;"><strong style="margin: 0px; padding: 0px;">内存高效速度快</strong>&nbsp;&#8212; 访问数据时只需要访问内存中的缓冲区。它不需要多余的内存分配（至少在C++是这样，其他语言中可能会有变动）。FlatBuffers还适合配合 mmap或数据流使用，只需要缓冲区的一部分存储在内存中。访问时速度接近原结构访问，只有一点延迟（一种虚函数表vtable），是为了允许格式升级以 及可选字段。FlatBuffers适合那些花费了大量时间和空间（内存分配）来访问和构建序列化数据的项目，比如游戏以及其他对表现敏感的应用。可以参 考这里的<a href="https://google.github.io/flatbuffers/flatbuffers_benchmarks.html" style="margin: 0px; padding: 0px; color: #3e62a6; outline: 0px;">基准</a>。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px; display: inline;"><strong style="margin: 0px; padding: 0px;">灵活</strong>&nbsp;&#8212; 由于有可选字段，你不但有很强的升级和回退兼容性（对于历史悠久的游戏尤其重要，不用为了每个版本升级所有数据），在选择要存储哪些数据以及设计数据结构时也很自由。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px; display: inline;"><strong style="margin: 0px; padding: 0px;">轻量的code footprint</strong>&nbsp;&#8212; FlatBuffers只需要很少量的生成代码，以及一个表示最小依赖的很小的头文件，很容易集成。细节上可以看上面的基准页。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px; display: inline;"><strong style="margin: 0px; padding: 0px;">强类型</strong>&nbsp;&#8212; 编译时报错，而不需要自己写重复的容易出错的运行时检查。它可以自动生成有用的代码。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px; display: inline;"><strong style="margin: 0px; padding: 0px;">使用方便</strong>&nbsp;&#8212; 生成的C++代码允许精简访问与构建代码。还有可选的用于实现图表解析、类似JSON的运行时字符串展示等功能的方法。（后者比JSON解析库更快，内存效率更高）</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px; display: inline;"><strong style="margin: 0px; padding: 0px;">代码跨平台且没有依赖</strong>&nbsp;&#8212; C++代码可以运行在任何近代的gcc/clang和VS2010上。同时还有用于测试和范例的构建文件（Android中.mk文件，其他平台是cmake文件）。</p></li></ul><p style="margin: 0px 0px 15pt; padding: 0px; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">都有谁使用FlatBuffers?</strong></p><ul list-paddingleft-2"="" style="margin: 0.5em 0px 0.5em 1.5em; padding: 0px; list-style-position: inside; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;"><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px; display: inline;"><a href="https://play.google.com/store/apps/details?id=com.touchtalent.bobbleapp" style="margin: 0px; padding: 0px; color: #3e62a6; outline: 0px;"><strong style="margin: 0px; padding: 0px;">BobbleApp</strong></a>，印度第一贴图App。我们在BobbleApp中使用FlatBuffers后App的性能明显增强。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px; display: inline;"><a href="http://www.cocos2d-x.org/" style="margin: 0px; padding: 0px; color: #3e62a6; outline: 0px;">Cocos2d-x</a>，第一开源移动游戏引擎，使用FlatBuffers来序列化所有的游戏数据。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px; display: inline;">Facebook使用FlatBuffers在Android App中进行客户端服务端的沟通。他们写了一篇<a href="https://code.facebook.com/posts/872547912839369/improving-facebook-s-performance-on-android-with-flatbuffers/" style="margin: 0px; padding: 0px; color: #3e62a6; outline: 0px;">文章</a>来描述FlatBuffers是如何加速加载内容的。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px; display: inline;">Google的<a href="https://developers.google.com/games/#Tools" style="margin: 0px; padding: 0px; color: #3e62a6; outline: 0px;">Fun Propulsion Labs</a>在他们所有的库和游戏中大量使用FlatBuffers。</p></li></ul><p style="margin: 0px 0px 15pt; padding: 0px; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">App性能有多大提高？</strong></p><ul list-paddingleft-2"="" style="margin: 0.5em 0px 0.5em 1.5em; padding: 0px; list-style-position: inside; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;"><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px; display: inline;"><strong style="margin: 0px; padding: 0px;">解析速度</strong>&nbsp;解析一个20KB的JSON流（这差不多是BobbleApp的返回大小）需要35ms，超过了UI刷新间隔也就是16.6ms。如果解析JSON的话，我们就在滑动时就会因为要从磁盘加载缓存而导致掉帧（视觉上的卡顿）。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px; display: inline;"><strong style="margin: 0px; padding: 0px;">解析器初始化</strong>&nbsp;一个JSON解析器需要先构建字段映射再进行解析，这会花100ms到200ms，很明显的拖缓App启动时间。</p></li><li style="margin: 0px; padding: 0px;"><p style="margin: 0px; padding: 0px; display: inline;"><strong style="margin: 0px; padding: 0px;">垃圾回收</strong>&nbsp;在解析JSON时创建了很多小对象，在我们的试验中，解析20kb的JSON流时，要分配大约100kb的瞬时存储，对Java内存回收造成很大压力。</p></li></ul><p style="margin: 0px 0px 15pt; padding: 0px; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">FlatBuffers vs JSON</strong></p><p style="margin: 0px 0px 15pt; padding: 0px; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;">我尝试使用FlatBuffers和JSON解析4mb的JSON文件。</p><p style="margin: 0px 0px 15pt; padding: 0px; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;">FlatBuffers花了1-5ms，JSON花了大约2000ms。在使用FlatBuffers期间Android App中没有GC，而在使用JSON时发生了很多次GC。在使用JSON时UI完全卡住，所以真实使用时只能在后台线程进行解析。</p><p style="margin: 0px 0px 15pt; padding: 0px; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;"><img src="http://static.oschina.net/uploads/space/2016/0711/074023_lnYJ_1774694.jpg" data-bd-imgshare-binded="1" style="margin: 0px; padding: 0px; border: 0px; max-width: 640px;"  alt="" /></p><p style="margin: 0px 0px 15pt; padding: 0px; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;"><strong style="margin: 0px; padding: 0px;">如何使用FlatBuffer呢？</strong></p><p style="margin: 0px 0px 15pt; padding: 0px; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;">我在我的GitHub中写了一个<a textvalue="示例" target="_blank" href="https://github.com/amitshekhariitbhu/FlatBuffer" style="margin: 0px; padding: 0px; color: #3e62a6; outline: 0px;">示例</a>，里面手把手教你如何使用FlatBuffer。</p><p style="margin: 0px 0px 15pt; padding: 0px; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;">原文链接:<a textvalue="https://medium.freecodecamp.com/why-consider-flatbuffer-over-json-2e4aa8d4ed07" target="_blank" href="https://medium.freecodecamp.com/why-consider-flatbuffer-over-json-2e4aa8d4ed07" style="margin: 0px; padding: 0px; color: #3e62a6; outline: 0px;">https://medium.freecodecamp.com/why-consider-flatbuffer-over-json-2e4aa8d4ed07</a></p><p style="margin: 0px 0px 15pt; padding: 0px; font-family: &quot;Microsoft YaHei&quot;, Verdana, sans-serif, SimSun; line-height: 22.4px; background-color: #ffffff;">稿源：<a target="_blank" href="http://www.infoq.com/cn/news/2016/07/FlatBuffers-JSON-Android" style="margin: 0px; padding: 0px; color: #3e62a6; outline: 0px;">infoQ</a>&nbsp;&nbsp;<span style="margin: 0px; padding: 0px;">作者<a textvalue="Amit Shekhar" target="_blank" href="http://www.infoq.com/cn/author/Amit-Shekhar" style="margin: 0px; padding: 0px; color: #3e62a6; outline: 0px;">Amit Shekhar</a>&nbsp; 译者<a textvalue="程大治" target="_blank" href="http://www.infoq.com/cn/author/%E7%A8%8B%E5%A4%A7%E6%B2%BB" style="margin: 0px; padding: 0px; color: #3e62a6; outline: 0px;"><strong style="margin: 0px; padding: 0px;">程大治</strong></a></span></p><img src ="http://www.blogjava.net/xiaomage234/aggbug/431622.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-08-18 16:17 <a href="http://www.blogjava.net/xiaomage234/archive/2016/08/18/431622.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>安卓App热补丁动态修复技术介绍</title><link>http://www.blogjava.net/xiaomage234/archive/2016/07/07/431120.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 07 Jul 2016 08:11:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/07/07/431120.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/431120.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/07/07/431120.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/431120.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/431120.html</trackback:ping><description><![CDATA[<div>作者：MagiLu<br />链接：https://zhuanlan.zhihu.com/p/20308548<br />来源：知乎<br />著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。<br /><br /><p>作者：johnczchen</p><p>出品：QQ空间终端开发团队</p><p>原文发布于QQ空间终端开发团队的官方公众号，任何形式的转载之前必须与本人联系。</p><br /><h3><strong>1.背景</strong></h3><p>        当一个App发布之后，突然发现了一个严重bug需要进行紧急修复，这时候公司各方就会忙得焦头烂额：重新打包App、测试、向各个应用市场和渠道换包、提示用户升级、用户下载、覆盖安装。有时候仅仅是为了修改了一行代码，也要付出巨大的成本进行换包和重新发布。</p><p>        这时候就提出一个问题：<strong>有没有办法以补丁的方式动态修复紧急Bug，不再需要重新发布App，不再需要用户重新下载，覆盖安装？</strong></p><p>        虽然Android系统并没有提供这个技术，但是很幸运的告诉大家，答案是：<strong>可以，我们QQ空间提出了热补丁动态修复技术来解决以上这些问题。</strong></p><p><strong>2.实际案例</strong></p><p>        空间Android独立版5.2发布后，收到用户反馈，结合版无法跳转到独立版的访客界面，每天都较大的反馈。在以前只能紧急换包，重新发布。成本非常高，也影响用户的口碑。最终决定使用热补丁动态修复技术，<strong>向用户下发Patch，在用户无感知的情况下，修复了外网问题，取得非常好的效果。</strong></p><p><strong>3.解决方案</strong></p><p>        该方案基于的是android dex分包方案的，关于dex分包方案，网上有几篇解释了，所以这里就不再赘述，具体可以看这里<a href="https://link.zhihu.com/?target=https%3A//m.oschina.net/blog/308583" wrap=""  external"="" target="_blank" rel="nofollow noreferrer">Android dex分包方案<em></em></a>。</p><p>        简单的概括一下，就是把多个dex文件塞入到app的classloader之中，但是android dex拆包方案中的类是没有重复的，如果classes.dex和classes1.dex中有重复的类，当用到这个重复的类的时候，系统会选择哪个类进行加载呢？</p><p>        让我们来看看类加载的代码：</p><img src="https://pic4.zhimg.com/3de788b45e865407b71a45e339639b0f_b.jpg" data-rawwidth="640" data-rawheight="697"  zh-lightbox-thumb"="" width="640" data-original="https://pic4.zhimg.com/3de788b45e865407b71a45e339639b0f_r.jpg"  alt="" /><p>        一个ClassLoader可以包含多个dex文件，每个dex文件是一个Element，多个dex文件排列成一个有序的数组dexElements，当找类的时候，会按顺序遍历dex文件，然后从当前遍历的dex文件中找类，如果找类则返回，如果找不到从下一个dex文件继续查找。</p><p>        理论上，如果在不同的dex中有相同的类存在，那么会优先选择排在前面的dex文件的类，如下图：</p><p><img src="https://pic1.zhimg.com/c3d8d50bdf89d50bf5254387ae761ccc_b.jpg" data-rawwidth="1190" data-rawheight="523"  zh-lightbox-thumb"="" width="1190" data-original="https://pic1.zhimg.com/c3d8d50bdf89d50bf5254387ae761ccc_r.jpg"  alt="" />在此基础上，我们构想了热补丁的方案，把有问题的类打包到一个dex（patch.dex）中去，然后把这个dex插入到Elements的最前面，如下图：</p><img src="https://pic3.zhimg.com/5af6c469a4866233d82ee7521c672ea6_b.jpg" data-rawwidth="1188" data-rawheight="512"  zh-lightbox-thumb"="" width="1188" data-original="https://pic3.zhimg.com/5af6c469a4866233d82ee7521c672ea6_r.jpg"  alt="" /><p>好，该方案基于第二个拆分dex的方案，方案实现如果懂拆分dex的原理的话，大家应该很快就会实现该方案，如果没有拆分dex的项目的话，可以参考一下谷歌的multidex方案实现。然后在插入数组的时候，把补丁包插入到最前面去。</p><p>好，看似问题很简单，轻松的搞定了，让我们来试验一下，修改某个类，然后打包成dex，插入到classloader，当加载类的时候出现了（本例中是QzoneActivityManager要被替换）：<br /></p><img src="https://pic3.zhimg.com/f08b4e50095ffbb79758a5766ef1837e_b.jpg" data-rawwidth="1266" data-rawheight="559"  zh-lightbox-thumb"="" width="1266" data-original="https://pic3.zhimg.com/f08b4e50095ffbb79758a5766ef1837e_r.jpg"  alt="" /><p><strong>为什么会出现以上问题呢？</strong></p><p><strong>        从log的意思上来讲，ModuleManager引用了QzoneActivityManager，但是发现这这两个类所在的dex不在一起，其中：</strong></p><p><strong>1. ModuleManager在classes.dex中</strong></p><p><strong>2. QzoneActivityManager在patch.dex中</strong></p><p><strong>结果发生了错误。</strong></p><p><strong>这里有个问题,拆分dex的很多类都不是在同一个dex内的,怎么没有问题?</strong></p><p><strong>        让我们搜索一下抛出错误的代码所在，嘿咻嘿咻，找到了一下代码：</strong></p><p><img src="https://pic4.zhimg.com/e4a58a54390ee4dd9c4f9c245f83d637_b.jpg" data-rawwidth="1184" data-rawheight="2868"  zh-lightbox-thumb"="" width="1184" data-original="https://pic4.zhimg.com/e4a58a54390ee4dd9c4f9c245f83d637_r.jpg"  alt="" />        从代码上来看，如果两个相关联的类在不同的dex中就会报错，但是拆分dex没有报错这是为什么，原来这个校验的前提是：</p><img src="https://pic4.zhimg.com/e58fc77e0768642ed90685ed857ccfb3_b.jpg" data-rawwidth="640" data-rawheight="112"  zh-lightbox-thumb"="" width="640" data-original="https://pic4.zhimg.com/e58fc77e0768642ed90685ed857ccfb3_r.jpg"  alt="" /><p>如果引用者（也就是ModuleManager）这个类被打上了<strong>CLASS_ISPREVERIF</strong><strong>IED</strong>标志，那么就会进行dex的校验。那么这个标志是什么时候被打上去的？</p><p><strong>让我们在继续搜索一下代码，嘿咻嘿咻~~，在DexPrepare.cpp找到了一下代码：</strong></p><img src="https://pic3.zhimg.com/bad6028a2293906d767fccedc6ddcc4a_b.jpg" data-rawwidth="757" data-rawheight="565"  zh-lightbox-thumb"="" width="757" data-original="https://pic3.zhimg.com/bad6028a2293906d767fccedc6ddcc4a_r.jpg"  alt="" /><p>这段代码是dex转化成odex(dexopt)的代码中的一段，我们知道当一个apk在安装的时候，apk中的classes.dex会被虚拟机(dexopt)优化成odex文件，然后才会拿去执行。</p><p>        虚拟机在启动的时候，会有许多的启动参数，其中一项就是verify选项，当verify选项被打开的时候，上面doVerify变量为true，那么就会执行dvmVerifyClass进行类的校验，如果dvmVerifyClass校验类成功，那么这个类会被打上CLASS_ISPREVERIFIED的标志，那么具体的校验过程是什么样子的呢？</p><p>        此代码在DexVerify.cpp中，如下：</p><img src="https://pic3.zhimg.com/979fdb303e4cb62524a9b2372d86c49a_b.jpg" data-rawwidth="892" data-rawheight="454"  zh-lightbox-thumb"="" width="892" data-original="https://pic3.zhimg.com/979fdb303e4cb62524a9b2372d86c49a_r.jpg"  alt="" /><p>1. 验证clazz-&gt;directMethods方法，directMethods包含了以下方法：</p><p>    1. static方法</p><p>    2. private方法</p><p>    3. 构造函数</p><p>2. clazz-&gt;virtualMethods</p><p>    1. 虚函数=override方法?</p><p>概括一下就是如果以上方法中直接引用到的类（第一层级关系，不会进行递归搜索）和clazz都在同一个dex中的话，那么这个类就会被打上<strong>CLASS_ISPREVERIFIED</strong>：</p><img src="https://pic3.zhimg.com/e6b47807888e11b1308ae38ffc0e223e_b.jpg" data-rawwidth="640" data-rawheight="650"  zh-lightbox-thumb"="" width="640" data-original="https://pic3.zhimg.com/e6b47807888e11b1308ae38ffc0e223e_r.jpg"  alt="" /><p><strong>所以为了实现补丁方案，所以必须从这些方法中入手，防止类被打上CLASS_ISPREVERIFIED标志。</strong></p><p><strong>最终空间的方案是往所有类的构造函数里面插入了一段代码，代码如下：</strong></p><p>if (ClassVerifier.PREVENT_VERIFY) {</p><p>        System.out.println(AntilazyLoad.class);</p><p>}</p><p><strong>其中AntilazyLoad类会被打包成单独的hack.dex，这样当安装apk的时候，classes.dex内的类都会引用一个在不相同dex中的AntilazyLoad类，这样就防止了类被打上CLASS_ISPREVERIFIED的标志了，只要没被打上这个标志的类都可以进行打补丁操作。</strong></p><p><strong>然后在应用启动的时候加载进来.AntilazyLoad类所在的dex包必须被先加载进来,不然AntilazyLoad类会被标记为不存在，即使后续加载了hack.dex包，那么他也是不存在的，这样屏幕就会出现茫茫多的类AntilazyLoad找不到的log。</strong></p><p><strong>所以Application作为应用的入口不能插入这段代码。（因为载入hack.dex的代码是在Application中onCreate中执行的，如果在Application的构造函数里面插入了这段代码，那么就是在hack.dex加载之前就使用该类，该类一次找不到，会被永远的打上找不到的标志)</strong></p><p>其中:</p><img src="https://pic1.zhimg.com/43e5d5382169eb6cd19a54534e62a7b8_b.jpg" data-rawwidth="640" data-rawheight="122"  zh-lightbox-thumb"="" width="640" data-original="https://pic1.zhimg.com/43e5d5382169eb6cd19a54534e62a7b8_r.jpg"  alt="" /><p>之所以选择构造函数是因为他不增加方法数，一个类即使没有显式的构造函数，也会有一个隐式的默认构造函数。</p><p>        空间使用的是在字节码插入代码,而不是源代码插入，使用的是javaassist库来进行字节码插入的。</p><h2>隐患:</h2><p>        虚拟机在安装期间为类打上<strong>CLASS_ISPREVERIFIED</strong>标志是为了提高性能的，我们强制防止类被打上标志是否会影响性能？这里我们会做一下更加详细的性能测试．但是在大项目中拆分dex的问题已经比较严重，很多类都没有被打上这个标志。</p><p>如何打包补丁包：</p><p>１. 空间在正式版本发布的时候，会生成一份缓存文件，里面记录了所有class文件的md5，还有一份mapping混淆文件。</p><p>２. 在后续的版本中使用-applymapping选项，应用正式版本的mapping文件，然后计算编译完成后的class文件的md5和正式版本进行比较，把不相同的class文件打包成补丁包。</p><p><strong>备注:该方案现在也应用到我们的编译过程当中,编译不需要重新打包dex,只需要把修改过的类的class文件打包成patch dex,然后放到sdcard下,那么就会让改变的代码生效。</strong></p><br /><br /><p><strong>关于Qzone :</strong></p><p>Qzone 是中国最大的社交网络，是腾讯集团的核心平台之一，目前Qzone的月活跃账户数达到6.68亿，Qzone智能终端月活跃账户数达到5.68亿。从2005~2015，Qzone见证了国内互联网蓬勃发展的十年，这十年风云变幻，但我们的业务却不断向前发展，也希望更多的朋友能够加入我们，共同迎接互联网和Qzone的下一个十年。</p></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/431120.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-07-07 16:11 <a href="http://www.blogjava.net/xiaomage234/archive/2016/07/07/431120.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>微信 Android 热补丁实践演进之路</title><link>http://www.blogjava.net/xiaomage234/archive/2016/07/07/431119.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 07 Jul 2016 08:10:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2016/07/07/431119.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/431119.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2016/07/07/431119.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/431119.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/431119.html</trackback:ping><description><![CDATA[<div style="color: #999999; padding-bottom: 5px; border-bottom-width: 1px; border-bottom-style: dashed; border-bottom-color: #d3d3d3; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif;"><div><span style="float: left;">原文</span>&nbsp;&nbsp;<a cut70"="" href="http://mp.weixin.qq.com/s?src=3&amp;timestamp=1466781270&amp;ver=1&amp;signature=jpcd9lSdexjm3LQrE8ijClC1k*AJHpy0FBLzrEXsTKkQYBe1bc7P0rVLXc8wyVsAYJiwcEz-FiotWtZAPZc7wAcFR73oyX0mR-bkZhOt-xFbqIhaT0p8K-Oj0x*ik1DvC6xxjbjRQI6E-nqDT9l25x*zfJ3jBmp-cQ2XkZDQAZg=&amp;utm_source=tuicool&amp;utm_medium=referral" style="color: #333333; text-decoration: none; transition: 0.25s; outline: none 0px; overflow: hidden; white-space: nowrap; word-break: keep-all; text-overflow: ellipsis; max-width: 69%; display: inline-block;">http://mp.weixin.qq.com/s?src=3&amp;timestamp=1466781270&amp;ver=1&amp;signature=jpcd9lSdexjm3LQrE8ijClC1k*AJHpy0FBLzrEXsTKkQYBe1bc7P0rVLXc8wyVsAYJiwcEz-FiotWtZAPZc7wAcFR73oyX0mR-bkZhOt-xFbqIhaT0p8K-Oj0x*ik1DvC6xxjbjRQI6E-nqDT9l25x*zfJ3jBmp-cQ2XkZDQAZg=</a></div><div><span style="margin-right: 5px;">主题</span>&nbsp;<a href="http://www.tuicool.com/topics/11080010" target="_blank" style="color: #333333; text-decoration: none; transition: 0.25s; outline: none 0px;"><span style="display: inline-block; padding: 2px 4px; font-size: 0.9em; line-height: 16px; vertical-align: baseline; white-space: nowrap; color: #787878; margin-right: 5px; background-color: #f2f2f2;">安卓开发</span></a></div></div><div id="nei" style="padding: 20px 5px 25px; margin-bottom: 0px; overflow-x: hidden; word-wrap: break-word; word-break: break-word; min-height: 340px; font-size: 16px; line-height: 1.7em; color: #333333; font-family: 'Helvetica Neue', Helvetica, Tahoma, Arial, STXihei, 'Microsoft YaHei', 微软雅黑, sans-serif;"><div style="line-height: 1.7em;"><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">继插件化后，热补丁技术在2015年开始爆发，目前已经是非常热门的Android开发技术。其中比较著名的有淘宝的Dexposed、支付宝的AndFix以及Qzone的超级热补丁方案。微信对热补丁技术的研究并不算早，大约开始于2015年6月。经过研究与尝试现有的各个方案，我们发现它们都有着自身的一些局限性。微信最终采用不同于它们的技术方案，走出了自己的实践演进之路。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">另外一方面，技术应当只是热补丁方案中的一环。随着对热补丁的多次尝试与应用，微信建立起自身的流程规范，同时也不断的尝试拓展它的应用场景。通过本文，我希望大家不仅能够全面的了解各项热补丁技术的优缺点，同时也能对它的应用场景有着更加全面的认识。在此基础上，大家或许能更容易的决定是否在自己的项目中使用热补丁技术，以及应当如何使用它。</p><h2>为什么需要热补丁</h2><div style="line-height: 1.7em;"><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">热补丁：让应用能够在无需重新安装的情况实现更新，帮助应用快速建立动态修复能力。</p></div><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">从上面的定义来看，热补丁节省Android大量应用市场发布的时间。同时用户也无需重新安装，只要上线就能无感知的更新。看起来很美好，这是否可以意味我们可以尽量使用补丁来代替发布呢？事实上，热补丁技术当前依然存在它的局限性，主要表现在以下几点：</p><ol style="padding: 0px; margin: 0px 0px 0.75em 25px; line-height: 1.7em;"><li style="line-height: 1.7em;"><p style="margin: 0px 0px 0.75em; text-indent: 1em; line-height: 1.7em;">补丁只能针对单一客户端版本，随着版本差异变大补丁体积也会增大；</p></li><li style="line-height: 1.7em;"><p style="margin: 0px 0px 0.75em; text-indent: 1em; line-height: 1.7em;">补丁不能支持所有的修改，例如AndroidManifest；</p></li><li style="line-height: 1.7em;"><p style="margin: 0px 0px 0.75em; text-indent: 1em; line-height: 1.7em;">补丁无论对代码还是资源的更新成功率都无法达到100%。</p></li></ol><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">既然补丁技术无法完全代替升级，那它适合使用在哪些场景呢？</p><h3>一. 轻量而快速的升级</h3><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">热补丁技术也可以理解为一个动态修改代码与资源的通道，它适合于修改量较少的情况。以微信的多次发布为例，补丁大小均在300K以内，它相对于传统的发布有着很大的优势。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;"><img src="http://img0.tuicool.com/zeMVbm2.jpg!web" style="max-width: 96%; height: auto; vertical-align: middle; border: 0px none; margin: 0px auto 10px; text-align: center; display: block;"  alt="" />以Android用户的升级习惯，即使是相对活跃的微信也需要10天以上的时间去覆盖50%的用户。使用补丁技术，我们能做到1天覆盖70%以上。这也是基于补丁体积较小，可以直接使用移动网络下载更新。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">正因如此，补丁技术非常适合使用在灰度阶段。在过去，我们需要在正式发布前保证所有严重的问题都已经得到修复，这通常需要我们经过三次以上的灰度过程，而且无法快速的验证这些问题在同一批用户的修复效果。利用热补丁技术，我们可以快速对同一批用户验证修复效果，这大大缩短我们的发布流程。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;"><img src="http://img0.tuicool.com/2aEZFfu.jpg!web" style="max-width: 96%; height: auto; vertical-align: middle; border: 0px none; margin: 0px auto 10px; text-align: center; display: block;"  alt="" />若发布版本出现问题或紧急漏洞，传统方式需要单独灰度验证修改，然后重新发布新的版本。利用补丁技术，我们只需要先上线小部分用户验证修改的效果，最后再全量上线即可。但是此种发布对线上用户影响较大， 我们需要谨慎而为。本着对用户负责的态度，&nbsp;<strong style="text-indent: 0px;">发布补丁等同于发布版本</strong>&nbsp;，它也应该严格执行完整的测试与上线流程。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;"><img src="http://img2.tuicool.com/F3i6Bjb.png!web" style="max-width: 96%; height: auto; vertical-align: middle; border: 0px none; margin: 0px auto 10px; text-align: center; display: block;"  alt="" />总的来说，补丁技术可以降低开发成本，缩短开发周期，实现轻量而快速的升级。</p><h3>二. 远端调试</h3><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">一入Android深似海，Android开发的另外一个痛是机型的碎片化。我们也许都会遇到"本地不复现"，"日志查不出"，"联系用户不鸟你"的烦恼。所以补丁机制非常适合使用在远端调试上。即我们需要具备只特定用户发送补丁的能力，这对我们查找问题非常有帮助。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;"><img src="http://img1.tuicool.com/E7Njq2u.jpg!web" style="max-width: 96%; height: auto; vertical-align: middle; border: 0px none; margin: 0px auto 10px; text-align: center; display: block;"  alt="" />利用补丁技术，我们避免了骚扰用户而默默的为用户解决问题。当然这也需要非常严格的权限管理，以防恶意或随意使用。</p><h3>三. 数据统计</h3><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">数据统计在微信中也占据着非常重要的位置，我们也非常希望将热补丁与数据统计结合的更好。事实上，热补丁无论在普通的数据统计还是ABTest都有着非常大的优势。例如若我想对同一批用户做两种test, 传统方式无法让这批用户去安装两个版本。使用补丁技术，我们可以方便的对同一批用户更换补丁版本。<img src="http://img1.tuicool.com/QRfEBjR.jpg!web" style="max-width: 96%; height: auto; vertical-align: middle; border: 0px none; margin: 0px auto 10px; text-align: center; display: block;"  alt="" />在数据统计之路，如何与补丁技术结合的更好，更加精准的控制样本人数与比例，这也是微信当前努力发展的一个方向。</p><h3>四. 其他</h3><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">事实上，Android官方也使用热补丁技术实现Instant Run。它分为Hot Swap、Warm Swap与Cold Swap三种方式，大家可以参考&nbsp;<span target="_blank">英文介绍</span>&nbsp;，也可以看参考文章中的翻译稿。最新的Instant App应该也是采用类似的原理，但是Google Play是不允许下发代码的，这个海外App需要注意一下。</p><h2>微信热补丁技术的演进之路</h2><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">在了解补丁技术可以与适合做什么之后，我们回到技术本身。由于&nbsp;<span target="_blank">Dexposed</span>&nbsp;无法支持全平台，并不适合应用到商业产品中。所以这里我们只简单介绍Andfix、Qzone、微信几套方案的实现，以及它们方案面临着的问题，大家也可以参考资料中的&nbsp;<span target="_blank">各大热补丁方案分析和比较</span>&nbsp;一文。</p><h3>一. AndFix</h3><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;"><span target="_blank">AndFix</span>&nbsp;采用native hook的方式，这套方案直接使用&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; border-radius: 3px; border: none; background-color: #f7f7f9;">dalvik_replaceMethod</code>&nbsp;替换class中方法的实现。由于它并没有整体替换class, 而field在class中的相对地址在class加载时已确定，所以AndFix无法支持新增或者删除filed的情况(通过替换&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; border-radius: 3px; border: none; background-color: #f7f7f9;">init</code>&nbsp;与<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; border-radius: 3px; border: none; background-color: #f7f7f9;">clinit</code>&nbsp;只可以修改field的数值)。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;"><img src="http://img0.tuicool.com/aiIJB3M.jpg!web" style="max-width: 96%; height: auto; vertical-align: middle; border: 0px none; margin: 0px auto 10px; text-align: center; display: block;"  alt="" />也正因如此，Andfix可以支持的补丁场景相对有限，仅仅可以使用它来修复特定问题。结合之前的发布流程，我们更希望补丁对开发者是不感知的，即他不需要清楚这个修改是对补丁版本还是正式发布版本(事实上我们也是使用git分支管理+cherry-pick方式)。另一方面，使用native替换将会面临比较复杂的兼容性问题。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;"><img src="http://img1.tuicool.com/2aqqYrJ.png!web" style="max-width: 96%; height: auto; vertical-align: middle; border: 0px none; margin: 0px auto 10px; text-align: center; display: block;"  alt="" />相比其他方案，AndFix的最大优点在于立即生效。事实上，AndFix的实现与&nbsp;<span target="_blank">Instant Run的热插拔</span>&nbsp;有点类似，但是由于使用场景的限制，微信在最初期已排除使用这一方案。</p><h3>二. Qzone</h3><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">Qzone方案并没有开源，但在github上的&nbsp;<span target="_blank">Nuwa</span>&nbsp;采用了相同的方式。这个方案使用classloader的方式，能实现更加友好的类替换。而且这与我们加载Multidex的做法相似，能基本保证稳定性与兼容性。具体原理在这里不再细说，大家可以参考"安卓App热补丁动态修复技术介绍"这篇文章。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">本方案为了解决&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; border-radius: 3px; border: none; background-color: #f7f7f9;">unexpected DEX problem</code>&nbsp;异常而采用插桩的方式，从而规避问题的出现。事实上，Android系统的这些检查规则是非常有意义的，这会导致Qzone方案在Dalvik与Art都会产生一些问题。</p><ul style="padding: 0px; margin: 0px 0px 0.75em 25px; list-style-type: none; line-height: 1.7em;"><li style="line-height: 1.7em; list-style-type: disc;"><p style="margin: 0px 0px 0.75em; line-height: 1.7em;">Dalvik； 在dexopt过程，若class verify通过会写入pre-verify标志，在经过optimize之后再写入odex文件。这里的optimize主要包括inline以及quick指令优化等。</p></li></ul><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;"><img src="http://img2.tuicool.com/qaIVFjN.jpg!web" style="max-width: 96%; height: auto; vertical-align: middle; border: 0px none; margin: 0px auto 10px; text-align: center; display: block;"  alt="" />若采用插桩导致所有类都非preverify，这导致verify与optimize操作会在加载类时触发。这会有一定的性能损耗，微信分别采用插桩与不插桩两种方式做过两种测试，一是连续加载700个50行左右的类，一是统计微信整个启动完成的耗时。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;"><img src="http://img0.tuicool.com/EzIjYzz.png!web" style="max-width: 96%; height: auto; vertical-align: middle; border: 0px none; margin: 0px auto 10px; text-align: center; display: block;"  alt="" />平均每个类verify+optimize(跟类的大小有关系)的耗时并不长，而且这个耗时每个类只有一次。但由于启动时会加载大量的类，在这个情况影响还是比较大。</p><ul style="padding: 0px; margin: 0px 0px 0.75em 25px; list-style-type: none; line-height: 1.7em;"><li style="line-height: 1.7em; list-style-type: disc;"><p style="margin: 0px 0px 0.75em; line-height: 1.7em;">Art； Art采用了新的方式，插桩对代码的执行效率并没有什么影响。但是若补丁中的类出现修改类变量或者方法，可能会导致出现内存地址错乱的问题。为了解决这个问题我们需要将修改了变量、方法以及接口的类的父类以及调用这个类的所有类都加入到补丁包中。这可能会带来补丁包大小的急剧增加。</p></li></ul><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;"><img src="http://img1.tuicool.com/NVjqQvi.jpg!web" style="max-width: 96%; height: auto; vertical-align: middle; border: 0px none; margin: 0px auto 10px; text-align: center; display: block;"  alt="" />这里是因为在dex2oat时&nbsp;<code style="padding: 2px 4px; font-family: Monaco, Menlo, Consolas, 'Courier New', monospace; border-radius: 3px; border: none; background-color: #f7f7f9;">fast*</code>&nbsp;已经将类能确定的各个地址写死。如果运行时补丁包的地址出现改变，原始类去调用时就会出现地址错乱。这里说的可能不够详细，事实上微信当时为了查清这两个问题，也花费了一定的时间将Dalvik跟Art的流程基本搞透。若大家对这里感兴趣，后续在单独的文章详细论述。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">总的来说，Qzone方案好处在于开发透明，简单，这一套方案目前的应用成功率也是最高的，&nbsp;但在补丁包大小与性能损耗上有一定的局限性。特别是无论我们是否真正应用补丁，都会因为插桩导致对程序运行时的性能产生影响。微信对于性能要求较高，所以我们也没有采用这套方案。</p><h3>三. 微信热补丁方案</h3><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">有没有那么一种方案，能做到开发透明，但是却没有Qzone方案的缺陷呢？Instant Run的冷插拔与buck的&nbsp;<span target="_blank">exopackage</span>&nbsp;或许能给我们灵感，它们的思想都是全量替换新的Dex。即我们完全使用了新的Dex，那样既不出现Art地址错乱的问题，在Dalvik也无须插桩。当然考虑到补丁包的体积，我们不能直接将新的Dex放在里面。但我们可以将新旧两个Dex的差异放到补丁包中，最简单我们可以采用BsDiff算法。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;"><img src="http://img0.tuicool.com/BzMrUrQ.jpg!web" style="max-width: 96%; height: auto; vertical-align: middle; border: 0px none; margin: 0px auto 10px; text-align: center; display: block;"  alt="" />简单来说，在编译时通过新旧两个Dex生成差异patch.dex。在运行时，将差异patch.dex重新跟原始安装包的旧Dex还原为新的Dex。这个过程可能比较耗费时间与内存，所以我们是单独放在一个后台进程:patch中。为了补丁包尽量的小，微信自研了DexDiff算法，它深度利用Dex的格式来减少差异的大小。它的粒度是Dex格式的每一项，可以充分利用原本Dex的信息，而BsDiff的粒度是文件，AndFix/Qzone的粒度为class。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;"><img src="http://img1.tuicool.com/VfymQne.jpg!web" style="max-width: 96%; height: auto; vertical-align: middle; border: 0px none; margin: 0px auto 10px; text-align: center; display: block;"  alt="" />这块后面我希望后面用单独的文章来讲述，这里先做一个铺垫，大致的效果如下图。在最极端的情况，由于利用了原本dex的信息完全替换一个13M的Dex，我们的补丁大小也仅仅只有6.6M。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;"><img src="http://img1.tuicool.com/bMvuymU.png!web" style="max-width: 96%; height: auto; vertical-align: middle; border: 0px none; margin: 0px auto 10px; text-align: center; display: block;"  alt="" />但是这套方案并非没有缺点，它带来的问题有两个：</p><ol style="padding: 0px; margin: 0px 0px 0.75em 25px; line-height: 1.7em;"><li style="line-height: 1.7em;"><p style="margin: 0px 0px 0.75em; text-indent: 1em; line-height: 1.7em;">占用Rom体积；这边大约是你所修改Dex大小的1.5倍(&nbsp;Dex压缩成jar的大小加上&nbsp;生成的dexopt文件大小)。</p></li><li style="line-height: 1.7em;"><p style="margin: 0px 0px 0.75em; text-indent: 1em; line-height: 1.7em;">一个额外的合成过程；虽然我们单独放在一个进程上处理，但是合成时间的长短与内存消耗也会影响最终的成功率(与修改Dex大小、补丁大小相关)。</p></li></ol><div style="line-height: 1.7em;"><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">微信的热补丁方案叫做Tinker，也算缅怀一下Dota中的地精修补匠，希望能做到无限刷新。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;"><img src="http://img2.tuicool.com/IjIzM3A.jpg!web" style="max-width: 96%; height: auto; vertical-align: middle; border: 0px none; margin: 0px auto 10px; text-align: center; display: block;"  alt="" /></p></div><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">限于篇幅，这里对Dex、library以及资源的更多技术细节并没有详细的论述，这里希望放在后面的单独文章中。我们最后从整体比较一下这几种方案：</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;"><img src="http://img2.tuicool.com/F7nmQne.jpg!web" style="max-width: 96%; height: auto; vertical-align: middle; border: 0px none; margin: 0px auto 10px; text-align: center; display: block;"  alt="" />若不care性能损耗与补丁包大小，Qzone方案是最简单且成功率最高的方案(没有单独的合成过程)。相对Tinker来说，它的占用Rom体积也更小。另一方面，Qzone与Tinker的成功率当前大约相差3%左右。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">事实上，一个完整的框架应该也是一个容易使用的框架。Tinker对补丁版本管理、进程管理、安全校验等都有着很好的支持。同时我们也支持gradle与命名行两种接入方式。希望在不久的将来，它可以很快的跟大家见面。</p><h2>微信的热补丁应用现状</h2><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">上一章节我们简单比较了各个热补丁的技术方案，它们解决了如何生成与加载补丁包的问题。但一个完善的热补丁系统不应该仅限于此，它还需要包括以下几个方面：</p><ul style="padding: 0px; margin: 0px 0px 0.75em 25px; list-style-type: none; line-height: 1.7em;"><li style="line-height: 1.7em; list-style-type: disc;"><p style="margin: 0px 0px 0.75em; line-height: 1.7em;">网络通道；这里要解决的问题是决定补丁以何种方式推送给哪部分的用户。</p></li><li style="line-height: 1.7em; list-style-type: disc;"><p style="margin: 0px 0px 0.75em; line-height: 1.7em;">上线与后台管理平台；这里主要包括热补丁的上线管理，历史管理以及上报分析，报警监控等；</p></li></ul><h3>一. 网络通道现状</h3><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">网络通道负责的将补丁包交付给用户，这个包括特定用户与全量用户两种情况。事实上，微信当前针对热补丁有以下三种通道更新：</p><ul style="padding: 0px; margin: 0px 0px 0.75em 25px; list-style-type: none; line-height: 1.7em;"><li style="line-height: 1.7em; list-style-type: disc;"><p style="margin: 0px 0px 0.75em; line-height: 1.7em;">pull通道; 在登陆/24小时等时机，通过pull方式查询后台是否有对应的补丁包更新，这也是我们最常用的方式；</p></li><li style="line-height: 1.7em; list-style-type: disc;"><p style="margin: 0px 0px 0.75em; line-height: 1.7em;">指定版本的push通道; 针对版本的通道，在紧急情况下，我们可以在一个小时内向所有用户下发补丁包更新。</p></li><li style="line-height: 1.7em; list-style-type: disc;"><p style="margin: 0px 0px 0.75em; line-height: 1.7em;">指定特定用户的push通道;对特定用户或用户组做远程调试。</p></li></ul><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">事实上，对于大部分的应用来说，假设不实现push通道，CDN+pull通道实现起来还是较为容易。</p><h3>二. 上线与管理平台现状</h3><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">上线与管理平台主要为了快速上线，管理历史记录，以及监控补丁的运行情况等(界面比较丑陋，因为我们木有美工啊)。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;"><img src="http://img0.tuicool.com/J7JNJnn.jpg!web" style="max-width: 96%; height: auto; vertical-align: middle; border: 0px none; margin: 0px auto 10px; text-align: center; display: block;"  alt="" />事实上，微信发布热补丁是非常慎重的。它整个发布流程与升级版本是保持一致的，也必须修改版本号、经过严格的完整测试流程等。我们也会通过灰度的方式上线，同时监控补丁版本的各个指标。这里的为了完整的监控补丁的情况，我们做的工作有：</p><ul style="padding: 0px; margin: 0px 0px 0.75em 25px; list-style-type: none; line-height: 1.7em;"><li style="line-height: 1.7em; list-style-type: disc;"><p style="margin: 0px 0px 0.75em; line-height: 1.7em;">1分钟粒度的每小时/每天的各版本累积用户，及时监控补丁版本的人数与活跃；</p></li><li style="line-height: 1.7em; list-style-type: disc;"><p style="margin: 0px 0px 0.75em; line-height: 1.7em;">3分钟粒度的Crash统计，基准版本与补丁版本的Crash每小时/每天的两个维度对照；</p></li><li style="line-height: 1.7em; list-style-type: disc;"><p style="margin: 0px 0px 0.75em; line-height: 1.7em;">10分钟粒度的补丁监控信息上报。</p></li></ul><h3>三. 补丁成功率现状</h3><div style="line-height: 1.7em;"><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">应用成功率= 补丁版本人数/补丁发布前该版本人数</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">由于可能存在基准或补丁版本用户安装了其他版本，所以本统计结果应略为偏低，但它能现实的反应补丁的线上覆盖情况。</p></div><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">使用Qzone方案，微信补丁在10天后的应用成功率大约在98.5%左右。使用Tinker大约只有95.5%左右，主要原因在于空间不足以及后台进程被杀。在这里我们也在尝试使用重试的方式以及降低合成的耗时与内存，从而提升成功率。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">热补丁技术发展的很快，Android推出的Instant App也令人期待。但是在国内，似乎我们还是指望自己更靠谱一点。每一个的应用的需求都不太一致，这里大致讲了一些微信的实践经验，希望对大家有帮助。</p><h2>未来工作</h2><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">随着微信部门内从&#8220;单APP&#8221;向&#8220;多APP&#8221;演进，微信也正在迈入开源化的开发实践。我们希望将各个功能组件化，从而做可以到快速复制与应用。微信的热补丁框架&#8220;Tinker&#8221;当前也在经历从微信分离，又合入到微信的过程。希望在不久的将来，我们也可以将&#8220;Tinker&#8221;以及微信中一些其他的组件开源出去。</p><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">我们也希望可以找一些App作为内测，给我们提供宝贵的意见。若对微信的Tinker方案感兴趣的用户，可以单独发消息或在文章末留言注明姓名、所在公司以及负责的App，我们希望挑选部分产品作为内测。</p><h2>参考文章</h2><p style="margin: 0px 0px 0.75em; line-height: 1.7em; text-indent: 1em;">大家可以点击下方的阅读原文，即可直接点击跳转。</p><ol style="padding: 0px; margin: 0px 0px 0.75em 25px; line-height: 1.7em;"><li style="line-height: 1.7em;"><p style="margin: 0px 0px 0.75em; text-indent: 1em; line-height: 1.7em;">Dexposed github (&nbsp;<span target="_blank">https://github.com/alibaba/dexposed</span>&nbsp;)</p></li><li style="line-height: 1.7em;"><p style="margin: 0px 0px 0.75em; text-indent: 1em; line-height: 1.7em;">AndFix github (&nbsp;<span target="_blank">https://github.com/alibaba/AndFix</span>&nbsp;)</p></li><li style="line-height: 1.7em;"><p style="margin: 0px 0px 0.75em; text-indent: 1em; line-height: 1.7em;">Nuwa github (&nbsp;<span target="_blank">https://github.com/jasonross/Nuwa</span>&nbsp;)</p></li><li style="line-height: 1.7em;"><p style="margin: 0px 0px 0.75em; text-indent: 1em; line-height: 1.7em;">Qzone实现原理解析 (&nbsp;https://mp.weixin.qq.com/s?__biz=MzI1MTA1MzM2Nw==&amp;mid=400118620&amp;idx=1&amp;sn=b4fdd5055731290eef12ad0d17f39d4a&nbsp;)</p></li><li style="line-height: 1.7em;"><p style="margin: 0px 0px 0.75em; text-indent: 1em; line-height: 1.7em;">Instant Run英文原文 (&nbsp;<span target="_blank">https://medium.com/google-developers/instant-run-how-does-it-work-294a1633367f#.c088qhdxu</span>&nbsp;)</p></li><li style="line-height: 1.7em;"><p style="margin: 0px 0px 0.75em; text-indent: 1em; line-height: 1.7em;">Instant Run工作原理及用法中文翻译稿 (&nbsp;<span target="_blank">http://www.jianshu.com/p/2e23ba9ff14b</span>&nbsp;)</p></li><li style="line-height: 1.7em;"><p style="margin: 0px 0px 0.75em; text-indent: 1em; line-height: 1.7em;">Buck exopackage 介绍 (&nbsp;<span target="_blank">https://buckbuild.com/article/exopackage.html</span>&nbsp;)</p></li><li style="line-height: 1.7em;"><p style="margin: 0px 0px 0.75em; text-indent: 1em; line-height: 1.7em;">各大热补丁方案分析和比较 (<span target="_blank">http://blog.zhaiyifan.cn/2015/11/20/HotPatchCompare/</span>&nbsp;)</p></li></ol></div></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/431119.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2016-07-07 16:10 <a href="http://www.blogjava.net/xiaomage234/archive/2016/07/07/431119.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Mac下获取AppStore安装包文件路径</title><link>http://www.blogjava.net/xiaomage234/archive/2015/10/21/427849.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Wed, 21 Oct 2015 04:29:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/10/21/427849.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/427849.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/10/21/427849.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/427849.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/427849.html</trackback:ping><description><![CDATA[<p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">本文介绍了Mac下如何找到AppStore下载的安装包路径，以及如何提取出来供以后使用的相关步骤，希望对大家有所帮助。</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;"><br style="padding: 0px;" /></span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通过远在大洋彼岸的苹果服务器下载东西，确实有够慢啊！AppStore更甚：甚至都经常提示连不上服务器，而有些软件呢，还必须从AppStore下载安装，所以没办法，谁让上了苹果的贼船呢！公司的网速更是不敢恭维，以至于基本上不下东西，除非像这次一样：手贱的把iPhone6升级到8.2.2了，然后Xcode6.1.1真机调试不成了，所以需要下个Xcode6.2。昨天刚更新的Xcode6.2，没有看国内有同胞下载下来没，一般我都是会从官网下载一个保存到百度网盘以供自己和别人使用的。但是迅雷、浏览器下载的都很慢，于是我就通过AppStore更新，貌似还有点儿小快呢（不知道是不是心理作用）！</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;但是又有一个问题：AppStore安装完后会删除安装包，而且也不知道路径在哪儿，这我怎么能容忍！！！因为公司还有好多电脑要装呢！！！于是乎，就参考网络上的各种资源，找到了下载的路径~~~</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;"><br style="padding: 0px;" /></span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;"><br style="padding: 0px;" /></span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">废话不多说了，上步骤（前提：正在安装一个程序，例如我正在安装Xcode）：</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">1.如图所示：从应用中打开活动监视器：</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; text-align: center; background-color: #ffffff;"><a href="http://s3.51cto.com/wyfs02/M01/5B/1C/wKioL1T_5VmDKW1SAASzbkb-DEU887.jpg" target="_blank" style="padding: 0px; color: #333333; text-decoration: none;"><img alt="技术分享" src="http://s3.51cto.com/wyfs02/M01/5B/1C/wKioL1T_5VmDKW1SAASzbkb-DEU887.jpg" title="QQ20150311-3.png" width="650" style="padding: 0px; max-width: 680px; overflow: hidden;" /></a></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><br style="padding: 0px;" /></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;打开后如图所示：</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; text-align: center; background-color: #ffffff;"><a href="http://s3.51cto.com/wyfs02/M02/5B/1C/wKioL1T_5NTiKWC1AAMz09kSCeA181.jpg" target="_blank" style="padding: 0px; color: #333333; text-decoration: none;"><img alt="技术分享" src="http://s3.51cto.com/wyfs02/M02/5B/1C/wKioL1T_5NTiKWC1AAMz09kSCeA181.jpg" title="QQ20150311-2.png" style="padding: 0px; max-width: 680px; overflow: hidden;" /></a></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><br style="padding: 0px;" /></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">2.找到进程storedownloadd（以前的是storeagent进程，到10.10之后是<span style="padding: 0px;">storedownloadd</span>这个进程）：</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; text-align: center; background-color: #ffffff;"><a href="http://s3.51cto.com/wyfs02/M00/5B/1C/wKioL1T_5qiDyFwcAAMz09kSCeA380.jpg" target="_blank" style="padding: 0px; color: #333333; text-decoration: none;"><img alt="技术分享" src="http://s3.51cto.com/wyfs02/M00/5B/1C/wKioL1T_5qiDyFwcAAMz09kSCeA380.jpg" title="QQ20150311-2.png" style="padding: 0px; max-width: 680px; overflow: hidden;" /></a></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><br style="padding: 0px;" /></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">3.点击左上角第二个：查看所选进程的信息：</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; text-align: center; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;"><a href="http://s3.51cto.com/wyfs02/M01/5B/22/wKiom1T_5Irz3AdqAAM-7Kc9wG8094.jpg" target="_blank" style="padding: 0px; color: #333333; text-decoration: none;"><img alt="技术分享" src="http://s3.51cto.com/wyfs02/M01/5B/22/wKiom1T_5Irz3AdqAAM-7Kc9wG8094.jpg" title="QQ20150311-4.png" style="padding: 0px; max-width: 680px; overflow: hidden;" /></a></span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; text-align: center; background-color: #ffffff;"><br style="padding: 0px;" /></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><br style="padding: 0px;" /></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;"><br style="padding: 0px;" /></span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">4.选择第三个标签：打开的文件和端口</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; text-align: center; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;"><a href="http://s3.51cto.com/wyfs02/M01/5B/1C/wKioL1T_5fuxej5WAAGj9dvsfZI465.jpg" target="_blank" style="padding: 0px; color: #333333; text-decoration: none;"><img alt="技术分享" src="http://s3.51cto.com/wyfs02/M01/5B/1C/wKioL1T_5fuxej5WAAGj9dvsfZI465.jpg" title="QQ20150311-5.png" style="padding: 0px; max-width: 680px; overflow: hidden;" /></a></span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><br style="padding: 0px;" /></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">5.command + F，找到以.pkg结尾的路径并且拷贝，如下图所示：</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; text-align: center; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;"><br style="padding: 0px;" /><a href="http://s3.51cto.com/wyfs02/M01/5B/1C/wKioL1T_5fuxej5WAAGj9dvsfZI465.jpg" target="_blank" style="padding: 0px; color: #333333; text-decoration: none;"><img alt="技术分享" src="http://s3.51cto.com/wyfs02/M01/5B/1C/wKioL1T_5fuxej5WAAGj9dvsfZI465.jpg" title="QQ20150311-5.png" style="padding: 0px; max-width: 680px; overflow: hidden;" /></a></span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">6.在Finder中前往文件夹：</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; text-align: center; background-color: #ffffff;"><a href="http://s3.51cto.com/wyfs02/M00/5B/22/wKiom1T_5cHSU8TzAAHhWvDJ0QY936.jpg" target="_blank" style="padding: 0px; color: #333333; text-decoration: none;"><img alt="技术分享" src="http://s3.51cto.com/wyfs02/M00/5B/22/wKiom1T_5cHSU8TzAAHhWvDJ0QY936.jpg" title="QQ20150311-6.png" style="padding: 0px; max-width: 680px; overflow: hidden;" /></a></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><br style="padding: 0px;" /></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">7.粘贴复制的路径，并且回车</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; text-align: center; background-color: #ffffff;"><a href="http://s3.51cto.com/wyfs02/M01/5B/1C/wKioL1T_5xTxM8Y3AABzKKg_WNs929.jpg" target="_blank" style="padding: 0px; color: #333333; text-decoration: none;"><img alt="技术分享" src="http://s3.51cto.com/wyfs02/M01/5B/1C/wKioL1T_5xTxM8Y3AABzKKg_WNs929.jpg" title="QQ20150311-11.png" style="padding: 0px; max-width: 680px; overflow: hidden;" /></a></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><br style="padding: 0px;" /></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">8.如下图一样的pkg包就是下载的安装包</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; text-align: center; background-color: #ffffff;"><a href="http://s3.51cto.com/wyfs02/M02/5B/1C/wKioL1T_5y2AxUPNAAGbzI0BSQs610.jpg" target="_blank" style="padding: 0px; color: #333333; text-decoration: none;"><img alt="技术分享" src="http://s3.51cto.com/wyfs02/M02/5B/1C/wKioL1T_5y2AxUPNAAGbzI0BSQs610.jpg" title="QQ20150311-7.png" width="650" style="padding: 0px; max-width: 680px; overflow: hidden;" /></a></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><br style="padding: 0px;" /></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;"><br style="padding: 0px;" /></span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注意，<span style="padding: 0px; background-color: #ffff00;">这一点非常重要</span>：<span style="padding: 0px; background-color: #ffc000;">第一：不要把这个包早拷出来：因为还没有下载完成；第二：不要等安装完再拷：安装完系统会把这个包删除的。</span>一定要抓住机会，在系统安装程序的时候以迅雷不及掩耳盗铃儿响叮当之势，把它拉出来~~~</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;"><br style="padding: 0px;" /></span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">例如下载的Xcode：</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;正在下载：</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; text-align: center; background-color: #ffffff;"><a href="http://s3.51cto.com/wyfs02/M02/5B/22/wKiom1T_5sSSzGnMAAAljsRt7lg986.jpg" target="_blank" style="padding: 0px; color: #333333; text-decoration: none;"><img alt="技术分享" src="http://s3.51cto.com/wyfs02/M02/5B/22/wKiom1T_5sSSzGnMAAAljsRt7lg986.jpg" title="QQ20150311-8.png" style="padding: 0px; max-width: 680px; overflow: hidden;" /></a></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="padding: 0px; font-size: 20px;">&nbsp;快完了，一定要看住：</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; text-align: center; background-color: #ffffff;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://s3.51cto.com/wyfs02/M01/5B/22/wKiom1T_5uyB4tawAAAjwzCRADI448.jpg" target="_blank" style="padding: 0px; color: #333333; text-decoration: none;"><img alt="技术分享" src="http://s3.51cto.com/wyfs02/M01/5B/22/wKiom1T_5uyB4tawAAAjwzCRADI448.jpg" title="QQ20150311-9.png" style="padding: 0px; max-width: 680px; overflow: hidden;" /></a><br style="padding: 0px;" /><br style="padding: 0px;" /></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;我这个是下载完了的，因为我打开了Xcode，所以桌面弹出了一个警告框让我关闭，我直接拖出来了，所以还没有出现正在安装。如果没有打开正在安装的程序，<span style="padding: 0px; background-color: #ffff00;">这里会显示：正在安装</span>，就是这个时候抓住这一瞬间，把pkg拖出来，完工~~~</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><br style="padding: 0px;" /></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;现在好了，整个世界平静了，下载的软件被我们揪住了，然后双击安装即可。安装完后还可以拷到其他的电脑上进行安装，省的再次下载了~~~</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; text-align: center; background-color: #ffffff;"><a href="http://s3.51cto.com/wyfs02/M00/5B/1C/wKioL1T_55eTFvP4AAC4ghxB5hg919.jpg" target="_blank" style="padding: 0px; color: #333333; text-decoration: none;"><img alt="技术分享" src="http://s3.51cto.com/wyfs02/M00/5B/1C/wKioL1T_55eTFvP4AAC4ghxB5hg919.jpg" title="QQ20150311-10.png" style="padding: 0px; max-width: 680px; overflow: hidden;" /></a></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><br style="padding: 0px;" /></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;通过这种方式得到的安装包和从苹果官网下载的安装包不一样：苹果官网下载的时后缀为.dmg的镜像，里面包含.pkg的安装包，而这个直接就是pkg的包，双击安装即可~~~</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;"><br style="padding: 0px;" /></span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;希望对大家有所帮助！！！</span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;"><br style="padding: 0px;" /></span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><span style="padding: 0px; font-size: 20px;"><br style="padding: 0px;" /></span></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;"><br style="padding: 0px;" /></p><p style="font-family: Arial, Helvetica, sans-serif; padding: 0px; color: #3f3f3f; line-height: 30px; background-color: #ffffff;">本文出自 &#8220;<a href="http://www.mamicode.com/%E2%80%98http://winann.blog.51cto.com%E2%80%98" style="padding: 0px; color: #333333; text-decoration: none;">一毛</a>&#8221; 博客，请务必保留此出处<a href="http://www.mamicode.com/%E2%80%98http://winann.blog.51cto.com/4424329/1619352%E2%80%98" style="padding: 0px; color: #333333; text-decoration: none;">http://winann.blog.51cto.com/4424329/1619352</a></p><img src ="http://www.blogjava.net/xiaomage234/aggbug/427849.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-10-21 12:29 <a href="http://www.blogjava.net/xiaomage234/archive/2015/10/21/427849.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MAC OS X10.10上Android开发环境搭建【转】</title><link>http://www.blogjava.net/xiaomage234/archive/2015/06/15/425690.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Mon, 15 Jun 2015 01:01:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/06/15/425690.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/425690.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/06/15/425690.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/425690.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/425690.html</trackback:ping><description><![CDATA[<p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;">from:</span><span style="font-family: verdana, 'courier new'; line-height: 21px;">http://blog.csdn.net/yanzi1225627/article/details/42040629</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;">由于Google官方已经不提供Adt－Bundle下载了，主推AndroidStudio。可以从这个链接下载http://www.androiddevtools.cn。上面不光有adt－bundle，还有最新的AndroidStudio。由于对OS X还不是很熟悉，本次采用adt－bundle安装。</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;">一,下载JDK</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><span style="white-space: pre;">	</span>下载方式有两种，其一是从链接http://www.androiddevtools.cn处下载，选择Mac OSX的1.8u5版本即可。截图如下：</span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-align: center; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><img src="http://img.blog.csdn.net/20141220090815536?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWFuemkxMjI1NjI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><span style="white-space: pre;">	</span>其二是从JDK的官网下载，文件名为<span style="line-height: 16px;">jdk-8u25-macosx-x64.dmg，大小219.3M。这个稍后我上传至百度网盘供大家下载。我就是通过这种方式下载的。下载完毕后，点击打开，接着出现如下：</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-align: center; background-color: #ffffff;"><span style="line-height: 16px;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><img src="http://img.blog.csdn.net/20141220091348004?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWFuemkxMjI1NjI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /></span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="line-height: 16px;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;">再点击一下就开始安装了，中间会让输入用户名和密码。安装完毕后，打开个终端，输入javac －version查看是否安装成功。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-align: center; background-color: #ffffff;"><span style="line-height: 16px;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><img src="http://img.blog.csdn.net/20141220091548576?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWFuemkxMjI1NjI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /></span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="line-height: 16px;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;">像上图所示就是安装成功了。哈哈，其实OSX没什么神秘的，全当它是linux就好了。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="line-height: 16px;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;">二，下载Adt－Bundle</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="line-height: 16px;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;">从http://www.androiddevtools.cn处下载，选择Mac OSX的64位23.0.2即可。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-align: center; background-color: #ffffff;"><span style="line-height: 16px;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><img src="http://img.blog.csdn.net/20141220091908990?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWFuemkxMjI1NjI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /></span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="line-height: 16px;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;">文件名为adt-bundle-mac-x86_64-20140702.zip，大小320.6M。是个zip格式的压缩包，打开解压后看到根windows上一样是熟悉的eclipse和sdk文件夹。这就表示安装完毕了。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="line-height: 16px;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;">三，打开Eclipse</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><span style="line-height: 16px;">打开之后就傻眼了：</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-align: center; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><span style="line-height: 16px;"><img src="http://img.blog.csdn.net/20141220101919195?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWFuemkxMjI1NjI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /></span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><span style="line-height: 16px;">为此，我研究了N种解决办法：</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><span style="line-height: 16px;">1，http://www.cnblogs.com/zhouyinhui/p/3750836.html 让修改<span style="line-height: 24px;">Info.plist，没有任何效果。</span></span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><span style="line-height: 16px;"><span style="line-height: 24px;">2，还有的让配置jdk环境变量，sudo vim ／etc/profile,之后输入：</span></span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><span style="line-height: 16px;"></span></span></p><p style="color: #333333; font-family: Arial; line-height: 16px; background-color: #ffffff;">JAVA_HOME=<span style="line-height: normal;">/Library/Java/JavaVirtualMachines/jdk1.8.0_25.jdk/Contents/Home</span></p><p style="color: #333333; font-family: Arial; line-height: 16px; background-color: #ffffff;">export JAVA_HOME</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><span style="line-height: 24px;">然后source /etc/profile,没有效果。注意此处，jdk的环境变量设置一定要使用sudo vim，退出后用wq! 否则是保存不了的。JDK的路径貌似高低版本的OSX还不太一样，应以终端里输入：</span><span style="line-height: 24px;">/usr/libexec/java_home 打印出来的变量为准。可以参考：http://han.guokai.blog.163.com/blog/static/136718271201301183938165/</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="line-height: 24px;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;">3，最终找到了链接：http://java.com/zh_CN/download/faq/java_mac.xml#mac1010&nbsp;</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-align: center; background-color: #ffffff;"><span style="line-height: 24px;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><img src="http://img.blog.csdn.net/20141220102933375?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWFuemkxMjI1NjI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /></span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><span style="line-height: 24px;">上面的链接也就是打开eclipse，弹窗上的&#8220;更多信息&#8221;，http://support.apple.com/kb/DL1572?viewlocale=zh_CN&amp;locale=en_US，截图如下：</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; text-align: center; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><span style="line-height: 24px;"><img src="http://img.blog.csdn.net/20141220103115595?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWFuemkxMjI1NjI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /></span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><span style="line-height: 24px;">下载的文件名为</span><span style="line-height: 24px;">JavaForOSX2014-001.dmg，60多M。点击安装。终于Eclipse启动起来了，后面的就不啰嗦了。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="line-height: 24px;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><img src="http://img.blog.csdn.net/20141220103614804?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveWFuemkxMjI1NjI3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" style="border: none; max-width: 100%;" /><br /></span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><span style="line-height: 24px;">总结：一定要先在苹果官网上下载java1.6的安装包，然后java官网上下载安装jdk8u25. 后者是否是必须我没有测试，我mac上安装了这两个东西未见不良现象。</span></span></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><span style="font-family: 'Comic Sans MS'; font-size: 18px;"><span style="line-height: 24px;">备注：最新的jdk8u25已经可以顺利在OSX10.10上安装了，无需按照http://www.krislq.com/2014/07/mac-x-yosemide10-10-update-jdk-7-jdk-8/ 进行处理。</span></span></p><img src ="http://www.blogjava.net/xiaomage234/aggbug/425690.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-06-15 09:01 <a href="http://www.blogjava.net/xiaomage234/archive/2015/06/15/425690.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WWDC 2013 Session笔记 - iOS7中的多任务</title><link>http://www.blogjava.net/xiaomage234/archive/2015/01/19/422286.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Mon, 19 Jan 2015 10:11:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2015/01/19/422286.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/422286.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2015/01/19/422286.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/422286.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/422286.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 这是我的WWDC2013系列笔记中的一篇，完整的笔记列表请参看这篇总览。本文仅作为个人记录使用，也欢迎在许可协议范围内转载或使用，但是还烦请保留原文链接，谢谢您的理解合作。如果您觉得本站对您能有帮助，您可以使用RSS或邮件方式订阅本站，这样您将能在第一时间获取本站信息。本文涉及到的WWDC2013 Session有Session 204 What's New with MultitaskingSe...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2015/01/19/422286.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/422286.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2015-01-19 18:11 <a href="http://www.blogjava.net/xiaomage234/archive/2015/01/19/422286.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Mac下Eclipse连接不上Android手机的解决方法</title><link>http://www.blogjava.net/xiaomage234/archive/2014/12/16/421471.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 16 Dec 2014 08:19:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/12/16/421471.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/421471.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/12/16/421471.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/421471.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/421471.html</trackback:ping><description><![CDATA[from:http://blog.csdn.net/cooldragon/article/details/40212761<br /><br /><br /><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">现象是：</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">Windows下Eclipse可以连接Device里能显示设备名称，但是在Mac OS X下的Eclipse Device始终不能显示连接。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br /></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">解决方法：<br />1.把Android手机开启调试模式，然后连接在我们的Mac OS上。<br />2.选择Mac的 关于本机-&gt;更多信息-&gt; 系统报告-&gt;找到usb选项，右边会出现一系列和usb相关的设备我们找到自己的Android设备并选中。<br />3.选中后找到 供应商ID或叫厂商ID，我的MX4手机显示的供应商ID是：0x2a45</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><img src="http://img.blog.csdn.net/20141018170211687?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY29vbGRyYWdvbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" style="border: none; max-width: 100%;" /><br />4.打开Mac终端 输入： echo 0x2a45 &gt;&gt; ~/.android/adb_usb.ini<br /><br />然后重启adb（我是重启Mac系统）后再打开eclipse 你会发现Android手机的设备显示了。这样的办法还可以解决Mac上其他android设备不显示的问题。</p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br /></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;">感谢魅族的冤家对手小米论坛提供了解决方法，原文：<a target="_blank" href="http://www.miui.com/thread-1413676-1-1.html" style="color: #336699; text-decoration: none;">点击打开链接</a><br /></p><p style="color: #333333; font-family: Arial; line-height: 26px; background-color: #ffffff;"><br /><br /></p><img src ="http://www.blogjava.net/xiaomage234/aggbug/421471.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-12-16 16:19 <a href="http://www.blogjava.net/xiaomage234/archive/2014/12/16/421471.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Objective-C基础语法快速入门</title><link>http://www.blogjava.net/xiaomage234/archive/2014/11/04/419478.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 04 Nov 2014 03:24:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/11/04/419478.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/419478.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/11/04/419478.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/419478.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/419478.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 假如我们对面向对象的思维已经C语言都很熟悉的话，对于我们学习Objective-C将会非常有用。假如我们对C语言还不熟悉的话，那我们需要学习一下C语言。AD：2014WOT全球软件技术峰会北京站 课程视频发布2010年11月编程语言排行榜和2月编程语言排行榜讲的都是Objective-C。Objective-C是Mac软件开发领域最主要的开发语言，假如我们对面向对象的思维已经C语言都很熟悉的话，对...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2014/11/04/419478.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/419478.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-11-04 11:24 <a href="http://www.blogjava.net/xiaomage234/archive/2014/11/04/419478.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>构建iOS持续集成平台[转]</title><link>http://www.blogjava.net/xiaomage234/archive/2014/10/29/419174.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Wed, 29 Oct 2014 08:52:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/10/29/419174.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/419174.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/10/29/419174.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/419174.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/419174.html</trackback:ping><description><![CDATA[<table width="100%" border="0" align="center" cellpadding="0" cellspacing="0" style="font-family: 宋体; background-color: #ffffff;"><tbody><tr><td valign="top" bgcolor="#FFFFFF"><table width="95%" border="0" align="center" cellpadding="1" cellspacing="1"><tbody><tr></tr><tr><td bgcolor="#FFFFFF"><div align="center" style="font-family: stone-kaiti; font-size: 24px; font-weight: bold;">构建iOS持续集成平台</div></td></tr><tr><td height="17" bgcolor="#FFFFFF">&nbsp;</td></tr><tr><td bgcolor="#FFFFFF"><div align="center" style="color: #999999; font-size: 12px;">作者 刘先宁，火龙果软件&nbsp;&nbsp;&nbsp; 发布于&nbsp;2013-11-11</div></td></tr><tr><td height="16" bgcolor="#FFFFFF">&nbsp;</td></tr><tr><td valign="top" bgcolor="#FFFFFF"><table width="95%" border="0" align="center" cellpadding="3" cellspacing="1"><tbody><tr><td height="8739" valign="top" bgcolor="#FFFFFF" style="font-size: 12px; line-height: 20px;"><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">（一）&#8212;&#8212;自动化构建和依赖管理</p><p style="text-indent: 2em; font-size: 13px;">2000年Matin Fowler发表文章Continuous Integration【1】；2007年，Paul Duvall, Steve Matyas和 Andrew Glover合著的《Continuous Integration：Improving Software Quality and Reducing Risk》 【2】出版发行，该书获得了2008年的图灵大奖。持续集成理念经过10多年的发展，已经成为了业界的标准。在Java， Ruby的世界已经诞生了非常成熟的持续集成工具和实践，而对于iOS领域来说，因为技术本身相对比较年轻和苹果与生俱来的封闭思想，在持续集成方面的发展相对滞后一些，但是，随着越来越多的iOS开发者的涌入，以及各个互联网巨头加大对iOS开发的投入，诞生了一大批非常好用的持续集成工具和服务，本文的目的就是介绍一下如何有效的利用这些类库，服务快速构建一个iOS开发环境下的持续集成平台。</p><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">自动化构建</p><p style="text-indent: 2em; font-size: 13px;">在MartinFowler的文章[1]中关于自动化的构建定义如下：</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>Anyone should be able to bring in a virgin machine, check the sources <br />out of the repository, issue a single command, and have a running <br />system on their machine.</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">因此，自动化构建的的首要前提是有一个支持自动化构建的命令行工具，可以让开发人员可以通过一个简单的命令运行当前项目。</p><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">命令行工具</p><p style="text-indent: 2em; font-size: 13px;">自动化构建的命令行工具比持续集成的概念要诞生得早很多，几十年前，Unix世界就已经有了Make，而Java世界有Ant，Maven，以及当前最流行的Gradle，.Net世界则有Nant和MSBuild。作为以GUI和命令行操作结合的完美性著称的苹果公司来说，当然也不会忘记为自己的封闭的iOS系统提供开发环境下命令行编译工具：xcodebuild【3】</p><p style="text-indent: 20pt; font-size: 14px; line-height: 18px; font-weight: bold;">xcodebuild</p><p style="text-indent: 2em; font-size: 13px;">在介绍xcodebuild之前，需要先弄清楚一些在XCode环境下的一些概念【4】：</p><p style="text-indent: 2em; font-size: 13px;">Workspace：简单来说，Workspace就是一个容器，在该容器中可以存放多个你创建的Xcode Project， 以及其他的项目中需要使用到的文件。使用Workspace的好处有，1),扩展项目的可视域，即可以在多个项目之间跳转，重构，一个项目可以使用另一个项目的输出。Workspace会负责各个Project之间提供各种相互依赖的关系;2),多个项目之间共享Build目录。</p><p style="text-indent: 2em; font-size: 13px;">Project：指一个项目，该项目会负责管理生成一个或者多个软件产品的全部文件和配置，一个Project可以包含多个Target。</p><p style="text-indent: 2em; font-size: 13px;">Target：一个Target是指在一个Project中构建的一个产品，它包含了构建该产品的所有文件，以及如何构建该产品的配置。</p><p style="text-indent: 2em; font-size: 13px;">Scheme：一个定义好构建过程的Target成为一个Scheme。可在Scheme中定义的Target的构建过程有</p><p style="text-indent: 2em; font-size: 13px;">Build/Run/Test/Profile/Analyze/Archive</p><p style="text-indent: 2em; font-size: 13px;">BuildSetting：配置产品的Build设置，比方说，使用哪个Architectures？使用哪个版本的SDK？。在Xcode Project中，有Project级别的Build Setting，也有Target级别的Build Setting。Build一个产品时一定是针对某个Target的，因此，XCode中总是优先选择Target的Build Setting，如果Target没有配置，则会使用Project的Build Setting。</p><p style="text-indent: 2em; font-size: 13px;">弄清楚上面的这些概念之后，xcodebuild就很好理解了，官网上对其作用的描述如下：</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>xcodebuild builds one or more targets contained in an Xcode <br />project, or builds a scheme contained in an Xcode workspace or <br />Xcode project.</pre></td></tr></tbody></table><p style="text-indent: 20pt; font-size: 14px; line-height: 18px; font-weight: bold;">xcodebuild就是用了构建产品的命令行工具，其用法可以归结为3个部分：</p><p style="text-indent: 2em; font-size: 13px;">1.可构建的对象</p><p style="text-indent: 2em; font-size: 13px;">2.构建行为</p><p style="text-indent: 2em; font-size: 13px;">3.一些其他的辅助命令</p><p style="text-indent: 20pt; font-size: 14px; line-height: 18px; font-weight: bold;">可以构建的对象有，默认情况下会运行project下的第一个target：</p><p style="text-indent: 2em; font-size: 13px;">1.workspace：必须和&#8220;-scheme&#8221;一起使用，构建该workspace下的一个scheme。</p><p style="text-indent: 2em; font-size: 13px;">2.project：当根目录下有多个Project的时候，必须使用&#8220;-project&#8221;指定project，然后会运行</p><p style="text-indent: 2em; font-size: 13px;">3.target：构建某个Target</p><p style="text-indent: 2em; font-size: 13px;">4.scheme：和&#8220;-workspace&#8221;一起使用，指定构建的scheme。</p><p style="text-indent: 2em; font-size: 13px;">5.&#8230;&#8230;</p><p style="text-indent: 20pt; font-size: 14px; line-height: 18px; font-weight: bold;">构建行为包括：</p><p style="text-indent: 2em; font-size: 13px;">1.clean:清除build目录下的</p><p style="text-indent: 2em; font-size: 13px;">2.build: 构建</p><p style="text-indent: 2em; font-size: 13px;">3.test: 测试某个scheme，必须和"-scheme"一起使用</p><p style="text-indent: 2em; font-size: 13px;">4.archive:打包，必须和&#8220;-scheme&#8221;一起使用</p><p style="text-indent: 2em; font-size: 13px;">5.&#8230;&#8230;</p><p style="text-indent: 20pt; font-size: 14px; line-height: 18px; font-weight: bold;">辅助命令包括：</p><p style="text-indent: 2em; font-size: 13px;">1.-sdk：指定构建使用的SDK</p><p style="text-indent: 2em; font-size: 13px;">2.-list：列出当前项目下所有的Target和scheme。</p><p style="text-indent: 2em; font-size: 13px;">3.-version：版本信息</p><p style="text-indent: 2em; font-size: 13px;">4.&#8230;...</p><p style="text-indent: 2em; font-size: 13px;">关于xcodebuild更多详细的命令行请参见：https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/xcodebuild.1.html</p><p style="text-indent: 2em; font-size: 13px;">下图是使用XcodeBuild运行一个scheme的build的结果：</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/2013111111.png" width="700" height="285"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">了解了xcodebuild的用法之后，接下来分析一下xcodebuild的主要缺陷：</p><p style="text-indent: 2em; font-size: 13px;">1.从上图直接可以得到的感觉，其脚本输出的可读性极差，</p><p style="text-indent: 2em; font-size: 13px;">2.只能要么完整的运行一个target或者scheme，要么全部不运行。不能指定运行Target中特定的测试。</p><p style="text-indent: 2em; font-size: 13px;">3.最令人发指的是，XCode 4中的xcodebuild居然不支持iOSUnitTest的Target【5】，当我尝试运行一个iOS App的测试target时，得到如下的错误：</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/2013111112.png" width="700" height="86"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">对于上面提到的缺陷，Facebook给出了他们的解决方案：xctool【6】</p><p style="text-indent: 20pt; font-size: 14px; line-height: 18px; font-weight: bold;">xctool</p><p style="text-indent: 2em; font-size: 13px;">xctool在 其主页直接表明了其目的：</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>xctool is a replacement for Apple's xcodebuild that makes it easier  to build and<br /> test iOS and Mac products. It's especially helpful for continuous integration.</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">其作用是替代xcodebuild，目的是让构建和测试更加容易，更好的支持持续集成。从个人感受来看，它的确成功取代了xcodebuild。但是xctool说到底只是对xcodebuild的一个封装，只是提供了更加丰富的build指令，因此，使用xctool的前提是xcodebuild已经存在，且能正常工作。</p><p style="text-indent: 20pt; font-size: 14px; line-height: 18px; font-weight: bold;">安装</p><p style="text-indent: 2em; font-size: 13px;">xctool的安装非常简单，只需要clone xctool的repository到项目根目录就可以使用， 如果你的机器上安装有Homebrew，可以通过&#8220;brew install xctool&#8221;命令直接安装。（注意：使用xctool前一定要首先确认xcodebuild已安装且能正确工作）。</p><p style="text-indent: 20pt; font-size: 14px; line-height: 18px; font-weight: bold;">用法</p><p style="text-indent: 2em; font-size: 13px;">关于xctool的用法就更加人性化了，几乎可以重用所有的xcodebuild的指令，配置。只需要注意一下几点：</p><p style="text-indent: 2em; font-size: 13px;">1.xctool不支持target构建，只能使用scheme构建。</p><p style="text-indent: 2em; font-size: 13px;">2.支持&#8220;-only&#8221;指令运行指定的测试。</p><p style="text-indent: 2em; font-size: 13px;">3.支持多种格式的build报告。</p><p style="text-indent: 2em; font-size: 13px;">例子：</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>path/to/xctool.sh <br />  -workspaceYourWorkspace.xcworkspace<br />  -schemeYourScheme<br />test -only SomeTestTarget:SomeTestClass/testSomeMethod</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">下图是我使用xctool运行test的效果：</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/2013111113.png" width="700" height="317"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">常见问题：</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=x86_64, VALID_ARCHS=armv7 armv7s).</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">解决方法：到Project Setting中，把"Build Active Architecture Only"设置为NO</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>Code Sign error: A valid provisioning profile matching the application's Identifier 'dk.muncken.MyApp' could not be found</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">解决方法：通过&#8220;-sdkiphonesimulator&#8221;指定SDK，从而能够使用符合iOS约定的application Identifier。</p><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">依赖管理</p><p style="text-indent: 2em; font-size: 13px;">选定了命令行工具之后, 接下来可以考虑下依赖管理的问题了。我到现在还记得几年前，刚从Ant转到使用Maven的那种爽快的感觉。后来，进入Ruby的世界，其与生俱来的Gem管理系统，也让其依赖管理变得极其简单。 对于iOS平台来说，在做项目时，经常需要使用到各种各样的第三方Framework，这同样需要一个爽快的依赖管理系统，不然的话，各位可以想象一下重复的下载Framework文件，拖入各个Target的Build Phase的Link Binary With Libraries中的场景。这种重复的劳动对于&#8220;懒惰&#8221;的程序员来说，是很难接受的，于是，活跃的社区开发者们提供了这样的一个工具：Cocoapods【7】</p><p style="text-indent: 2em; font-size: 13px;">Cocoapods开始于2011年8月12日，经过2年多的发展，现在已经超过2500次提交，并且持续保持活跃更新，目前已成为iOS领域最流行的第三方依赖管理工具。从技术层面来说，其是一个Ruby Gem，从功能层面来说，其是一个iOS平台下的依赖管理工具，为iOS项目开发提供了类似于在Ruby世界使用Gem的依赖管理体验。</p><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">安装</p><p style="text-indent: 2em; font-size: 13px;">前面提到cocoapods本质上是一个Ruby Gem，因此，其使用前提首先是Ruby开发环境。庆幸的是，Mac下都自带Ruby。这样，只需要简单的2条命令，就可以把cocoapods安装好：</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>$ [sudo] gem install cocoapods<br />$ pod setup</pre></td></tr></tbody></table><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">用法</p><p style="text-indent: 2em; font-size: 13px;">cocoapods的使用方式和使用Ruby Gem非常相似，首先需要在项目根目录下创建文件Podfile,在Podfile中，开发人员只需要按照规则配置好如下内容就好：</p><p style="text-indent: 2em; font-size: 13px;">1.项目支持的平台，版本（iOS/OSX）</p><p style="text-indent: 2em; font-size: 13px;">2.每个target的第三方依赖</p><p style="text-indent: 2em; font-size: 13px;">例子：</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>platform :ios, '6.0'<br />inhibit_all_warnings!<br />xcodeproj `MyProject`<br />pod 'ObjectiveSugar', '~&gt; 0.5'<br />target :test do<br />pod 'OCMock', '~&gt; 2.0.1'<br />end<br />post_install do |installer|<br />installer.project.targets.each do |target|<br />puts "#{target.name}"<br />end<br />end</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">修改好配置文件之后，只需要简单的使用&#8220;pod install&#8221;即可安装好所有的依赖，执行该命令之后，在项目跟目录下会出现&#8220;.xcworkspace&#8221;和&#8220;Pods&#8221;两个目录：</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/2013111114.png" width="700" height="309"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">接下来，开发者需要使用xcworkspace打开项目而不是使用xcodeproject，打开项目之后，在项目目录下除了自己的project以外，还可以看到一个叫做Pods的项目，该项目会为每一个依赖创建一个target：</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/2013111115.png" width="700" height="319"  alt="" /></p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/2013111116.png" width="330" height="344"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">在Podfile中，还可以指定依赖专属于某个Target，</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>target :CocoaPodsTest do<br />pod 'OCMock', '~&gt; 2.0.1'<br />pod 'OCHamcrest'<br />end</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">如果你记不清楚某个依赖库的名称，可以使用&#8220;pod search &lt;name&gt;&#8221;模糊搜索依赖库中的相似库,另外，如果你想使用的库在cocoapods的中央库中找不到，那么，你可以考虑为开源社区做做贡献，把你觉得好用的库添加到中央库中，Cocoapods的官网上有具体的步骤【8】</p><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">原理</p><p style="text-indent: 2em; font-size: 13px;">CocoaPods的原理思想基本上来自于Jonah Williams的博客&#8220;Using Open Source Static Libraries in Xcode 4&#8221;【9】,当使用&#8220;pod install&#8221;安装文件时，cocoapods做了如下这些事：</p><p style="text-indent: 2em; font-size: 13px;">1.创建或者更新当前的workspace</p><p style="text-indent: 2em; font-size: 13px;">2.创建一个新的项目来存放静态库</p><p style="text-indent: 2em; font-size: 13px;">3.把静态库会编译生成的libpods.a文件配置到target的build phase的link with libraries中</p><p style="text-indent: 2em; font-size: 13px;">4.在依赖项目中创建*.xcconfig文件,指定在编译时的一些参数和依赖</p><p style="text-indent: 2em; font-size: 13px;">5.添加一个新的名为&#8220;Copy Pods Resource&#8221;的Build Phase，该build phase会使用"${SRCROOT}/Pods/Pods-CocoaPodsTest-resources.sh"把Pods下的资源文件拷贝到app bundle下。</p><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">注意事项</p><p style="text-indent: 2em; font-size: 13px;">当使用xctool作为命令行工具构建项目时，使用cocoapods管理依赖时，需要做一些额外的配置：</p><p style="text-indent: 2em; font-size: 13px;">1.编辑Scheme，把pods静态库项目作为显式的依赖添加到项目的build中，</p><p style="text-indent: 2em; font-size: 13px;">2.把pods依赖项目拖动到本来的项目之上，表示先编译pods静态库项目，再编译自己的项目。</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/2013111117.png" width="700" height="209"  alt="" /></p><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">（二）&#8212;&#8212;测试框架</p><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">测试框架</p><p style="text-indent: 2em; font-size: 13px;">有了自动化构建和依赖管理之后，开发者可以很轻松的在命令行构建整个项目，但是，作为持续集成平台来说，最重要的还是测试，持续集成最大的好处在于能够尽早发现问题，降低解决问题的成本。而发现问题的手段主要就是测试。在Martin Fowler的Test Pyramid【10】一文中论述了测试金子塔的概念，测试金字塔的概念来自Mike Cohn，在他的书Succeeding With Agile中有详细描述：测试金字塔最底层是单元测试，然后是业务逻辑测试，如果更细化一点的话，可以分为把完整的测试策略分为如下的层级：</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/2013111118.png" width="353" height="215"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">作为持续集成平台，能自动化的测试层级越多，平台就能产生越大的价值。</p><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">Unit Test</p><p style="text-indent: 2em; font-size: 13px;">目前，在iOS领域， 最流行的Unit测试框架有2个：OCUnit【11】和GHunit【12】，这两个框架各有其优缺点：</p><table width="700" border="0" align="center" bgcolor="#999999" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="225" height="25" style="vertical-align: top;">&nbsp;</td><td width="176" height="25" style="vertical-align: top;">优点<br /></td><td width="285" height="25" style="vertical-align: top;">缺点</td></tr><tr bgcolor="#FFFFFF"><td height="25" style="vertical-align: top;">OCUnit</td><td height="25" style="vertical-align: top;">与Xcode无缝集成， 快捷键，Scheme配置都非常方便</td><td height="25" style="vertical-align: top;">1. 只能一次运行整个测试，不能灵活的运行某个测试集; 2.测试结果输出的可读性不好，不容易找到失败的测试</td></tr><tr bgcolor="#FFFFFF"><td height="25" style="vertical-align: top;">GHUnit</td><td height="25" style="vertical-align: top;">1.自带GUI，测试结果清晰可见；2.可以灵活的运行指定的测试；3.开源项目</td><td height="25" style="vertical-align: top;">1.需开发者安装，配置略显复杂；2. 对命令行运行测试的支持不是很好，</td></tr><tr bgcolor="#FFFFFF"><td height="25" style="vertical-align: top;">&nbsp;</td><td height="25" style="vertical-align: top;">&nbsp;</td><td height="25" style="vertical-align: top;">&nbsp;</td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">OCUnit的运行结果会通过弹窗直接告诉开发者，运行的细节信息则会打印在Xcode的输出窗口中：</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/2013111119.png" width="700" height="632"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">GHUnit的运行结果则全部显示在自己的应用界面中，开发者可以在应用中查看所有的信息，以及做运行测试等各种各样的操作。</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111110.png" width="654" height="974"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">关于如何使用OCUnit和GHUnit， InfoQ上有高嘉峻的文章《iOS开发中的单元测试》（http://www.infoq.com/cn/articles/ios-unit-test-1）有详细的介绍，我就不再这儿重复叙述了。</p><p style="text-indent: 2em; font-size: 13px;">如果单从单元测试框架来看，个人更喜欢GHUnit测试结果的可读性和运行测试的灵活性，但是，随着Facebook的xctool的发布，OCUnit华丽丽的逆袭了，因为xctool帮助OCUnit把运行测试的灵活性和测试结果的可读性这两块短板给补齐了，再加上其和Xcode的集成优势以及通过命令行运行的便捷性，让其成为持续集成平台的Unit测试框架的首选。</p><p style="text-indent: 2em; font-size: 13px;">在Java程序员的心中，Junit和Hamcrest永远是一体的，Hamcrest为junit提供了非常丰富的断言机制，极大的增强了测试的可读性。越来越活跃的iOS开发社区，当然不会让Object-C的世界缺失这样一个优秀的框架，于是OCHamcrest【13】诞生了。</p><p style="text-indent: 2em; font-size: 13px;">在测试项目中使用OCHamcrest非常简单，尤其是使用了cocoapods管理依赖的项目。只需要在Podfile文件中加上：</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>target :&lt;TestTargetName&gt; do<br />    ...<br />pod 'OCHamcrest'<br />end</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">然后，运行&#8220;pod install&#8221;命令安装Hamcrest到测试Target，安装好之后，为了在测试类中使用OCHamcrest的断言。还需要在测试类的头文件中加入如下代码：</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>#define HC_SHORTHAND<br />#import&lt;OCHamcrest/OCHamcrest.h&gt;</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">开发者可以把这段代码加入&lt;TestTargetName&gt;-prefix.pch中，这样所有的测试类就都可以使用OCHamcrest的断言了。在前面提到的高嘉峻的文章中的第二部分更加详细的讲解了OCHamcrest的断言，以及其和另一个断言框架Expecta的对比，感兴趣的同学可以跳过去看看。</p><p style="text-indent: 20pt; font-size: 14px; line-height: 18px; font-weight: bold;">Component Test &amp; Integration Test</p><p style="text-indent: 2em; font-size: 13px;">在开发手机应用时，总难免会和其他的系统集成，尤其当开发的应用是某个系统的手机客户端时，这样就涉及到很多第三方API的集成点需要测试，在成熟的Java世界中，诞生了EasyMock，Mockito，moco等针对这种集成点的测试工具。同样的，活跃的社区力量正一步一步的在让Object-C世界成熟，OCMock【14】诞生。</p><p style="text-indent: 20pt; font-size: 14px; line-height: 18px; font-weight: bold;">OCMock</p><p style="text-indent: 2em; font-size: 13px;">有了cocoaPods，新加框架变得非常容易，基本上就是&#8220;哪里没有加哪里&#8221;的节奏，添加OCMock框架，只需要在Podfile文件中加上：</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>target :&lt;TestTargetName&gt; do<br />    ...<br />pod 'OCMock', '~&gt; 2.0.1'<br />end</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">然后，运行&#8220;pod install&#8221;命令安装OCMock到测试Target，同样的，需要把OCmock的头文件添加&lt;TestTargetName&gt;-prefix.pch文件中</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>#import&lt;OCMock/OCMock.h&gt;</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">下面是一个简单的使用OCMock的例子，更多的用法请参考OCMock的官网：http://ocmock.org/features/：</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>- (void)testSimpeMockPass{<br />idmockObject = [OCMockObjectmockForClass:NSString.class];<br />    [[[mockObject stub] andReturn:@"test"] lowercaseString];</pre><p style="text-indent: 2em; font-size: 13px;">NSString * returnValue = [mockObjectlowercaseString];<br />assertThat(returnValue, equalTo(@"test"));<br />}</p></td></tr></tbody></table><p style="text-indent: 20pt; font-size: 14px; line-height: 18px; font-weight: bold;">moco</p><p style="text-indent: 2em; font-size: 13px;">moco【15】以其对系统集成点测试的贡献荣获了2013年的&#8220;Duke's Choice Award&#8221;奖，虽然其以Java写成，主要的生态系统也是围绕Java打造，但是，其Standalone模式可以非常方便的构造一个开发者期望的服务器，这对于Mobile领域的集成点测试来说，本就是一个非常好的Mock服务器的工具。Moco有如下的特点：</p><p style="text-indent: 2em; font-size: 13px;">易于配置，使用：一个Json配置文件，然后&#8220;java -jar moco-runner--standalone.jar -p 8080 ***.json&#8221;就可以启动一个Mock服务器。该服务器的所有行为都在配置文件里。如果你想添加，修改服务器行为，只需要修改一下配置文件，然后重新启动该服务器就行了。</p><p style="text-indent: 2em; font-size: 13px;">配置文件可读性好，使用Json格式的配置文件，对绝大多数开发者来说都可以很容易理解。</p><p style="text-indent: 2em; font-size: 13px;">支持模拟客户端需要的所有http操作，moco实现了针对请求Content、URI、Query Parameter、Http Method、Header、Xpath的模拟。对响应的格式支持有Content、Status Code、Header、URL、甚至支持Sequence请求，即根据对同一请求的调用次数返回不同的结果。</p><p style="text-indent: 2em; font-size: 13px;">完全开源，代码不多也比较易懂，如果没有覆盖到我们的场景，完全可以在该项目基础上实现一个自己的Mock服务器 。</p><p style="text-indent: 2em; font-size: 13px;">熊节在infoQ上发表的《企业系统集成点测试策略》【16】一文中，详细的论述了在企业系统中，moco对测试系统集成点的 帮助。这些论点在Mobile开发领域同样适用，因此合理的使用moco可以帮助iOS开发者更加容易的构建一个稳固的持续集成平台。</p><p style="text-indent: 20pt; font-size: 14px; line-height: 18px; font-weight: bold;">System Test</p><p style="text-indent: 2em; font-size: 13px;">对于iOS的系统（UI）测试来说，比较知名的工具有UIAutomation【17】和FonMonkey【18】。</p><p style="text-indent: 20pt; font-size: 14px; line-height: 18px; font-weight: bold;">UIAutomation</p><p style="text-indent: 2em; font-size: 13px;">UIAutomation是随着iOS SDK 4.0引入，帮助开发者在真实设备和模拟器上执行自动化的UI测试。其本质上是一个Javascript的类库，通过 界面上的标签和值的访问性来获得UI元素，完成相应的交互操作，从而达到测试的目的，类似于Web世界的Selenium。</p><p style="text-indent: 2em; font-size: 13px;">通过上面的描述，可以得知，使用UIAutomation做测试时，开发者必须掌握两件事：</p><p style="text-indent: 2em; font-size: 13px;">1.如何找到界面上的一个UI元素</p><p style="text-indent: 2em; font-size: 13px;">2.如何指定针对一个UI元素的操作</p><p style="text-indent: 2em; font-size: 13px;">在UIAutomation中，界面就是由一堆UI元素构建的层级结构，所有UI元素都继承对象UIAElement ，该对象提供了每个UI元素必须具备的一些属性：</p><p style="text-indent: 2em; font-size: 13px;">1.name</p><p style="text-indent: 2em; font-size: 13px;">2.value</p><p style="text-indent: 2em; font-size: 13px;">3.elements</p><p style="text-indent: 2em; font-size: 13px;">4.parent</p><p style="text-indent: 2em; font-size: 13px;">5.&#8230;</p><p style="text-indent: 2em; font-size: 13px;">而整个界面的层级结构如下：</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>Target（设备级别的UI，用于支持晃动，屏幕方向变动等操作）<br />    Application（设备上的应用，比方说Status Bar，keyboard等）<br />      Main window（应用的界面，比方说导航条）<br />        View（界面下的View，比方说UITableView）<br />           Element（View下的一个元素）<br />              Child element(元素下的一个子元素)</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">下面是一个访问到Child element的例子：</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>UIATarget.localTarget().HamcrestDemo().tableViews()[0].cells()[0].elements()</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">开发者还可以通过&#8220;UIATarget.localTarget().logElementTree()&#8221;在控制台打印出该target下所有的的elements。</p><p style="text-indent: 2em; font-size: 13px;">找到UI元素之后，开发者可以基于该UI元素做期望的操作，UIAutomation作为原生的UI测试框架，基本上支持iOS上的所有UI元素和操作，比方说：</p><p style="text-indent: 2em; font-size: 13px;">1.点击按钮，例: ***.buttons[&#8220;add&#8221;].tap()</p><p style="text-indent: 2em; font-size: 13px;">2.输入文本, 例:***.textfields[0].setValue(&#8220;new&#8221;)</p><p style="text-indent: 2em; font-size: 13px;">3.滚动屏幕，例:***.scrollToElementWithPredicate(&#8220;name begin with &#8217;test&#8217;&#8221;)</p><p style="text-indent: 2em; font-size: 13px;">4.&#8230;&#8230;</p><p style="text-indent: 2em; font-size: 13px;">关于使用UIAutomation做UI测试，推荐大家一定要看一下2010的WWDC的Session 306：Automating User Interface Testing with Instruments【19】。 另外，这儿还有一篇很好的博客，详细的讲解了如何使用UIAutomation做UI自动化测试：http://blog.manbolo.com/2012/04/08/ios-automated-tests-with-uiautomation</p><p style="text-indent: 2em; font-size: 13px;">Apple通过Instruments为UIAutomation测试用例的命令行运行提供了支持，这样就为UIAutomation和CI服务器的集成提供了便利。开发者可以通过如下的步骤在命令行中运行UIAutomation测试脚本</p><p style="text-indent: 2em; font-size: 13px;">指定目标设备，构建被测应用，该应用会被安装到指定的DSTROOT目录下</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>xcodebuild<br />-project "/Users/twer/Documents/xcodeworkspace/AudioDemo/AudioDemo.xcodeproj" <br />-schemeAudioDemo<br />-sdk iphonesimulator6.1 <br />-configuration Release SYMROOT="/Users/twer/Documents/xcodeworkspace/<br />AudioDemo/build" DSTROOT="/Users/twer/Documents/xcodeworkspace/AudioDemo/<br />build" TARGETED_DEVICE_FAMILY="1" <br />install</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">启动Instruments，基于第一步生成的应用运行UIAutomation测试</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>instruments<br />-t  "/Applications/Xcode.app/Contents/Applications/Instruments.app/<br />Contents/PlugIns/AutomationInstrument.bundle/Contents/Resources/<br />Automation.tracetemplate" "/Users/twer/Documents/xcodeworkspace/AudioDemo<br />/build/Applications/TestExample.app"<br />-e UIASCRIPT &lt;absolute_path_to_the_test_file&gt;</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">为了更好的展示测试效果以及与CI服务器集成，活跃的社区开发者们还尝试把UIAutomation和Jasmine集成: https://github.com/shaune/jasmine-ios-acceptance-tests</p><p style="text-indent: 2em; font-size: 13px;">UIAutomation因其原生支持，并且通过和Instruments的绝佳配合，开发者可以非常方便的使用录制操作自动生成测试脚本，赢得了很多开发者的支持，但是因苹果公司的基因，其系统非常封闭，导致开发者难以扩展，于是活跃的社区开发者们开始制造自己的轮子，Fone Monkey就是其中的一个优秀成果。</p><p style="text-indent: 20pt; font-size: 14px; line-height: 18px; font-weight: bold;">Fone Monkey</p><p style="text-indent: 2em; font-size: 13px;">Fone Monkey是由Gorilla Logic 公司创建并维护的一个iOS自动化测试工具，其功能和UIAutomation差不多，但是由于其开源特性，极大的解放了活跃开发者的生产力，开发者可以很容易的根据自身需要扩展其功能。</p><p style="text-indent: 2em; font-size: 13px;">Fone Monkey的安装虽然简单，但是比UIAutomation的原生支持来说，也算是一大劣势了，具体的安装过程可以参考：http://www.gorillalogic.com/fonemonkey-ios/fonemonkey-setup-guide/add-fonemonkey-your-xcode-project</p><p style="text-indent: 2em; font-size: 13px;">Fone Monkey的使用方式主要就是录制/回放，也可以把录制好的测试用例保存为脚本以其他方式运行。安装好Fone Monkey启动测试以后，应用界面会有点变化：</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111111.png" width="700" height="756"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">开发者通过点击Record按钮录制操作，点击Play按钮播放之前录制的操作，点击More按钮可以添加一些针对元素的验证， 这样就形成了一个测试用例。</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111112.png" width="638" height="1212"  alt="" /></p><p style="text-indent: 20pt; font-size: 14px; line-height: 18px; font-weight: bold;">在Fone Monkey中录制的测试用例可以保存为3种格式，以支持多种运行方式：</p><p style="text-indent: 2em; font-size: 13px;">1.scriptName.fm：用于支持在Fone Monkey的窗口中运行测试</p><p style="text-indent: 2em; font-size: 13px;">2.scriptName.m：用于和Xcode的OCUnit test 集成，可以以OCUnit的测试用例的形式运行UI测试，这就让UI具备了命令行运行和与CI集成的能力。</p><p style="text-indent: 2em; font-size: 13px;">3.scriptName.js：UIAutomation的格式，用于支持在Instruments中，以UIAutomation的形式运行测试。</p><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">（三）&#8212;&#8212;CI服务器与自动化部署</p><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">CI服务器</p><p style="text-indent: 2em; font-size: 13px;">写到这儿，对于iOS开发者来说，需要准备好：</p><p style="text-indent: 2em; font-size: 13px;">一个比较容易获取的源代码仓库(包含源代码)<br />一套自动化构建脚本<br />一系列围绕构建的可执行测试<br />接下来就需要一个CI服务器来根据源代码的变更触发构建，监控测试结果。目前，业界比较流行的，支持iOS构建的CI服务器有Travis CI和Jenkins</p><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">Travis CI</p><p style="text-indent: 2em; font-size: 13px;">Travis CI【20】是一个免费的云服务平台，主要功能就是为开源社区提供免费的CI服务，对于商业用户可以使用Travis Pro版本，其基本上支持所有目前主流的语言，Object-C自然也在其中。但是，Travis CI只支持github极大的限制了其应用场景。但是也由于其只支持github，其把和github的集成做到了极致的平滑，易用，因此，对于本就把github作为代码托管平台的项目来说，Travis CI可以做为第一选择。</p><p style="text-indent: 2em; font-size: 13px;">使用Travis CI只需要简单的2步即可为你托管在github的项目增加一个CI服务器</p><p style="text-indent: 2em; font-size: 13px;">第一步：在项目的根目录下创建travis CI配置文件&#8220;.travis.yml&#8221;，在配置文件指定语言，环境要求，构建脚本等</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>language: objective-c<br />before_install:<br />     - brew update<br />     - brew install xctool<br />script: xctool -project LighterViewControllerDemo.xcodeproj -scheme <br />LighterViewControllerDemo -sdkiphonesimulator  test</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">第二步：使用github账号登陆Travis CI，在账户的repositories开启该项目的自动构建功能，该设置会在github上该项目repository中开启对Travis CI的Service Hook</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111113.png" width="700" height="238"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">下图就是我的一个iOS项目在Travis CI的构建记录：</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111114.png" width="700" height="328"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">除此之外，Travis CI还非常贴心的提供了一个指示灯，可以让开发者在自己的repository展示构建状态。使用指示灯的方法很简单，只需要在repository的README.md中添加下面这行代码就行了。</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>[![Build Status](https://travis-ci.org/xianlinbox/iOSCIDemo.png)](https://travis-ci.<br />org/xianlinbox/iOSCIDemo)</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">效果如下：</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111115.png" width="500" height="210"  alt="" /></p><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">Jenkins</p><p style="text-indent: 2em; font-size: 13px;">Jenkins【21】经过多年的发展，其活跃的社区和丰富的插件让其成为了业界最受欢迎的CI服务器。通过使用Xcode插件，可以非常方便在Jenkins中运行iOS项目的构建脚本。</p><p style="text-indent: 20pt; font-size: 14px; line-height: 18px; font-weight: bold;">安装</p><p style="text-indent: 2em; font-size: 13px;">Jenkins的安装非常简单，尤其是在Mac环境下使用Homebrew安装，只需要简单的使用&#8220;brew install jenkins&#8221;,即可成功安装，这个安装过程做的事情非常简单，就是把对应版本的jenkins.war文件下载到对应的目录&#8220;/usr/local/Cellar/jenkins/1.524/libexec/&#8221;。因此，如果没有Homebrew，可以直接到官网下载安装文件，自己安装。</p><p style="text-indent: 2em; font-size: 13px;">配置安装完之后，只需要使用&#8220;java -jar */jenkins.war&#8221;即可启动Jenkins，开发者可以自己创建一个bash alias简化输入，在用户目录下的.bashrc文件中添加如下代码</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>aliasjenkins='java -jar /Applications/Jenkins/jenkins.war'</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">启动Jenkins之后，可以通过浏览器访问http://localhost:8080查看Jenkins界面。</p><p style="text-indent: 2em; font-size: 13px;">然后，开发者可以到Manage Plugins界面，安装需要的插件：Xcode Plugin，Git Plugin，Github Plugin（我使用git做源代码管理），Cocoapods Plugin。安装好插件之后，需要重启Jenkins，一切就绪之后，开始配置自己的iOS构建过程。</p><p style="text-indent: 2em; font-size: 13px;">在Jenkins中配置一个iOS Job的步骤如下：</p><p style="text-indent: 2em; font-size: 13px;">1.新建Job，Job类型选择&#8220;Build a free-style software project&#8221;。</p><p style="text-indent: 2em; font-size: 13px;">2.配置代码仓库，</p><p style="text-indent: 2em; font-size: 13px;">3.点击&#8220;Add build step&#8221;添加构建步骤，如果已安装Xcode插件，则可以在Step类型中看到Xcode选项:</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111116.png" width="452" height="224"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">选择Xcode，可以看到Xcode构建step的所有配置选项:</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111117.png" width="700" height="462"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">4.点击&#8220;Add build step&#8221;添加测试步骤,选择&#8220;Execute shell&#8221;选项，然后，添加脚本,执行测试并生成期望的Report, 可以重复本步骤添加&#8220;Acceptaince Test&#8221;等构建步骤。</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>path-to/xctool.sh <br />-workspaceAudioDemo.xcworkspace  -scheme AudioDemo  -sdkiphonesimulator <br />-reporter junit:test-reports/junit-report.xml clean test</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">5.点击&#8220;Add post-build action&#8221;添加一个新的步骤，选择&#8220;publish Junit test result report&#8221;，把测试报告展示在Jenkins中。</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111118.png" width="700" height="85"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">配置好之后，可以点击Build Now运行Job，下图是在Jenkins中运行iOS构建 Job的结果图：</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111119.png" width="700" height="395"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">开发者可以点击每次的构建，查看具体的构建信息及测试结果：</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111120.png" width="700" height="284"  alt="" /></p><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">常见问题</p><p style="text-indent: 2em; font-size: 13px;">启动Jenkins提示运行&#8220;java&#8221;命令需要X11支持，</p><p style="text-indent: 2em; font-size: 13px;">解决方法：这是因为在OS X Mountain Lion系统中不再内置X11，当需要使用X11时，可通过安装XQuartz project得到支持，具体信息：http://support.apple.com/kb/HT5293</p><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">自动化部署</p><p style="text-indent: 2em; font-size: 13px;">这儿的想谈的&#8220;部署&#8221;不是传统意义上的直接部署到产品环境的部署，而是指如何把最新版本的应用快速的部署到测试用户的机器上以收集反馈，或者做一些探索性的测试。</p><p style="text-indent: 2em; font-size: 13px;">在我写第一个iOS应用的时候，我想把应用安装到多个机器上测试的时候，需要非常繁琐的步骤：</p><p style="text-indent: 2em; font-size: 13px;">1.需要申请到苹果开发者账号，获得开发者证书。</p><p style="text-indent: 2em; font-size: 13px;">2.需要在苹果的开发者网站上注册我想使用的设备。</p><p style="text-indent: 2em; font-size: 13px;">3.使用开发者证书打包应用，使用Ad-HOC部署模式，生成ipa文件。</p><p style="text-indent: 2em; font-size: 13px;">4.通过ipa文件把应用安装到iTunes上。</p><p style="text-indent: 2em; font-size: 13px;">5.通过iTunes把应用同步到多台测试机器上。</p><p style="text-indent: 2em; font-size: 13px;">如果是测试机器在多个地理位置的时候，还需要把ipa文件发送到对应的地点，每个地点都需要重复的做第4，5步。 这样一个繁琐，且低效的过程让开发者非常痛苦，直到TestFlight的出现。</p><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">TestFlight</p><p style="text-indent: 2em; font-size: 13px;">TestFlight【22】就是一个专门解决上面提到的痛点的云服务方案，它可以帮助开发者：</p><p style="text-indent: 2em; font-size: 13px;">1.轻松采集测试用户的UDID和iOS 版本、硬件版本，并发送给开发者。</p><p style="text-indent: 2em; font-size: 13px;">2.实时反馈应用是否成功安装到测试机器</p><p style="text-indent: 2em; font-size: 13px;">3.轻松部署最新版本应用到测试用机上。</p><p style="text-indent: 2em; font-size: 13px;">4.开发者可以灵活选择部署哪个版本到哪部分测试机器上。</p><p style="text-indent: 2em; font-size: 13px;">使用使用Test Flight服务非常简单，只需要到Test Flight注册一个账号。然后把链接发送给测试设备，测试设备只要打开该链接，并授权给Test Flight，在Test Flight的设备中心就可以看到这些设备。</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111121.png" width="700" height="169"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">而测试设备上，则会多一个Test Flight的应用。</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111122.png" width="128" height="128"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">当应用有了新的测试包之后，只需要将IPA上传到TestFlight网站，然后勾选合适的测试用户或者合适的设备，点击Update &amp; Notify。</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111123.png" width="700" height="496"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">TestFlight会向对应的测试设备发送更新通知，测试用户只需在测试设备上打开TestFlight应用，点击Install，TestFlight就会自动将新版本的IPA文件安装到测试设备上。</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111124.png" width="680" height="552"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">另外，TestFlight还提供了Upload API，这样就等于提供了和CI服务器集成的能力。其Upload API非常简单，就是一个简单的，带有指定参数的HTTP POST请求，具体细节可参考官网：https://www.testflightapp.com/api/doc/。</p><p style="text-indent: 2em; font-size: 13px;">在 CI服务器中，开发者可以在构建过程中，添加步骤通过upload API把通过测试的ipa文件自动上传到TestFlight上，从而达到持续部署的目的。而像Jenkins这样有丰富插件机制的CI服务器， 活跃的社区开发者们早为其开发了十分便于使用的TestFlight的插件。</p><p style="text-indent: 2em; font-size: 13px;">在Jenkins中使用TestFlight插件也非常简单，安装好插件，重启Jenkins，然后在项目的构建过程配置页面的Post-build Actions中，点击add post-build action，可以看到Upload to Testflight选项:</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111125.png" width="514" height="328"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">选择之后，可以在页面上看到TestFlight的配置项：</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111126.png" width="700" height="213"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">为了增强安全性，该插件把Token的设置移到了Jenkins的Global Setting界面：</p><p align="center" style="text-indent: 2em; font-size: 13px;"><img src="http://www.uml.org.cn/jchgj/images/20131111127.png" width="700" height="122"  alt="" /></p><p style="text-indent: 2em; font-size: 13px;">配置好Token Pair之后，在在TestFlight的配置项 上选择相应的pair即可，设置想要的参数，保存即可。</p><p style="text-indent: 2em; font-size: 13px;">你如果不喜欢使用插件或者说使用的其它CI服务器的话，可以通过添加一个Execute shell步骤，直接通过代码上传构建好的ipa文件：</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>curl http://testflightapp.com/api/builds.json      <br />-F file=@testflightapp.ipa<br />-F dsym=@testflightapp.app.dSYM.zip     <br />-F api_token='your_api_token'      <br />-F team_token='your_team_token'      <br />-F notes='This build was uploaded via the upload API'      <br />-F notify=True      <br />-F distribution_lists='Internal, QA'</pre></td></tr></tbody></table><p style="text-indent: 20pt; font-size: 18px; font-weight: bold;">结语</p><p style="text-indent: 2em; font-size: 13px;">《持续集成》一书中引用了Javaranch.com的创始人Kathy Sierra的一句话：</p><table width="700" border="0" align="center" cellpadding="7" cellspacing="1" bgcolor="#CCCCCC" style="color: #000000; font-size: 12px; line-height: 20px;"><tbody><tr bgcolor="#FFFFFF"><td width="694" height="30" bgcolor="#f5f5f5"><pre>There's a big difference between saying, "Eat an apple a day" and actually eating the apple</pre></td></tr></tbody></table><p style="text-indent: 2em; font-size: 13px;">正所谓知易行难，您几乎很难听到开发者说：&#8220;持续集成毫无价值&#8221;，但是，构建一个持续集成平台并非易事，希望本文中介绍的iOS应用的构建过程，以及在构建过程的各个阶段可以使用的一些优秀的类库，服务，能够让iOS开发者们在想搭建一个持续集成平台时有所参考，从而能够更加坚定，且容易的为自己的项目搭建一个持续集成平台。</p></td></tr></tbody></table><table width="95%" border="0" align="center" cellpadding="1" cellspacing="1"><tbody><tr><td width="34%" height="30" valign="top"></td><td height="30" valign="top"></td></tr></tbody></table></td></tr></tbody></table></td></tr></tbody></table><img src ="http://www.blogjava.net/xiaomage234/aggbug/419174.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-10-29 16:52 <a href="http://www.blogjava.net/xiaomage234/archive/2014/10/29/419174.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>让构建和测试变得更轻松：xctool</title><link>http://www.blogjava.net/xiaomage234/archive/2014/10/29/419173.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Wed, 29 Oct 2014 08:38:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/10/29/419173.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/419173.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/10/29/419173.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/419173.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/419173.html</trackback:ping><description><![CDATA[<div style="margin: 0px; border: 0px; font-family: Vollkorn, Georgia, Times, 'Times New Roman', serif; font-stretch: inherit; line-height: 34px; font-size: 20px; vertical-align: baseline; color: #222222; background-color: #fafafa;"><blockquote style="margin: 0px 0px 1.5em; padding: 0px 0px 0px 1.5em; border-width: 0px 0px 0px 4px; border-left-color: rgba(170, 170, 170, 0.498039); font-style: italic; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: 1.5em; font-size: 1.2em; vertical-align: baseline; quotes: none; position: relative;"><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">控制了一门语言的构建系统（build system），就控制了这门语言的命运，以及它的生态和社区。</p></blockquote><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">Objective-C 用很短的时间，取得了非常大的变化。在短短几年间，这门语言从 NeXT 的&#8220;废墟&#8221;中走出，成为<a href="http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">颇具影响力</a>的一门语言。开源社区对于 Objective-C 有着巨大的贡献，其中一个很重要的方面是：开发工具。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">例如&nbsp;<a href="http://cocoapods.org/" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">CocoaPods</a>，它充分证明了科技和社区结合的威力。两年间，有超过 2700 个开源的库或框架被添加进去，你只需要简单的命令行 -&nbsp;<code style="margin: -1px 0px; padding: 0px 0.3em; border: 0px; font-family: Menlo, Monaco, 'Andale Mono', 'lucida console', 'Courier New', monospace; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: 1.5em; font-size: 0.8em; vertical-align: baseline; display: inline-block; color: #555555;">pod install</code>，就可以轻松管理第三方库。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">开源社区对于 iOS 和 Mac OS X 开发的各个方面都有着巨大贡献，第三方库管理只是其中一个，其他方面还包括<a href="http://nomad-cli.com/" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">自动配置和分发</a>、<a href="http://www.quickradar.com/" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">报告BUG</a>、<a href="http://cocoadocs.org/" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">文档检索</a>等。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">但是本周，我们聚焦于这样一个工具：它重新定义了构建过程，是新一代开发集成的基础&#8212;&#8212;xctool。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;"><a href="https://github.com/facebook/xctool" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">xctool</a>&nbsp;是&nbsp;<a href="https://github.com/fpotter" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">Fred Potter</a>&nbsp;的开源项目，来自于他在 Facebook 工作中创建的自动构建系统。xctool 用于替换 Xcode.app 中的&nbsp;<a href="https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/xcodebuild.1.html" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">xcodebuild</a>。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">在 Xcode 中点击&#8220;Build &amp; Run&#8221;，所有的 project、build target 和 scheme settings 都被传到 xcodebuild，xcodebuild 调用构建的命令行，然后执行 .ipa 文件运行在真机或模拟器上。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">这个过程我们只能祈祷它顺利了，因为 Xcode 将自己的构建系统封闭起来，我们从外部很难访问和控制。当我们试图通过 Terminal.app 和 xcodebuild 交互的时候，会发现真的很难用。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">与其使用上个时代的工具，狂打断点去遍历所有错误，不如让 xctool 来告诉你什么是现代的解决方案。</p><h3>美学和风格</h3><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">xctool 给人的第一印象是它那漂亮、彩色的输出样式。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;"><img src="http://yangfei.me/images/2013-11-06-pic-0.gif" style="margin: 0px; padding: 0px; border: 0.5em solid #ffffff; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; max-width: 100%; height: auto; border-top-left-radius: 0.3em; border-top-right-radius: 0.3em; border-bottom-right-radius: 0.3em; border-bottom-left-radius: 0.3em; -webkit-box-shadow: rgba(0, 0, 0, 0.14902) 0px 1px 4px; box-shadow: rgba(0, 0, 0, 0.14902) 0px 1px 4px; box-sizing: border-box;"  alt="" /></p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">我们自己作为苹果硬件和软件的用户，对设计绝对不会轻视。xctool 也是。 它把构建过程的每一步都组织的很整洁，通过 ANSI 标准色 和 Unicode 符号输出易懂、易读的报告。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">但是 xctool 的美丽不仅是外在，build 的过程中可以生成用其他工具可读的报告：</p><figure style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; -webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none;"><div style="margin: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; overflow-y: hidden; overflow-x: auto; border: 1px solid #05232b !important; background: #212c3b !important;"><table style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-size: 20px; vertical-align: baseline; border-collapse: collapse; border-spacing: 0px;"><tbody style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;"><tr style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;"><td style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-stretch: inherit; line-height: inherit; vertical-align: middle; width: 342px;"><pre style="margin-top: 0px; margin-bottom: 0px; padding: 0px; border: none; font-family: Menlo, Monaco, 'Andale Mono', 'lucida console', 'Courier New', monospace; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: 1.45em; font-size: 13px; vertical-align: baseline; -webkit-box-shadow: none; box-shadow: none; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; color: #93a1a1; overflow: auto; background: none;"><code style="margin: 0px; padding: 0.8em; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: 1.45em; vertical-align: baseline; overflow-y: hidden; display: block; overflow-x: auto; font-family: Menlo, Monaco, 'Andale Mono', 'lucida console', 'Courier New', monospace !important; background-image: initial !important; background-attachment: initial !important; background-size: initial !important; background-origin: initial !important; background-clip: initial !important; background-position: initial !important; background-repeat: initial !important;"><span style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-variant: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">  xctool -reporter plain:output.txt build</span></code></pre></td></tr></tbody></table></div></figure><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">报告类型：</p><ul style="margin: 0px 0px 1.5em 2em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; list-style-position: initial; list-style-image: initial;"><li style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">pretty：（默认）输出样式使用 ANSI 标准色和 Unicode 符号</li><li style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">plain：类似 pretty，但没有 ANSI 标准色和 Unicode 符号</li><li style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">phabricator：将构建/测试的结果输出为 JSON 数组，可导入到&nbsp;<a href="http://phabricator.org/" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">Phabricator</a>&nbsp;这个 code-review 工具</li><li style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">junit：生成兼容&nbsp;<a href="http://junit.org/" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">JUnit</a>/<a href="http://xunit.codeplex.com/" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">xUnit</a>&nbsp;的 XML 格式的测试结果</li><li style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">json-stream：输出构建/测试的事件流 （ JSON 字典格式），一行一个（如图）</li><li style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">json-compilation-database：输出&nbsp;<a href="http://clang.llvm.org/docs/JSONCompilationDatabase.html" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">JSON Compilation Database</a>，可用于基于&nbsp;<a href="http://clang.llvm.org/docs/LibTooling.html" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">Clang Tooling</a>&nbsp;的工具，如&nbsp;<a href="http://oclint.org/" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">OCLint</a></li></ul><h3>集成构建系统</h3><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">相对于 xcodebuild，xctool 另一个重大改进是可以和 Xcode.app 一样运行测试（xcodebuild 并不能分辨哪些 target 是 test target，从而单独运行它们）。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">单单这个原因，对于 Objective-C 社区的持续集成测试这个领域，xctool 就有非常大的意义。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">Travis CI</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;"><a href="https://travis-ci.org/" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">Travis CI</a>&nbsp;为开源项目提供免费的持续集成服务（商业项目收费），支持 Objective-C。它可以在你每次提交到 GitHub 时自动运行你的测试代码，如果最新的提交导致构建失败它会通知你。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">在你的 Objective-C 项目中添加 Travis CI，你需要<a href="http://about.travis-ci.org/docs/user/getting-started/" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">创建账号绑定 GitHub</a>，然后在你的 repo 中添加 .travis.yml 文件：</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">.travis.yml</p><figure style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; -webkit-box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; box-shadow: rgba(0, 0, 0, 0.0588235) 0px 0px 10px; background: none;"><div style="margin: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; overflow-y: hidden; overflow-x: auto; border: 1px solid #05232b !important; background: #212c3b !important;"><table style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-size: 20px; vertical-align: baseline; border-collapse: collapse; border-spacing: 0px;"><tbody style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;"><tr style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;"><td style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-stretch: inherit; line-height: inherit; vertical-align: middle; width: 507px;"><pre style="margin-top: 0px; margin-bottom: 0px; padding: 0px; border: none; font-family: Menlo, Monaco, 'Andale Mono', 'lucida console', 'Courier New', monospace; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: 1.45em; font-size: 13px; vertical-align: baseline; -webkit-box-shadow: none; box-shadow: none; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; color: #93a1a1; overflow: auto; background: none;"><code style="margin: 0px; padding: 0.8em; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: 1.45em; vertical-align: baseline; overflow-y: hidden; display: block; overflow-x: auto; font-family: Menlo, Monaco, 'Andale Mono', 'lucida console', 'Courier New', monospace !important; background-image: initial !important; background-attachment: initial !important; background-size: initial !important; background-origin: initial !important; background-clip: initial !important; background-position: initial !important; background-repeat: initial !important;"><span style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-variant: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">language: objective-c </span><span style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-variant: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">before_install: </span><span style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-variant: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">    - brew update </span><span style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-variant: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">    - brew install xctool </span><span style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-variant: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">script: xctool -workspace MyApp.xcworkspace -scheme MyApp test</span></code></pre></td></tr></tbody></table></div></figure><h3>OCLint</h3><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;"><a href="http://oclint.org/" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">OCLint</a>&nbsp;是一个静态代码分析器，可以检测 Objective-C 代码（同时支持 C 和 C++），发现常见的问题：例如 if/else/try/catch/finally 声明出错、未被使用的本地实例和参数、过度复杂（有效代码行数 和&nbsp;<a href="http://zh.wikipedia.org/wiki/%E5%9C%88%E8%A4%87%E9%9B%9C%E5%BA%A6" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">循环复杂度</a>太高）、冗余代码、<a href="http://zh.wikipedia.org/wiki/%E4%BB%A3%E7%A0%81%E5%BC%82%E5%91%B3" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">代码异味</a>、以及其他不好的代码。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">还记得 xctool 的 json-compilation-database 格式吧，这种格式可以<a href="http://docs.oclint.org/en/dev/guide/xctool.html" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">被 OCLint 直接读取</a>，进而进行神奇的静态分析。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">在我写这篇文章的时候，离构建系统集成被广泛接受还有很长的路，但我的希望是，既然已经开始， 大家就应该齐心协力，让这个有前途的工具变得更加的强大。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">这就像一座城市，随着人口的增长，基础设施就需要改变。通过各种各样的方式，通过本地政府、新兴组织，或者其他。总之，环境需要改变，以适应人口的增长。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">Objective-C 已经并且还将随着 iOS 设备的流行而快速进化。为更多新进开发者提供必要的基础设施是社区的责任，当然这离不开与苹果的协作（有时是反对或抗议）。我们在这方面做得如何，决定了我们是否真正理解并传达了作为专业开发者应当扮演的角色，以及应当的承担责任。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">我们是该成为平庸的业余者，还是该成为改善技术的关键角色？</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">xctool，和社区的其他工具一样，为这门语言的未来和生态，提供了希望和灵感。让我们继续创造这样强大的工具，创造我们为之自豪的开发体验。</p><p style="margin: 0px 0px 1.5em; padding: 0px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;"><em style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline;">注：本文译自&nbsp;<a href="http://nshipster.com/xctool/" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word;">NSHipster</a></em></p></div><footer style="margin: 2em 0px 0px; padding: 0px 0px 1em; border: 0px; font-family: Cabin, 'Helvetica Neue', Arial, sans-serif; font-stretch: inherit; line-height: 34px; font-size: 20px; vertical-align: baseline; color: #222222; background-color: #fafafa;"><p style="margin: 0px 0px 0.8em; padding: 0px; border: 0px; font-family: Vollkorn, Georgia, Times, 'Times New Roman', serif; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-size: 0.85em; vertical-align: baseline; clear: both; overflow: hidden;"><a left"="" href="http://yangfei.me/blog/idevweekly/" title="Previous Post: iDev Weekly" style="margin: 0px 1.5em 0.8em 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; vertical-align: baseline; color: #1863a1; -webkit-transition: color 0.3s; transition: color 0.3s; white-space: pre-wrap; word-wrap: break-word; float: left;">&#171; iDev Weekly</a></p></footer><img src ="http://www.blogjava.net/xiaomage234/aggbug/419173.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-10-29 16:38 <a href="http://www.blogjava.net/xiaomage234/archive/2014/10/29/419173.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>安卓应用程序插件化开发框架 -AAP Framework【转】</title><link>http://www.blogjava.net/xiaomage234/archive/2014/10/28/419113.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 28 Oct 2014 03:21:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/10/28/419113.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/419113.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/10/28/419113.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/419113.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/419113.html</trackback:ping><description><![CDATA[from:http://code.google.com/p/android-application-plug-ins-frame-work/<br /><h1>介绍</h1><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;">这个框架的初衷，是为了方便让程序模块化、插件化，将一个apk应用拆分为多个apk。</blockquote><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;">不明白这个插件化、模块化是怎么回事的话，可以看看腾讯微信的安卓客户端中的插件配置。</blockquote><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;">在这里我会以腾讯微信为例，如何使用这个框架。 (<strong>腾讯微信并不是真正的插件化，它是伪的，插件并非与它的主程序分离开，结果就是每次插件的更新，都必须以整个程序的更新为代价</strong>)</blockquote><h1><a name="都能干啥"></a>都能干啥</h1><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;">框架的思想，主要是通过apk清单文件中的sharedUserId属性来吧多个apk融合为单一的dalvik虚拟机，也就是融合为一个进程，这样就变相逾越了android框架中不同apk权限不同无法互通的鸿沟(rpc啦什么的其它的毕竟不如这个来的实在)。</blockquote><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;">从最简单的皮肤插件到复杂的涉及数据库的拓展功能，从普通activity跳转到把插件的activity转变为view并附加到主程序中的拓展功能，都是可以通过本框架来实现的，当然，本框架只是提供了一种途径，如何编码还得靠自己。</blockquote><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;">本人能力有限，可能有一些错误、疏漏或者不足之处，请不吝指教，我的博客地址在左下角，或者我的邮箱，都可以联系到我。</blockquote><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;">ps:下面会以腾讯微信为例，这里声明一下，本人没有对微信安卓客户端进行任意形式的反编译与破解工作，只是看球半天进行简单的猜测而已。</blockquote><h1><a name="框架结构"></a>框架结构</h1><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;">本插件框架由三个包组成：</blockquote><p style="line-height: 1.25em; max-width: 64em; font-family: arial, sans-serif; font-size: 13px; background-color: #ffffff;"></p><ul style="padding-left: 25px; max-width: 62em; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><li style="margin-bottom: 0.3em;">org.igeek.android.pluginframework&nbsp;<strong><em>这个包种类是框架的主要操作类</em></strong></li><ol style="padding-left: 25px; max-width: 62em;"><li style="margin-bottom: 0.3em;">PluginBuilder&nbsp;<strong><em>组装插件</em></strong></li><li style="margin-bottom: 0.3em;">PluginDescription&nbsp;<strong><em>组装用户自定义的插件描述</em></strong></li><li style="margin-bottom: 0.3em;">PluginInvoke&nbsp;<strong><em>插件功能调用</em></strong></li><li style="margin-bottom: 0.3em;">PluginSearch&nbsp;<strong><em>查找插件</em></strong></li></ol><li style="margin-bottom: 0.3em;">org.igeek.android.pluginframework.annotation&nbsp;<strong><em>未来可能会考虑使用注解</em></strong></li><ol style="padding-left: 25px; max-width: 62em;"><li style="margin-bottom: 0.3em;">PluginDescription&nbsp;<strong><em>用于用户自定义描述类的注解</em></strong></li><li style="margin-bottom: 0.3em;">PluginFeature&nbsp;<strong><em>用于插件类的注解</em></strong></li><li style="margin-bottom: 0.3em;">PluginMethod&nbsp;<strong><em>用于插件类方法的注解</em></strong></li></ol><li style="margin-bottom: 0.3em;">org.igeek.android.pluginframework.beans&nbsp;<strong><em>框架内部使用的一些beans</em></strong></li><ol style="padding-left: 25px; max-width: 62em;"><li style="margin-bottom: 0.3em;">Plugin&nbsp;<strong><em>插件包</em></strong></li><li style="margin-bottom: 0.3em;">PluginFeature&nbsp;<strong><em>插件类</em></strong></li><li style="margin-bottom: 0.3em;">PluginFeatureMethod&nbsp;<strong><em>插件方法</em></strong></li></ol><li style="margin-bottom: 0.3em;">org.igeek.android.pluginframework.util&nbsp;<strong><em>一些工具类</em></strong></li><ol style="padding-left: 25px; max-width: 62em;"><li style="margin-bottom: 0.3em;">XMLParse&nbsp;<strong><em>插件包</em></strong></li></ol></ul><p style="line-height: 1.25em; max-width: 64em; font-family: arial, sans-serif; font-size: 13px; background-color: #ffffff;"></p><h1><a name="如何使用"></a>如何使用</h1><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;">以腾讯微信为例，虽然从表面来看，它是插件化的多种功能的一种集成。<em>但是，这都是虚的，每次更新时你会发现，哪怕一个小小的功能添加，都会让用户更新整个程序，截至目前(2011-12-17)，微信让我更新到3.5，修复了一些小bug，增加了1个插件功能，以及其它的小改进，就得让我下载并升级整个程序，6.8m啊。。</em></blockquote><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;">在工程开发时，预留插件的使用、管理页面，如：</blockquote><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><img src="http://android-application-plug-ins-frame-work.googlecode.com/svn/trunk/%20android-application-plug-ins-frame-work/trunk/AndroidPluginFramework/srcshoot/weixin1.png" style="border: 0px; max-width: 100%;"  alt="" /></blockquote><p style="line-height: 1.25em; max-width: 64em; font-family: arial, sans-serif; font-size: 13px; background-color: #ffffff;">这是微信的插件浏览页面，所有可暴露在这里的插件都会被列出来</p><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><img src="http://android-application-plug-ins-frame-work.googlecode.com/svn/trunk/%20android-application-plug-ins-frame-work/trunk/AndroidPluginFramework/srcshoot/weixin2.png" style="border: 0px; max-width: 100%;"  alt="" />&nbsp;这是微信的插件管理界面，可以卸载安卓，但这些都是虚的，可能只是把服务关了，并非真正的卸载</blockquote><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><h2><a name="主程序(APK)"></a>主程序(APK)</h2></blockquote><ul style="padding-left: 25px; max-width: 62em; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><li style="margin-bottom: 0.3em;">、主程序清单<strong></strong></li></ul><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><strong>首先为工程想好一个名字，并在清单中加入sharedUserId属性，属性值就是想好的那个名字，例如微信：com.qq.weixin<pre style="font-size: 12px; padding: 0.5em; overflow: auto; font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; max-width: 70em; background-color: #eeeeee;">&nbsp; &nbsp;android<span style="color: #666600;">:</span>sharedUserId<span style="color: #666600;">=</span><span style="color: #008800;">"com.qq.weixin"</span></pre></strong></blockquote><ul style="padding-left: 25px; max-width: 62em; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><li style="margin-bottom: 0.3em;"><strong>、为插件描述写一个类</strong></li></ul><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><img src="http://android-application-plug-ins-frame-work.googlecode.com/svn/trunk/%20android-application-plug-ins-frame-work/trunk/AndroidPluginFramework/srcshoot/weixin2.png" style="border: 0px; max-width: 100%;"  alt="" />&nbsp;这就是插件描述</blockquote><p style="line-height: 1.25em; max-width: 64em; font-family: arial, sans-serif; font-size: 13px; background-color: #ffffff;"></p><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;">首先在主程序中单独建立一个包，并写一个类，这个类相当于一个bean，具有相应的插件描述信息的字段，如微信，那么这个bean的字段就有&nbsp;<strong>插件名</strong>:<em>漂流瓶</em>&nbsp;<strong>插件logo</strong>:<em>那个人头</em>&nbsp;<strong>插件描述</strong>:<em>描述信息...</em></blockquote><p style="line-height: 1.25em; max-width: 64em; font-family: arial, sans-serif; font-size: 13px; background-color: #ffffff;"></p><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;">这个类在主程序中不会很多的使用，只会读取框架返回的插件的bean。</blockquote><p style="line-height: 1.25em; max-width: 64em; font-family: arial, sans-serif; font-size: 13px; background-color: #ffffff;"></p><ul style="padding-left: 25px; max-width: 62em; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><li style="margin-bottom: 0.3em;">、引入本框架的jar包或导入源码<strong></strong></li></ul><p style="line-height: 1.25em; max-width: 64em; font-family: arial, sans-serif; font-size: 13px; background-color: #ffffff;"></p><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;">正式编码时，可在任何地方调用框架。具体步骤是这样的</blockquote><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><em>1、查找插件</em>&nbsp;本框架是根据sharedUserId来查找插件。它首先会根据自身apk的sharedUserId值来查找系统中具有相同属性的包并加载。</blockquote><ul style="padding-left: 25px; max-width: 62em; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><li style="margin-bottom: 0.3em;">��以说，插件apk的sharedUserId值也应与主程序相同<strong></strong></li></ul><pre style="font-size: 12px; padding: 0.5em; overflow: auto; font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; max-width: 70em; line-height: normal; background-color: #eeeeee;"><strong>&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #880000;">//首先，就是查找插件</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660066;">PluginSearch</span> psearch<span style="color: #666600;">=</span><span style="color: #000088;">new</span> <span style="color: #660066;">PluginSearch</span><span style="color: #666600;">();</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #880000;">//第一次获得的是简要的插件描述</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660066;">List</span><span style="color: #666600;">&lt;</span><span style="color: #660066;">Plugin</span><span style="color: #666600;">&gt;</span> &nbsp;plugins<span style="color: #666600;">=</span>psearch<span style="color: #666600;">.</span>getPlugins<span style="color: #666600;">(</span><span style="color: #000088;">this</span><span style="color: #666600;">);</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #880000;">//然后将插件再组装一下</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660066;">PluginBuilder</span> pbuilder<span style="color: #666600;">=</span><span style="color: #000088;">new</span> <span style="color: #660066;">PluginBuilder</span><span style="color: #666600;">(</span><span style="color: #000088;">this</span><span style="color: #666600;">);</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #880000;">//将用户所定义插件描述融合进去</span><br />&nbsp; &nbsp; &nbsp; &nbsp; plugins<span style="color: #666600;">=</span>pbuilder<span style="color: #666600;">.</span>buildPluginsDescrition<span style="color: #666600;">(</span>plugins<span style="color: #666600;">);</span></strong></pre><p style="line-height: 1.25em; max-width: 64em; font-family: arial, sans-serif; font-size: 13px; background-color: #ffffff;"><strong></strong></p><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><strong>这样就把所有插件找到手了，很简单吧？</strong></blockquote><p style="line-height: 1.25em; max-width: 64em; font-family: arial, sans-serif; font-size: 13px; background-color: #ffffff;"></p><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><em>1、调用插件</em>&nbsp;找到插件后肯定是调用，最简单应用，就是靠Button按钮来调用</blockquote><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;">比如微信的摇一摇，点了它就触发框架的插件调用<pre style="font-size: 12px; padding: 0.5em; overflow: auto; font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; max-width: 70em; background-color: #eeeeee;">&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006666;">@Override</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">public</span> <span style="color: #000088;">void</span> onClick<span style="color: #666600;">(</span><span style="color: #660066;">View</span> v<span style="color: #666600;">)</span> <span style="color: #666600;">{</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #880000;">//新建一个插件调用类</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #660066;">PluginInvoke</span> pi<span style="color: #666600;">=</span><span style="color: #000088;">new</span> <span style="color: #660066;">PluginInvoke</span><span style="color: #666600;">(</span><span style="color: #660066;">AndroidPluginFrameworkActivity</span><span style="color: #666600;">.</span><span style="color: #000088;">this</span><span style="color: #666600;">);</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #880000;">//这是真正的调用</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #880000;">//三个参数，第一个是Plugin类型，第二个是PluginFeature，第三个PluginFeatureMethod</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pi<span style="color: #666600;">.</span>invoke<span style="color: #666600;">(</span>plug<span style="color: #666600;">,</span> pf<span style="color: #666600;">,</span> fm<span style="color: #666600;">);</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666600;">}</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #666600;">});</span></pre></blockquote><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><h2><a name="插件程序(APK)"></a>插件程序(APK)</h2></blockquote><ul style="padding-left: 25px; max-width: 62em; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><li style="margin-bottom: 0.3em;">、插件程序清单<strong></strong></li></ul><p style="line-height: 1.25em; max-width: 64em; font-family: arial, sans-serif; font-size: 13px; background-color: #ffffff;"><strong></strong></p><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><strong>同主程序的清单文件一样，sharedUserId必须有且和主程序的一样 插件的activity的意图过滤描述必须是这样 示例：</strong><p style="line-height: 1.25em; max-width: 64em;"></p><pre style="font-size: 12px; padding: 0.5em; overflow: auto; font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; max-width: 70em; background-color: #eeeeee;">&nbsp;<span style="color: #000088;">&lt;intent-filter&gt;</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">&lt;category</span> <span style="color: #660066;">android:name</span><span style="color: #666600;">=</span><span style="color: #008800;">"android.intent.category.DEFAULT"</span> <span style="color: #000088;">/&gt;</span><br />&nbsp; <span style="color: #000088;">&lt;/intent-filter&gt;</span></pre></blockquote><ul style="padding-left: 25px; max-width: 62em; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><li style="margin-bottom: 0.3em;">、插件程序的功能<strong></strong></li></ul><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><strong>插件可以包含任意类，如同一个普通的apk工程一样。</strong></blockquote><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><strong>但是，向主程序提供调用的类，必须是个activity，方法必须是无返回值的，有且只有一个Context参数，框架会反射这个方法，并将主程序的context句柄传入，也就是，不管你用不用这个context，他都是被框架传入的。</strong></blockquote><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><strong>如果主程序规定了描述类，也就是框架中需要PluginDescription来调用的bean，在插件工程中，也必须有主程序这个bean，包名也必须一样。插件程序可以直接继承或者更改这个bean的字段，方便主程序去获取这个插件的描述信息。这种方式，是避过框架，给主程序一种方便。</strong></blockquote><ul style="padding-left: 25px; max-width: 62em; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><li style="margin-bottom: 0.3em;"><strong>、插件程序的plugin.xml配置</strong></li></ul><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;"><a href="http://android-application-plug-ins-frame-work.googlecode.com/files/plugin.xml" rel="nofollow" style="color: #0000cc;">http://android-application-plug-ins-frame-work.googlecode.com/files/plugin.xml</a>&nbsp;plugin.xml不能改名，必须放在工程的 assets 目录下。</blockquote><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;">内容大致是这样：<pre style="font-size: 12px; padding: 0.5em; overflow: auto; font-family: Monaco, 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Lucida Console', monospace; max-width: 70em; background-color: #eeeeee;"><span style="color: #666600;">&lt;?</span>xml version<span style="color: #666600;">=</span><span style="color: #008800;">"1.0"</span> encoding<span style="color: #666600;">=</span><span style="color: #008800;">"UTF-8"</span><span style="color: #666600;">?&gt;</span><br /><span style="color: #880000;">&lt;!-- 这个xml配置文件放在插件工程的 assets 目录下 --&gt;</span><br /><br /><br /><span style="color: #880000;">&lt;!-- 插件提供的功能(类) --&gt;</span><br /><span style="color: #000088;">&lt;plugin-features&gt;</span><br /><br />&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #880000;">&lt;!-- 描述类，这个是自定义的 --&gt;</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #880000;">&lt;!-- 这个描述类使用户定义的，在主程序中必须有，插件工程中也必须有，并被继承 --&gt;</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">&lt;description</span> <span style="color: #660066;">name</span><span style="color: #666600;">=</span><span style="color: #008800;">"org.pakage.name.and.description.name"</span><span style="color: #000088;">/&gt;</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #880000;">&lt;!-- 这是一个功能(类)，必须是activity的子类 --&gt;</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">&lt;feature</span> <span style="color: #660066;">name</span><span style="color: #666600;">=</span><span style="color: #008800;">"org.pakage.name.and.activity.name1"</span><span style="color: #000088;">&gt;</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #880000;">&lt;!-- 这是一个方法 --&gt;</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #880000;">&lt;!-- name 方法名 --&gt;</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">&lt;method</span> <span style="color: #660066;">need-context</span><span style="color: #666600;">=</span><span style="color: #008800;">"true"</span> <span style="color: #660066;">name</span><span style="color: #666600;">=</span><span style="color: #008800;">"methodName1"</span> <span style="color: #000088;">&gt;</span>描述信息<span style="color: #000088;">&lt;/method&gt;</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">&lt;method</span> <span style="color: #660066;">need-context</span><span style="color: #666600;">=</span><span style="color: #008800;">"true"</span> <span style="color: #660066;">name</span><span style="color: #666600;">=</span><span style="color: #008800;">"methodName2"</span> <span style="color: #000088;">&gt;</span>描述信息<span style="color: #000088;">&lt;/method&gt;</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">&lt;/feature&gt;</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <br />&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">&lt;feature</span> <span style="color: #660066;">name</span><span style="color: #666600;">=</span><span style="color: #008800;">"org.pakage.name.and.activity.name2"</span><span style="color: #000088;">&gt;</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">&lt;method</span> <span style="color: #660066;">need-context</span><span style="color: #666600;">=</span><span style="color: #008800;">"true"</span> <span style="color: #660066;">name</span><span style="color: #666600;">=</span><span style="color: #008800;">"methodName1"</span> <span style="color: #000088;">&gt;</span>描述信息<span style="color: #000088;">&lt;/method&gt;</span><br />&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000088;">&lt;/feature&gt;</span><br /><span style="color: #000088;">&lt;/plugin-features&gt;</span></pre></blockquote><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;">按着上面的套路来配置，就很容易了。</blockquote><h1><a name="最后"></a>最后</h1><blockquote style="margin: 20px; max-width: 60em; color: #000000; font-family: arial, sans-serif; font-size: 13px; line-height: normal; background-color: #ffffff;">上面说的比较泛，最好还是看看示例工程，里面包含了一个主程序和两个插件扩展，总共是4个工程，也就是说，在用户端是4个apk<a href="http://android-application-plug-ins-frame-work.googlecode.com/files/demo.zip" rel="nofollow" style="color: #0000cc;">http://android-application-plug-ins-frame-work.googlecode.com/files/demo.zip</a></blockquote><img src ="http://www.blogjava.net/xiaomage234/aggbug/419113.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-10-28 11:21 <a href="http://www.blogjava.net/xiaomage234/archive/2014/10/28/419113.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>高手速成android开源项目【developer篇】</title><link>http://www.blogjava.net/xiaomage234/archive/2014/10/22/418953.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Wed, 22 Oct 2014 11:56:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/10/22/418953.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/418953.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/10/22/418953.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/418953.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/418953.html</trackback:ping><description><![CDATA[from:http://www.ppst.cc/post_info/1389279044687141000000<br /><br /><div style="margin: 0px; overflow: hidden; color: #676767; font-family: 'Microsoft Yahei'; font-size: medium; line-height: normal;"><ul style="margin: 20px 0px 10px 10px; overflow: hidden; padding: 0px;"><li style="list-style: none outside none; float: left;"><span style="border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: #5090ba; display: inline-block; line-height: 18px; margin: 0px 5px 0px 0px; padding: 0px 6px; background: none 0px 0px repeat scroll #e6f0f5;">标签:</span>&nbsp;<span style="border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: #5090ba; display: inline-block; line-height: 18px; margin: 0px 5px 0px 0px; padding: 0px 6px; background: none 0px 0px repeat scroll #e6f0f5;">android</span>&nbsp;<span style="border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: #5090ba; display: inline-block; line-height: 18px; margin: 0px 5px 0px 0px; padding: 0px 6px; background: none 0px 0px repeat scroll #e6f0f5;">Android</span>&nbsp;<span style="border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: #5090ba; display: inline-block; line-height: 18px; margin: 0px 5px 0px 0px; padding: 0px 6px; background: none 0px 0px repeat scroll #e6f0f5;">andriod</span>&nbsp;<span style="border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; color: #5090ba; display: inline-block; line-height: 18px; margin: 0px 5px 0px 0px; padding: 0px 6px; background: none 0px 0px repeat scroll #e6f0f5;">开源项目</span></li></ul></div><div style="color: #676767; font-family: 'Microsoft Yahei'; font-size: medium; line-height: normal;"><ul style="padding: 5px 0px 0px 10px; font-size: 13px; letter-spacing: 1px; margin: 0px; text-align: justify; text-indent: 15px; word-spacing: 2px; width: 630px; overflow: hidden; color: #000000;"><p style="margin-top: 15px; margin-bottom: 15px; font-size: 15px; line-height: 25px; font-family: Helvetica, arial, freesans, clean, sans-serif; color: #333333;"></p><p style="margin-top: 15px; margin-bottom: 15px; font-size: 15px; line-height: 25px; font-family: Helvetica, arial, freesans, clean, sans-serif; color: #333333;">主要介绍和Android开发工具和测试工具相关的开源项目。</p><ol style="padding: 0px 0px 0px 30px; margin: 15px 0px; font-size: 15px; line-height: 25px; font-family: Helvetica, arial, freesans, clean, sans-serif; color: #333333;"><li style="list-style: none outside none;"><p style="margin-top: 15px; margin-bottom: 15px;">Buck<br />facebook开源的Android编译工具，效率是ant的两倍。主要优点在于：<br />(1) 加快编译速度，通过并行利用多核cpu和跟踪不变资源减少增量编译时间实现<br />(2) 可以在编译系统中生成编译规则而无须另外的系统生成编译规则文件<br />(3) 编译同时可生成单元测试结果<br />(4) 既可用于IDE编译也可用于持续集成编译<br />(5) facebook持续优化中<br />项目地址：<a target="_blank" href="https://github.com/facebook/buck" style="cursor: pointer; text-decoration: none; color: #4183c4;">https://github.com/facebook/buck</a></p></li><li style="list-style: none outside none;"><p style="margin-top: 15px; margin-bottom: 15px;">Android Maven Plugin<br />Android Maven插件，可用于对android三方依赖进行管理。在J2EE开发中，maven是非常成熟的依赖库管理工具，可统一管理依赖库。<br />项目地址：<a target="_blank" href="https://github.com/jayway/maven-android-plugin" style="cursor: pointer; text-decoration: none; color: #4183c4;">https://github.com/jayway/maven-android-plugin</a></p></li><li style="list-style: none outside none;"><p style="margin-top: 15px; margin-bottom: 15px;">Spoon<br />可用于android不同机型设备自动化测试，能将应用apk和测试apk运行在不同机器上并生成相应测试报告。<br />项目地址：<a target="_blank" href="https://github.com/square/spoon" style="cursor: pointer; text-decoration: none; color: #4183c4;">https://github.com/square/spoon</a></p></li><li style="list-style: none outside none;"><p style="margin-top: 15px; margin-bottom: 15px;">Android FEST<br />提供一些列方便的断言，可用于提高编写Android自测代码效率<br />项目地址：<a target="_blank" href="https://github.com/square/fest-android" style="cursor: pointer; text-decoration: none; color: #4183c4;">https://github.com/square/fest-android</a></p></li><li style="list-style: none outside none;"><p style="margin-top: 15px; margin-bottom: 15px;">SelectorChapek for Android<br />Android Studio插件，可根据固定文件名格式资源自动生成drawable selectors xml文件。<br />项目地址：<a target="_blank" href="https://github.com/inmite/android-selector-chapek" style="cursor: pointer; text-decoration: none; color: #4183c4;">https://github.com/inmite/android-selector-chapek</a></p></li><li style="list-style: none outside none;"><p style="margin-top: 15px; margin-bottom: 15px;">Android Resource Navigator<br />chrome插件，可以方便的查看github上android源码工程的styles.xml和themes.xml。主要功能：<br />(1) 快速打开android styles.xml themes.xml<br />(2) 方便在资源间跳转。styles.xml themes.xml文件中资源链接跳转，可以方便跳转到某个资源<br />(3) 方便查找某个style和theme。chrome地址栏输入arn+tab+搜索内容回车即可<br />(4) 自动下载不同分辨率下的drawable<br />(5) 通过映射查找那些不是按照固定命名规则命名的style和theme<br />项目地址：<a target="_blank" href="https://github.com/jgilfelt/android-resource-navigator" style="cursor: pointer; text-decoration: none; color: #4183c4;">https://github.com/jgilfelt/android-resource-navigator</a><br />示例：<a target="_blank" href="https://chrome.google.com/webstore/detail/android-resource-navigato/agoomkionjjbejegcejiefodgbckeebo?hl=en&amp;gl=GB" style="cursor: pointer; text-decoration: none; color: #4183c4;">https://chrome.google.com/webstore/detail/android-resource-navigato/agoomkionjjbejegcejiefodgbckeebo?hl=en&amp;gl=GB</a></p></li><li style="list-style: none outside none;"><p style="margin-top: 15px; margin-bottom: 15px;">Android Action Bar Style Generator<br />Android ActionBar样式生成器，可在线选择ActionBar样式自动生成所需要的图片资源及xml文件<br />项目地址：<a target="_blank" href="https://github.com/jgilfelt/android-actionbarstylegenerator" style="cursor: pointer; text-decoration: none; color: #4183c4;">https://github.com/jgilfelt/android-actionbarstylegenerator</a><br />在线演示：<a target="_blank" href="http://jgilfelt.github.io/android-actionbarstylegenerator/" style="cursor: pointer; text-decoration: none; color: #4183c4;">http://jgilfelt.github.io/android-actionbarstylegenerator/</a></p></li><li style="list-style: none outside none;"><p style="margin-top: 15px; margin-bottom: 15px;">ViewServer<br />允许app运行在任何手机上都可以用HierarchyViewer查看<br />项目地址：<a target="_blank" href="https://github.com/romainguy/ViewServer" style="cursor: pointer; text-decoration: none; color: #4183c4;">https://github.com/romainguy/ViewServer</a></p></li><li style="list-style: none outside none;"><p style="margin-top: 15px; margin-bottom: 15px;">GridWichterle for Android<br />在整个系统上显示一个grid，用来帮助查看应用布局及使得布局更美观，可设置grid网格大小和颜色，android推荐48dp和8dp，可见 Android Design Guidelines &#8211; Metrics and Grids<br />项目地址：<a target="_blank" href="https://github.com/inmite/android-grid-wichterle" style="cursor: pointer; text-decoration: none; color: #4183c4;">https://github.com/inmite/android-grid-wichterle</a><br />APK地址：<a target="_blank" href="https://play.google.com/store/apps/details?id=eu.inmite.android.gridwichterle" style="cursor: pointer; text-decoration: none; color: #4183c4;">https://play.google.com/store/apps/details?id=eu.inmite.android.gridwichterle</a><br />PS：比起hierarchyviewer相差甚远，不过偶尔可用来作为布局查看工具。</p></li><li style="list-style: none outside none;"><p style="margin-top: 15px; margin-bottom: 15px;">渠道打包工具<br />允许app运行在任何手机上都可以用HierarchyViewer查看<br />项目地址：<a target="_blank" href="https://github.com/umeng/umeng-muti-channel-build-tool" style="cursor: pointer; text-decoration: none; color: #4183c4;">https://github.com/umeng/umeng-muti-channel-build-tool</a><br />另可参见Google的构建系统Gradle：<a target="_blank" href="http://tools.android.com/tech-docs/new-build-system/user-guide" style="cursor: pointer; text-decoration: none; color: #4183c4;">http://tools.android.com/tech-docs/new-build-system/user-guide</a></p></li><li style="list-style: none outside none;"><p style="margin-top: 15px; margin-bottom: 15px;">Catlog<br />手机端log查看工具，支持不同颜色显示、关键字过滤、级别过滤、进程id过滤、录制功能等<br />项目地址：<a target="_blank" href="https://github.com/nolanlawson/Catlog" style="cursor: pointer; text-decoration: none; color: #4183c4;">https://github.com/nolanlawson/Catlog</a><br />在线演示：<a target="_blank" href="https://play.google.com/store/apps/details?id=com.nolanlawson.logcat" style="cursor: pointer; text-decoration: none; color: #4183c4;">https://play.google.com/store/apps/details?id=com.nolanlawson.logcat</a></p></li><li style="list-style: none outside none;"><p style="margin-top: 15px; margin-bottom: 15px;">PID Cat<br />根据package查看logcat日志<br />项目地址：<a target="_blank" href="https://github.com/JakeWharton/pidcat" style="cursor: pointer; text-decoration: none; color: #4183c4;">https://github.com/JakeWharton/pidcat</a></p></li><li style="list-style: none outside none;"><p style="margin-top: 15px; margin-bottom: 15px;">Hugo<br />用于打印函数信息及执行时间的工具，仅在debug模式生效<br />项目地址：<a target="_blank" href="https://github.com/JakeWharton/hugo" style="cursor: pointer; text-decoration: none; color: #4183c4;">https://github.com/JakeWharton/hugo</a></p></li><li style="list-style: none outside none;"><p style="margin-top: 15px; margin-bottom: 15px;">scalpel<br />在应用下面添加一层用于界面调试，待详细补充 // TODO<br />项目地址：<a target="_blank" href="https://github.com/JakeWharton/scalpel" style="cursor: pointer; text-decoration: none; color: #4183c4;">https://github.com/JakeWharton/scalpel</a></p></li></ol></ul></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/418953.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-10-22 19:56 <a href="http://www.blogjava.net/xiaomage234/archive/2014/10/22/418953.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用buck构建你的Android App</title><link>http://www.blogjava.net/xiaomage234/archive/2014/10/22/418951.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Wed, 22 Oct 2014 11:34:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/10/22/418951.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/418951.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/10/22/418951.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/418951.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/418951.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: from:https://typeblog.net/tech/2014/07/22/use-buck-to-build-your-app.htmlbuck&nbsp;是Facebook推出的一款高效率的Android App/Java项目构建工具，目前仅支持&nbsp;Unix/Linux&nbsp;平台。因为它使用多线程编译方式，所以相对于其他的构建工具而言编译时间可以缩短50%甚至更多。buc...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2014/10/22/418951.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/418951.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-10-22 19:34 <a href="http://www.blogjava.net/xiaomage234/archive/2014/10/22/418951.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]直接拿来用！最火的Android开源项目（二）</title><link>http://www.blogjava.net/xiaomage234/archive/2014/09/26/418316.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Fri, 26 Sep 2014 09:15:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/09/26/418316.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/418316.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/09/26/418316.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/418316.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/418316.html</trackback:ping><description><![CDATA[<div id="cnblogs_post_body" style="margin: 0px 0px 20px; outline: none 0px; color: #333333; font-family: 'Microsoft Yahei', Tahoma, Arial, Helvetica, STHeiti; font-size: 15px; line-height: 27px; background-color: #ffffff;"><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">在《<a href="http://www.cnblogs.com/purediy/archive/2013/05/20/3088330.html" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">直接拿来用！最火的Android开源项目（一）</strong></a>》中，我们详细地介绍了GitHub上最受欢迎的TOP20 Android开源项目，引起了许多读者的热议，作为开发者，你最常用的是哪些开源项目？使用起来是否能让你得心应手？今天，我们将介绍另外20个Android开源项目，在这些项目中，你又用到了哪些呢？</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">21.&nbsp;<a href="https://github.com/bauerca/drag-sort-listview" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">drag-sort-listview</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">DragSortListView（DSLV）是Android ListView的一个扩展，支持拖拽排序和左右滑动删除功能。重写了TouchInterceptor（TI）类来提供更加优美的拖拽动画效果。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/06/5187781b64cbe.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/06/5187781b64cbe_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a>&nbsp;<a href="http://cms.csdnimg.cn/article/201305/06/5187782519829.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/06/5187782519829_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">DSLV主要特性：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;">&nbsp;</p><ul style="margin: 0px 0px 0px 45px; padding: 0px; outline: none 0px;"><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">完美的拖拽支持；</span></li><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">在拖动时提供更平滑的滚动列表滚动；</span></li><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">支持每个ListItem高度的多样性</span></li><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">公开startDrag()和stopDrag()方法；</span></li><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">有公开的接口可以自定义拖动的View。</span></li></ul><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">DragSortListView适用于带有任何优先级的列表：收藏夹、播放列表及清单等，算得上是目前Android开源实现拖动排序操作最完美的方案。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">22.&nbsp;<a href="https://github.com/cgeo/c-geo-opensource" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">c-geo-opensource</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">c:geo是Android设备上一个简单而又强大的非官方地理寻宝客户端。与其他类似应用不同的是，c:geo不需要Web浏览器，也不需要文件输出。你可以在毫无准备的情况下，毫无后顾之忧地带上你的智能手机去进行地理寻宝。当然，你也不需要付钱，因为它是免费的。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/07/518894ed23ed2.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/07/518894ed23ed2_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">c-geo-opensource包含了c:geo所有开源代码。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">详情请参考：<a href="http://www.cgeo.org/" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">c:geo</strong></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">23.&nbsp;<a href="https://github.com/JakeWharton/NineOldAndroids" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">NineOldAndroids</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">自Android 3.0以上的版本，SDK新增了一个android.animation包，里面的类都是跟动画效果实现相关的，通过Honeycomb API，能够实现非常复杂的动画效果。但如果开发者想在3.0以下的版本中也能使用到这套API，那么Nine Old Androids就会是你最好的选择，该API和Honeycomb API完全一样，只是改变了你使用com.nineoldandroids.XXX的入口。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/07/51889435c4f33.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/07/51889435c4f33_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">该项目包含两个工程，一个是Library，即为动画效果的实现库，另一个则是Sample，是对如何使用该API的演示。开发者可以直接登陆Google Play下载安装<a href="https://play.google.com/store/apps/details?id=com.jakewharton.nineoldandroids.sample" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">Nine Old Androids Sample</strong></a>，查看演示。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">详情请参考：<a href="http://nineoldandroids.com/" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">Nine Old Androids</strong></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">24.&nbsp;<a href="https://github.com/hrydgard/ppsspp" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">ppsspp</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">PPSSPP是由GC/Wii模拟器<a href="http://dolphin-emu.org/" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">Dolphin</strong></a>联合创始人之一Henrik Rydg&#229;rd开发的一款免费的跨平台开源模拟器，支持Windows、Linux、Mac、Android、iOS、BlackBerry 10等主流计算机与移动操作系统，可直接工作在x86、x64、ARM等CPU平台上，以GNU GPLv2许可协议发布，主要使用C++编写以提高效率和可移植性。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/06/518779953e825.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/06/518779953e825_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">只要支持OpenGL ES 2.0，PPSSPP就可以在相当低规格的硬件设备上运行，包括基于ARM的手机及平板电脑。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">详情请参考：<a href="http://www.ppsspp.org/" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">PPSSPP</strong></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">25.&nbsp;<a href="https://github.com/androidquery/androidquery" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">androidquery</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">Android-Query（AQuery）是一个轻量级的开发包，用于实现Android上的异步任务和操作UI元素，可让Android应用开发更简单、更容易，也更有趣。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">26.&nbsp;<a href="https://github.com/mttkay/droid-fu" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">droid-fu</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">Droid-Fu是一个开源的通用Android应用库，其主要目的是为了让Android开发更容易，包含有许多工具类，还有非常易用的Android组件。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">Droid-Fu提供支持的领域包括：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;">&nbsp;</p><ul style="margin: 0px 0px 0px 45px; padding: 0px; outline: none 0px;"><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">Android应用的生命周期帮助</span></li><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">支持处理Intents和diagnostics类</span></li><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">后台任务支持</span></li><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">HTTP消息处理</span></li><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">对象、HTTP响应及远程图像高速缓存</span></li><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">定制各种Adapter及View</span></li></ul><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/07/518897f7199f4.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/07/518897f7199f4_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">Droid-Fu最大的优势在于它的应用生命周期帮助类，如果你正在开发一款Android应用，而它的主要任务是运行后台任务，比如从Web上抓取数据，那么，你一定会使用到Droid-Fu，不过，目前该项目在GitHub上已经停止更新维护。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">详情请参考：<a href="https://github.com/mttkay/droid-fu/wiki" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">droid-fu</strong></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">27.&nbsp;<a href="https://github.com/WhisperSystems/TextSecure" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">TextSecure</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">TextSecure是Whisper Systems团队开发的一个Android上的加密信息客户端，旨在增强用户和企业通信的安全性，其源代码于2011年被Twitter发布在GitHub开源数据库中。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/07/51889740c3bd3.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/07/51889740c3bd3_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">该软件允许用户将在Android设备上所有发送和接收的短信内容进行加密，还可以将加密信息发送给另一个TextSecure用户。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">28.&nbsp;<a href="https://github.com/xamarin/XobotOS" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">XobotOS</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">XobotOS是Xamarin的一个研究项目，用于将Android 4.0从Java/Dalvik移植到C#，并对移植后的性能及内存占用情况进行检测。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/06/518779fcb89b9.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/06/518779fcb89b9_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">29.&nbsp;<a href="https://github.com/mttkay/ignition" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">ignition</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">在编写Android应用时，通过提供即用组件和包含许多样板文件的实用类，ignition可以让你的Android应用快速起步。ignition涵盖的区域包括：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;">&nbsp;</p><ul style="margin: 0px 0px 0px 45px; padding: 0px; outline: none 0px;"><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">Widget、Adapter、Dialog等UI组件；</span></li><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">允许编写简单却强大的网络代码的HTTP Wrapper库；</span></li><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">加载远程Web图像并进行缓存的类；</span></li><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">简单但有效的缓存框架（将对所有对象树做出响应的HTTP缓存到内存或硬盘中）；</span></li><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">Intents、diagnostics等几个能让API级别更容易向后兼容的帮助类；</span></li><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">更友好、更强大的AsyncTask实现。</span></li></ul><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/07/51889448dd732.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/07/51889448dd732_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">ignition包括三个子项目：</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;">&nbsp;</p><ul style="margin: 0px 0px 0px 45px; padding: 0px; outline: none 0px;"><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">ignition-core&#8212;&#8212;是一个可以直接编译到App中的Android库项目。</span></li><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">ignition-support&#8212;&#8212;一个标准的Java库项目，被部署为一个普通的JAR，包含了大部分实用工具类。开发者可以独立使用该工程的核心模块。</span></li><li style="margin: 0px; padding: 0px; outline: none 0px; list-style: inherit !important;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">ignition-location&#8212;&#8212;一个可以直接编译到应用程序中的Android AspectJ库项目。能够让定位应用在不需要Activity位置更新处理的情况下获取到最新的位置信息。</span></li></ul><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">详情请参考：<a href="https://github.com/mttkay/ignition/wiki/Sample-applications" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">ignition&nbsp;Sample applications</strong></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">30.&nbsp;<a href="https://github.com/harism/android_page_curl" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">android_page_curl</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">android_page_curl是一个在Android上使用OpenGL ES实现类似书本翻页效果的示例程序。（点击链接查看<a href="http://www.youtube.com/watch?v=iwu7P5PCpsw" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">视频演示</strong></a>）</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/07/51889b43ec9e9.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/07/51889b43ec9e9_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">31.&nbsp;<a href="https://github.com/Flowdalic/asmack" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">asmack</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">说到aSmack，自然要先提提Smack。Smack API是一个完整的实现了XMPP协议的开源API库，而aSmack则是Smack在Android上的构建版本，于2013年2月初迁移到GitHub上，该资源库并不包含太多的代码，只是一个构建环境。开发者可以利用该API进行基于XMPP协议的即时消息应用程序开发。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">详情请参考：<a href="https://code.google.com/p/asmack/" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">asmack</strong></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">32.&nbsp;<a href="https://github.com/robotmedia/AndroidBillingLibrary" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">AndroidBillingLibrary</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">In-app Billing是一项Google Play服务，能够让你在应用内进行数字内容销售，可销售的数字内容范围非常广，包括媒体文件、照片等下载内容，还包括游戏级别、药剂、增值服务和功能等虚拟内容。Android Billing Library可以实现In-app Billing的所有规范，并提供更高级的类来进行使用。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/07/5188ae278fb5a.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/07/5188ae278fb5a_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">Google于2012年底正式发布了v3版Android In-app Billing，但截至目前，GitHub上的Android Billing Library还只能支持到v2版，据悉Google将于2013年初对它进行更新。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">详情请参考：<a href="http://developer.android.com/google/play/billing/index.html" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">Google Play In-app Billing</strong></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">33.&nbsp;<a href="https://github.com/keyboardsurfer/Crouton" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">Crouton</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">Crouton是Android上的一个可以让开发者对环境中的Toast进行替换的类，以一个应用程序窗口的方式显示，而其显示位置则由开发者自己决定。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/07/5188b6491fd81.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/07/5188b6491fd81_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">开发者可以直接登陆Google Play下载安装<a href="https://play.google.com/store/apps/details?id=de.keyboardsurfer.app.demo.crouton" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">Crouton Demo</strong></a>，查看应用演示。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">34.&nbsp;<a href="https://github.com/commonsguy/cwac-endless" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">cwac-endless</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">CommonsWare Android Components（CWAC）是一个开源的Android组件库，用来解决Android开发中各个方面的常见问题，每个 CWAC组件打包成一个独立的jar文件，其中就包含cwac-endless。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/07/5188ca3020955.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/07/5188ca3020955_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">cwac-endless提供一个EndlessAdapter，这是一个自动分页的List，当用户浏览到List最后一行时自动请求新的数据。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">详情请参考：<a href="http://commonsware.com/cwac" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">Commons Ware</strong></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">35.&nbsp;<a href="https://github.com/JakeWharton/DiskLruCache" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">DiskLruCache</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">在Android应用开发中，为了提高UI的流畅性、响应速度，提供更高的用户体验，开发者常常会绞尽脑汁地思考如何实现高效加载图片，而DiskLruCache实现正是开发者常用的图片缓存技术之一。Disk LRU Cache，顾名思义，硬件缓存，就是一个在文件系统中使用有限空间进行高速缓存。每个缓存项都有一个字符串键和一个固定大小的值。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/07/5188fc60a7729.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/07/5188fc60a7729_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">点击链接<a href="http://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&amp;g=com.jakewharton&amp;a=disklrucache&amp;v=LATEST" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">下载</strong></a>该库项目。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">36.&nbsp;<a href="https://github.com/tjerkw/Android-SlideExpandableListView" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">Android-SlideExpandableListView</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">如果你对Android提供的Android ExpandableListView并不满意，一心想要实现诸如Spotify应用那般的效果，那么SlideExpandableListView绝对是你最好的选择。该库允许你自定义每个列表项目中的ListView，一旦用户点击某个按钮，即可实现该列表项目区域滑动。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/07/5188ff9b1a21b.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/07/5188ff9b1a21b_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">37.&nbsp;<a href="https://github.com/github/gauges-android" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">gauges-android</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">Gaug.es for Android是由<a href="http://get.gaug.es/" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">gaug.es</strong></a>推出的一款在Android设备上对网站流量数据进行实时统计的应用。gauges-android包含了该应用的源代码，开发者可以直接登陆<a href="https://play.google.com/store/apps/details?id=com.github.mobile.gauges" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">Google Play</strong></a>下载安装该应用。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/07/5189035ebf373.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/07/5189035ebf373_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">38.&nbsp;<a href="https://github.com/ACRA/acra" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">acra</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">ACRA是一个能够让Android应用自动将崩溃报告以谷歌文档电子表的形式进行发送的库，旨在当应用发生崩溃或出现错误行为时，开发者可以获取到相关数据。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/07/5189057f9195e.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/07/5189057f9195e_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">39.&nbsp;<a href="https://github.com/roboguice/roboguice" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">roboguice</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">RoboGuice是Android平台上基于Google Guice开发的一个库，可以大大简化Android应用开发的代码及一些繁琐重复的代码。给Android带来了简单、易用的依赖注入，如果你使用过Spring或Guice的话，你就会知道这种编程方式是多么的便捷。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/07/518906ff6405e.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/07/518906ff6405e_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">40.&nbsp;<a href="https://github.com/square/otto" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">otto</a></strong></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">Otto是由Square发布的一个着重于Android支持的基于Guava的强大的事件总线，在对应用程序不同部分进行解耦之后，仍然允许它们进行有效的沟通。</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><a href="http://cms.csdnimg.cn/article/201305/07/51890a97dcfc6.jpg" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><img src="http://cms.csdnimg.cn/article/201305/07/51890a97dcfc6_middle.jpg" alt="" border="0" style="margin: 0px; padding: 0px; outline: none 0px; border: 0px;" /></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;">详情请参考：<a href="http://square.github.io/otto/" target="_blank" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">Otto</strong></a></span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; outline: none 0px;"><span style="margin: 0px; padding: 0px; outline: none 0px; line-height: 1.8; font-size: 13px;"><strong style="margin: 0px; padding: 0px; outline: none 0px;">转自：<a href="http://www.csdn.net/article/2013-05-06/2815145-Android-open-source-projects-two" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">http://www.csdn.net/article/2013-05-06/2815145-Android-open-source-projects-two</a></strong></span></p></div><div style="margin: 0px; outline: none 0px; clear: both; color: #333333; font-family: 'Microsoft Yahei', Tahoma, Arial, Helvetica, STHeiti; font-size: 15px; line-height: 27px; background-color: #ffffff;"></div><div id="blog_post_info_block" style="margin: 20px 0px 0px; outline: none 0px; color: #333333; font-family: 'Microsoft Yahei', Tahoma, Arial, Helvetica, STHeiti; font-size: 15px; line-height: 27px; background-color: #ffffff;"><div id="BlogPostCategory" style="margin: 0px 0px 10px; outline: none 0px;">分类:&nbsp;<a href="http://www.cnblogs.com/purediy/category/481941.html" style="margin: 0px; padding: 0px; outline: none 0px; text-decoration: none; color: #ff7700; border: 0px none;">android</a></div></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/418316.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-09-26 17:15 <a href="http://www.blogjava.net/xiaomage234/archive/2014/09/26/418316.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]直接拿来用！最火的Android开源项目（一）</title><link>http://www.blogjava.net/xiaomage234/archive/2014/09/26/418315.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Fri, 26 Sep 2014 09:14:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/09/26/418315.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/418315.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/09/26/418315.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/418315.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/418315.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: GitHub在中国的火爆程度无需多言，越来越多的开源项目迁移到GitHub平台上。更何况，基于不要重复造轮子的原则，了解当下比较流行的Android与iOS开源项目很是必要。利用这些项目，有时能够让你达到事半功倍的效果。为此，CSDN特整理了在GitHub平台上最受欢迎的Android及iOS开源项目，以飨开发者。下面，就让我们一起来看看，在GitHub平台上，究竟有哪些Android开源项目最火...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2014/09/26/418315.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/418315.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-09-26 17:14 <a href="http://www.blogjava.net/xiaomage234/archive/2014/09/26/418315.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JavaPNS使用与吐槽</title><link>http://www.blogjava.net/xiaomage234/archive/2014/07/22/416095.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 22 Jul 2014 10:44:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/07/22/416095.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/416095.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/07/22/416095.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/416095.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/416095.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: http://autumnrain-zgq.iteye.com/blog/1743279苹果平台开发的应用程序，不支持后台运行程序，所以苹果有一个推送服务在软件的一些信息推送给用户。&nbsp;JAVA中，有一个开源软件，JavaPNS实现了Java平台中连接苹果服务器与推送消息的服务。但是在使用的过程中，有两点需要使用者注意一下，希望后续使用的同志们能避免我走过的覆辙。&nbsp;1、一是向苹果...&nbsp;&nbsp;<a href='http://www.blogjava.net/xiaomage234/archive/2014/07/22/416095.html'>阅读全文</a><img src ="http://www.blogjava.net/xiaomage234/aggbug/416095.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-07-22 18:44 <a href="http://www.blogjava.net/xiaomage234/archive/2014/07/22/416095.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>iOS应用程序生命周期(前后台切换,应用的各种状态)详解</title><link>http://www.blogjava.net/xiaomage234/archive/2014/07/22/416091.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Tue, 22 Jul 2014 10:01:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/07/22/416091.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/416091.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/07/22/416091.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/416091.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/416091.html</trackback:ping><description><![CDATA[<div>http://blog.csdn.net/totogo2010/article/details/8048652<br /><p style="margin: 0px; padding: 0px;">iOS的应用程序的生命周期，还有程序是运行在前台还是后台，应用程序各个状态的变换，这些对于开发者来说都是很重要的。 iOS系统的资源是有限的，应用程序在前台和在后台的状态是不一样的。在后台时，程序会受到系统的很多限制，这样可以提高电池的使用和用户体验。</p><p style="margin: 0px; padding: 0px;">//开发app,我们要遵循apple公司的一些指导原则，原则如下：</p><h2><a name="t0" style="color: rgb(255, 153, 0);"></a>1、应用程序的状态</h2><p style="margin: 0px; padding: 0px;">状态如下：</p><p style="margin: 0px; padding: 0px;">Not running &nbsp;未运行 &nbsp;程序没启动</p><p style="margin: 0px; padding: 0px;">Inactive &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;未激活 &nbsp; &nbsp; &nbsp; &nbsp;程序在前台运行，不过没有接收到事件。在没有事件处理情况下程序通常停留在这个状态</p><p style="margin: 0px; padding: 0px;">Active &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 激活 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 程序在前台运行而且接收到了事件。这也是前台的一个正常的模式</p><p style="margin: 0px; padding: 0px;">Backgroud &nbsp; &nbsp; 后台 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 程序在后台而且能执行代码，大多数程序进入这个状态后会在在这个状态上停留一会。时间到之后会进入挂起状态(Suspended)。有的程序经过特殊的请求后可以长期处于Backgroud状态</p><p style="margin: 0px; padding: 0px;">Suspended &nbsp; &nbsp;挂起 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 程序在后台不能执行代码。系统会自动把程序变成这个状态而且不会发出通知。当挂起时，程序还是停留在内存中的，当系统内存低时，系统就把挂起的程序清除掉，为前台程序提供更多的内存。</p><p style="margin: 0px; padding: 0px;">下图是程序状态变化图：</p><p style="margin: 0px; padding: 0px;"><img src="http://img.my.csdn.net/uploads/201209/28/1348823833_6296.png" alt="" style="border: none; max-width: 100%;" /><br /></p><p style="margin: 0px; padding: 0px;">各个程序运行状态时代理的回调：</p><p style="margin: 0px; padding: 0px;"><span style="color: #ff0000;">- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions<br /></span>&nbsp; &nbsp; &nbsp; 告诉代理进程启动但还没进入状态保存<br /><span style="color: #ff0000;">- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions<br /></span>&nbsp; &nbsp; &nbsp;告诉代理启动基本完成程序准备开始运行<br /><span style="color: #ff0000;">- (void)applicationWillResignActive:(UIApplication *)application<br /></span>&nbsp; &nbsp; 当应用程序将要入非活动状态执行，在此期间，应用程序不接收消息或事件，比如来电话了<br /><span style="color: #ff0000;">- (void)applicationDidBecomeActive:(UIApplication *)application&nbsp;<br /></span>&nbsp; &nbsp; &nbsp;当应用程序入活动状态执行，这个刚好跟上面那个方法相反<br /><span style="color: #ff0000;">- (void)applicationDidEnterBackground:(UIApplication *)application<br /></span>&nbsp; &nbsp; 当程序被推送到后台的时候调用。所以要设置后台继续运行，则在这个函数里面设置即可<br /><span style="color: #ff0000;">- (void)applicationWillEnterForeground:(UIApplication *)application<br /></span><span style="white-space: pre;">	</span>当程序从后台将要重新回到前台时候调用，这个刚好跟上面的那个方法相反。<br /><span style="color: #ff0000;">- (void)applicationWillTerminate:(UIApplication *)application<br /></span><span style="white-space: pre;">	</span>当程序将要退出是被调用，通常是用来保存数据和一些退出前的清理工作。这个需要要设置UIApplicationExitsOnSuspend的键值。<br /><span style="color: #ff0000;">- (void)applicationDidFinishLaunching:(UIApplication*)application<br /></span><span style="white-space: pre;">	</span>当程序载入后执行<br /></p><p style="margin: 0px; padding: 0px;">在上面8个方法对应的方法中键入NSLog打印。</p><p style="margin: 0px; padding: 0px;">现在启动程序看看执行的顺序：</p><p style="margin: 0px; padding: 0px;">启动程序<br />lifeCycle[40428:11303] willFinishLaunchingWithOptions<br />lifeCycle[40428:11303] didFinishLaunchingWithOptions<br />lifeCycle[40428:11303] applicationDidBecomeActive</p><p style="margin: 0px; padding: 0px;">按下home键</p><p style="margin: 0px; padding: 0px;">lifeCycle[40428:11303] applicationWillResignActive<br />lifeCycle[40428:11303] applicationDidEnterBackground<br /></p><p style="margin: 0px; padding: 0px;">双击home键，再打开程序</p><p style="margin: 0px; padding: 0px;">lifeCycle[40428:11303] applicationWillEnterForeground<br />lifeCycle[40428:11303] applicationDidBecomeActive<br /></p><h2><a name="t1" style="color: rgb(255, 153, 0);"></a>2、应用程序的生命周期</h2><h3><a name="t2" style="color: rgb(255, 153, 0);"></a>2.1、加载应用程序进入前台</h3><p style="margin: 0px; padding: 0px;"><img src="http://img.my.csdn.net/uploads/201209/29/1348884482_7300.png" alt="" style="border: none; max-width: 100%;" /><br /></p><h3><a name="t3" style="color: rgb(255, 153, 0);"></a>2.2、加载应用程序进入后台</h3><p style="margin: 0px; padding: 0px;"><img src="http://img.my.csdn.net/uploads/201209/29/1348884525_3194.png" alt="" style="border: none; max-width: 100%;" /><br /></p><p style="margin: 0px; padding: 0px;"><br /></p><h3><a name="t4" style="color: rgb(255, 153, 0);"></a>2.3、关于main函数</h3><p style="margin: 0px; padding: 0px;">main函数是程序启动的入口，在iOS app中，main函数的功能被最小化，它的主要工作都交给了UIKit framework</p><p style="margin: 0px; padding: 0px;"></p><div bg_cpp"="" style="width: 936.53125px;"><div><div><strong>[cpp]</strong>&nbsp;<a href="http://blog.csdn.net/totogo2010/article/details/8048652#" title="view plain" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_plain.gif); background-position: 0% 0%; background-repeat: no-repeat;">view plain</a><a href="http://blog.csdn.net/totogo2010/article/details/8048652#" title="copy" style="padding: 1px; display: inline-block; width: 16px; height: 16px; text-indent: -2000px; background-image: url(http://static.blog.csdn.net/scripts/SyntaxHighlighter/styles/images/default/ico_copy.gif); background-position: 0% 0%; background-repeat: no-repeat;">copy</a><div style="position: absolute; left: 549px; top: 3530px; width: 18px; height: 18px; z-index: 99;"></div></div></div><ol start="1"><li style="line-height: 18px;">#import&nbsp;&lt;UIKit/UIKit.h&gt;&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;</li><li style="line-height: 18px;"><span style="color: #2e8b57; font-weight: bold;">int</span>&nbsp;main(<span style="color: #2e8b57; font-weight: bold;">int</span>&nbsp;argc,&nbsp;<span style="color: #2e8b57; font-weight: bold;">char</span>&nbsp;*argv[])&nbsp;&nbsp;</li><li style="line-height: 18px;">{&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;@autoreleasepool&nbsp;{&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;UIApplicationMain(argc,&nbsp;argv,&nbsp;nil,&nbsp;NSStringFromClass([MyAppDelegate&nbsp;class]));&nbsp;&nbsp;</li><li style="line-height: 18px;">&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li style="line-height: 18px;">}&nbsp;&nbsp;</li></ol></div><br />UIApplicationMain函数有四个参数，你不需要改变这些参数值，不过我们也需要理解这些参数和程序是如何开始的<p style="margin: 0px; padding: 0px;"></p><p style="margin: 0px; padding: 0px;">argc 和argv参数包含了系统带过来的启动时间。 &nbsp;第三个参数确定了主要应用程序类的名称，这个参数指定为nil，这样UIKit就会使用默认的程序类UIApplication。第四个参数是程序自定义的代理类名，这个类负责系统和代码之间的交互。它一般在Xcode新建项目时会自动生成。</p><p style="margin: 0px; padding: 0px;">另外 UIApplicationMain函数加载了程序主界面的文件。虽然这个函数加载了界面文件，但是没有放到应用程序的windows上，你需要在Delegate的&nbsp;application:willFinishLaunchingWithOptions方法中加载它。</p><p style="margin: 0px; padding: 0px;">一个应用程序可以有一个主的storyboard文件或者有一个主的nib文件，但不能同时有两个存在。</p><p style="margin: 0px; padding: 0px;">如果程序在启动时没有自动加载主要的故事版或nib文件，你可以在application:willFinishLaunchingWithOptions方法里准备windows的展示。</p><h2><a name="t5" style="color: rgb(255, 153, 0);"></a>3、响应中断</h2><h3><a name="t6" style="color: rgb(255, 153, 0);"></a>3.1 当一个基于警告式的中断发生时，比如有电话打进来了，这是程序会临时进入inactive状态，这用户可以选择如何处理这个中断，流程如下图：</h3><p style="margin: 0px; padding: 0px;"><img src="http://img.my.csdn.net/uploads/201209/29/1348885212_1391.png" alt="" style="border: none; max-width: 100%;" /><br /></p><p style="margin: 0px; padding: 0px;">在iOS5,通知不会把程序变成为激活状态，通知会显示在状态栏上，如果你；拉下状态栏，程序会变成inactive,把状态栏放回去，程序变回active。</p><p style="margin: 0px; padding: 0px;">按锁屏键也是另外一种程序的中断，当你按下锁屏键，系统屏蔽了所有触摸事件，把app放到了后台，这时app状态是 inactive，并进入后台。</p><h3><a name="t7" style="color: rgb(255, 153, 0);"></a>3.2 当有这些中断时，我们的app该怎么办呢？我们应该在<a href="http://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIApplicationDelegate/applicationWillResignActive:" target="_self" style="color: #003366; text-decoration: none; font-family: Courier, Consolas, monospace; font-size: 14.44444465637207px;">applicationWillResignActive:</a>方法中：</h3><p style="margin: 0px; padding: 0px;"></p><ul><li>停止timer 和其他周期性的任务</li><li>停止任何正在运行的请求</li><li>暂停视频的播放</li><li>如果是游戏那就暂停它</li><li>减少OpenGL ES的帧率</li><li>挂起任何分发的队列和不重要的操作队列（你可以继续处理网络请求或其他时间敏感的后台任务）。</li></ul><div>当程序回到active状态 ， &nbsp;&nbsp;<code style="font-size: 14.44444465637207px; font-family: Courier, Consolas, monospace; color: #666666;"><a href="http://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIApplicationDelegate/applicationDidBecomeActive:" target="_self" style="color: #003366; text-decoration: none;">applicationDidBecomeActive:</a></code>&nbsp;&nbsp; 方法应该上面提到的任务重新开始，比如重新开始timer, 继续分发队列，提高OpenGL ES的帧率。不过游戏要回到暂停状态，不能自动开始。</div><h2><a name="t8" style="color: rgb(255, 153, 0);"></a>4、转到后台运行</h2><h3><a name="t9" style="color: rgb(255, 153, 0);"></a>4.1 如图所示：</h3><div><img src="http://img.my.csdn.net/uploads/201209/29/1348886673_9662.png" alt="" style="border: none; max-width: 100%;" /></div><div>PS:只有在IOS4以上系统或者支持多任务的设备才能后台运行。不然会直接结束状态。</div><h3><a name="t10" style="color: rgb(255, 153, 0);"></a>4.2 当应用程序进入后台时，我们应该做写什么呢？</h3><div><ul><li>保存用户数据或状态信息，所有没写到磁盘的文件或信息，在进入后台时，最后都写到磁盘去，因为程序可能在后台被杀死，</li><li>释放尽可能释放的内存</li></ul><div>applicationDidEnterBackgound: 方法有大概5秒的时间让你完成这些任务。如果超过时间还有未完成的任务，你的程序就会被终止而且从内存中清除。如果还需要长时间的运行任务，可以调用 &nbsp;<span style="color: #666666; font-family: Courier, Consolas, monospace; font-size: 14.44444465637207px;">beginBackgroundTaskWithExpirationHandler</span>&nbsp; &nbsp; &nbsp; &nbsp;方法去请求后台运行时间和启动线程来运行长时间运行的任务。</div></div><div>4.3 应用程序在后台时的内存使用</div><div>在后台时，每个应用程序都应该释放最大的内存。系统努力的保持更多的应用程序在后台同时 运行。不过当内存不足时，会终止一些挂起的程序来回收内存，那些内存最大的程序首先被终止。</div><div>事实上，应用程序应该的对象如果不再使用了，那就应该尽快的去掉强引用，这样编译器可以回收这些内存。如果你想缓存一些对象提升程序的性能，你可以在进入后台时，把这些对象去掉强引用。</div><div>下面这样的对象应该尽快的去掉强引用：</div><div><ul><li>图片对象</li><li>你可以重新加载的 大的视频或数据文件</li><li>任何没用而且可以轻易创建的对象</li></ul></div><div>在后台时，为了减少程序占用的内存，系统会自动在回收一些系统帮助你开辟的内存。比如：</div><div>系统回收Core Animation的后备存储。</div><div>去掉任何系统引用的缓存图片</div><div>去掉系统管理数据缓存强引用</div><div></div><h2><a name="t11" style="color: rgb(255, 153, 0);"></a>5 、返回前台运行</h2><div>流程如图所示：</div><div><img src="http://img.my.csdn.net/uploads/201209/29/1348889472_5280.png" alt="" style="border: none; max-width: 100%;" /></div><div>当app处于挂起状态时，它是不能执行任何代码的。因此它不能处理在挂起期间发过来的通知，比如方向改变，时间改变，设置的改变还有其他影响程序展现的或状态的通知。在程序返回后台或前台是，程序都要正确的处理这些通知。</div><h2><a name="t12" style="color: rgb(255, 153, 0);"></a>6、程序的终止</h2><div>程序只要符合以下情况之一，只要进入后台或挂起状态就会终止：</div><div>iOS4.0以前的系统</div><div>app是基于iOS4.0之前系统开发的。</div><div>设备不支持多任务</div><div>在Info.plist文件中，程序包含了&nbsp;<span style="color: #666666; font-family: Courier, Consolas, monospace; font-size: 14.44444465637207px;">UIApplicationExitsOnSuspend</span>&nbsp; 键。</div><div>app如果终止了 &nbsp;,系统会调用app的代理的方法&nbsp;<a href="http://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/UIApplicationDelegate/applicationWillTerminate:" target="_self" style="color: #003366; text-decoration: none; font-family: Courier, Consolas, monospace; font-size: 14.44444465637207px;">applicationWillTerminate:</a>&nbsp; &nbsp;这样可以让你可以做一些清理工作。你可以保存一些数据或app的状态。这个方法也有5秒钟的限制。超时后方法会返回程序从内存中清除。</div><div>注意：用户可以手工关闭应用程序。</div><h2><a name="t13" style="color: rgb(255, 153, 0);"></a>7、 The Main Run Loop &nbsp;主运行循环</h2><div>Main Run Loop负责处理用户相关的事件。UIApplication对象在程序启动时启动main run Loop，它处理事件和更新视图的界面。看Main Run Loop就知道，它是运行在程序的主线程上的。这样保证了接收到用户相关操作的事件是按顺序处理的。</div><div></div><div><strong>Main Run Loop &nbsp;处理事件的架构图：</strong></div><div></div><div><img src="http://img.my.csdn.net/uploads/201210/08/1349677876_6777.png" alt="" style="border: none; max-width: 100%;" /></div><div>用户操作设备，相关的操作事件被系统生成并通过UIKit的指定端口分发。事件在内部排成队列，一个个的分发到Main run loop 去做处理。UIApplication对象是第一个接收到时间的对象，它决定事件如何被处理。触摸事件分发到主窗口，窗口再分发到对应出发触摸事件的View。其他的事件通过其他途径分发给其他对象变量做处理。</div><div></div><div>大部分的事件可以在你的应用里分发，类似于触摸事件，远程操控事件（线控耳机等）都是由app的&nbsp;<a href="http://developer.apple.com/library/ios/#documentation/general/conceptual/Devpedia-CocoaApp/Responder.html" target="_blank" style="color: #ff9900; text-decoration: none;">responder objects</a>&nbsp;对象处理的。Responder objects 在你的app里到处都是，比如：UIApplication 对象。view对象，view controller 对象，都是resopnder objects。大部分事件的目标都指定了resopnder object，不过事件也可以传递给其他对象。比如，如果view对象不处理事件，可以传给父类view或者view controller。</div><div></div><div>参考：https://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html#//apple_ref/doc/uid/TP40007072-CH4-SW20</div><div><p style="margin: 0px; padding: 0px; font-family: Arial; font-size: 13.63636302947998px; line-height: 26px; background-color: #ffffff;"></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: verdana, 宋体, Arial; font-size: 13px; line-height: 24px; background-color: #ffffff;"><span style="color: #ff0000;">容芳志 (<a href="http://blog.csdn.net/totogo2010" target="_blank" style="color: #ff9900; text-decoration: none; margin: 0px; padding: 0px; border-bottom-width: 1px; border-bottom-style: dotted; border-bottom-color: #333333;">http://blog.csdn.net/totogo2010</a>)</span></p><p style="margin-top: 10px; margin-bottom: 10px; padding: 0px; font-family: verdana, 宋体, Arial; font-size: 13px; line-height: 24px; background-color: #ffffff;"><span style="color: #ff0000;">本文遵循&#8220;<a href="http://creativecommons.org/licenses/by-nc-sa/2.5/cn/" target="_blank" style="color: #ff9900; text-decoration: none; margin: 0px; padding: 0px; border-bottom-width: 1px; border-bottom-style: dotted; border-bottom-color: #333333;">署名-非商业用途-保持一致</a>&#8221;创作公用协议</span></p></div><div><span style="color: #ff0000;"><br /></span></div></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/416091.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-07-22 18:01 <a href="http://www.blogjava.net/xiaomage234/archive/2014/07/22/416091.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ios企业版发布 https证书以及服务器设置</title><link>http://www.blogjava.net/xiaomage234/archive/2014/06/26/415163.html</link><dc:creator>小马歌</dc:creator><author>小马歌</author><pubDate>Thu, 26 Jun 2014 13:42:00 GMT</pubDate><guid>http://www.blogjava.net/xiaomage234/archive/2014/06/26/415163.html</guid><wfw:comment>http://www.blogjava.net/xiaomage234/comments/415163.html</wfw:comment><comments>http://www.blogjava.net/xiaomage234/archive/2014/06/26/415163.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/xiaomage234/comments/commentRss/415163.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xiaomage234/services/trackbacks/415163.html</trackback:ping><description><![CDATA[<span style="font-family: Tahoma; line-height: 24px;">url:</span>http://www.myexception.cn/operating-system/1525825.html<span style="font-family: Tahoma; line-height: 24px;"><br /></span><span style="font-family: Tahoma; line-height: 24px;">使用IOS企业版证书发布应用</span><br style="margin: 0px; padding: 0px; font-family: Tahoma; line-height: 24px;" /><div style="margin: 0px;"><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;">&nbsp; &nbsp; &nbsp; &nbsp; 苹果的企业开发证书，可以不经app store,直接发布到自己的网站上。其他人可以直接下载安装。但前提要用苹果自带的浏览器（safari)才能下载，其他浏览器不能识别该协议。</p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;">&nbsp; &nbsp; &nbsp; &nbsp; 一、制作证书</p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;">&nbsp; &nbsp; &nbsp; &nbsp;打开Keychain Access工具，把Keychain的配置改为如下图:</p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;"><br style="margin: 0px; padding: 0px;" /><img alt="" src="http://www.myexception.cn/img/2014/02/21/10171087.png" style="margin: 0px; padding: 0px; max-width: 579px; height: auto;" /></p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;">并从菜单中选择Keycahin Access-&gt;Certificate Assistant-&gt;Request a Certificate From a Certificate Authority...如下图所示：</p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;"><img alt="" src="http://www.myexception.cn/img/2014/02/21/10171088.png" style="margin: 0px; padding: 0px; max-width: 579px; height: auto;" /><br style="margin: 0px; padding: 0px;" />&nbsp;填写必要的信息，生成证书保存在桌面或其他地方，等会要用到：</p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;"><br style="margin: 0px; padding: 0px;" /><img alt="" src="http://www.myexception.cn/img/2014/02/21/10171089.png" style="margin: 0px; padding: 0px; max-width: 579px; height: auto;" /></p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;"><br style="margin: 0px; padding: 0px;" /><img alt="" src="http://www.myexception.cn/img/2014/02/21/10171090.png" style="margin: 0px; padding: 0px; max-width: 579px; height: auto;" /><br style="margin: 0px; padding: 0px;" />&nbsp;<br style="margin: 0px; padding: 0px;" />&nbsp;二、生成并安装证书</p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;">&nbsp; &nbsp; &nbsp; &nbsp; 用企业版的apple id登陆苹果开发者中心: https://developer.apple.com， 登陆后选择对应的选项，上传之前生成的证书文件，如下图：</p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;"><img alt="" src="http://www.myexception.cn/img/2014/02/21/10171091.png" style="margin: 0px; padding: 0px; max-width: 579px; height: auto;" /><br style="margin: 0px; padding: 0px;" />&nbsp;</p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;">&nbsp;生成证书文件后，下载下来，双击打开即安装。</p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;">三、增加APP ID</p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;">四、生成Profiles文件</p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;">在开发中心点击Provisioning Profiles中的Distribution, 点击&#8220;+&#8221;，增加Profiles。APP ID选择刚才增加的。如图<br style="margin: 0px; padding: 0px;" />&nbsp;<br style="margin: 0px; padding: 0px;" /><img alt="" src="http://www.myexception.cn/img/2014/02/21/10171092.png" style="margin: 0px; padding: 0px; max-width: 579px; height: auto;" /><br style="margin: 0px; padding: 0px;" />添加好之后，就可以下载下来，把它拖到Xcode中。或是拖到Organizer中。如图：</p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;"><br style="margin: 0px; padding: 0px;" /><img alt="" src="http://www.myexception.cn/img/2014/02/21/10171093.png" style="margin: 0px; padding: 0px; max-width: 579px; height: auto;" /><br style="margin: 0px; padding: 0px;" />&nbsp;</p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;">五、发布应用</p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;">在XCode的Targets中选择签名:</p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;"><br style="margin: 0px; padding: 0px;" /><img alt="" src="http://www.myexception.cn/img/2014/02/21/10171094.png" style="margin: 0px; padding: 0px; max-width: 579px; height: auto;" /><br style="margin: 0px; padding: 0px;" />&nbsp;在XCode的菜单Product-&gt;Archive中选择打包。打包时要把iPad或是iphone接到电脑上，并选择目标是iPad或是iphone才能成功。</p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;"><br style="margin: 0px; padding: 0px;" /><img alt="" src="http://www.myexception.cn/img/2014/02/21/10171095.png" style="margin: 0px; padding: 0px; max-width: 579px; height: auto;" /></p><p style="font-family: Tahoma; line-height: 24px; margin: 0px; padding: 0px;"><br style="margin: 0px; padding: 0px;" />&nbsp;<br style="margin: 0px; padding: 0px;" /><img alt="" src="http://www.myexception.cn/img/2014/02/21/10171096.png" style="margin: 0px; padding: 0px; max-width: 579px; height: auto;" /><br style="margin: 0px; padding: 0px;" />&nbsp;<br style="margin: 0px; padding: 0px;" /><img alt="" src="http://www.myexception.cn/img/2014/02/21/10171097.png" style="margin: 0px; padding: 0px; max-width: 579px; height: auto;" /><br /><br /><br /></p><div style="display: inline-block;"><span style="color: #464646; font-family: simsun; line-height: 21px; background-color: #f8ecd8;">Required的信息填写即可，save，则会同时生成ipa和plist 文件，如下</span><br style="color: #464646; font-family: simsun; line-height: 21px; background-color: #f8ecd8;" /><img alt="" title="iOS开发--in&nbsp;<wbr />house&nbsp;<wbr>企业发布" style="border: 0px; max-width: 100%; margin: 0px; padding: 0px; list-style: none; color: #464646; font-family: simsun; line-height: 21px; background-color: #f8ecd8;"><br style="color: #464646; font-family: simsun; line-height: 21px; background-color: #f8ecd8;" /><img src="http://img.blog.csdn.net/20140109091257937?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveHVlZXI4ODM1/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" style="border: none; max-width: 100%;" /></div><p>&nbsp;</p><p style="font-family: Tahoma; line-height: 24px;"><span style="color: #464646; font-family: simsun; line-height: 21px; background-color: #f8ecd8;">apple文档地址：</span><a target="_blank" href="http://developer.apple.com/library/ios/#featuredarticles/FA_Wireless_Enterprise_App_Distribution/Introduction/Introduction.html" style="color: #765f47; text-decoration: none; font-family: simsun; line-height: 21px; background-color: #f8ecd8;">http://developer.apple.com/library/ios/#featuredarticles/FA_Wireless_Enterprise_App_Distribution/Introduction/Introduction.html</a></p><p style="font-family: Tahoma; line-height: 24px;"><br /></p><p style="font-family: Tahoma; line-height: 24px;"></p><div style="font-family: 'Lucida Grande', Helvetica, Arial, sans-serif; line-height: 1.4; margin: 0px 0px 0.7em; padding-top: 18px; padding-right: 35px; bottom: 0px; font-size: 1.5em; min-width: 200px; overflow: hidden; position: relative;">以无线方式安装应用程序</div><p style="font-family: Tahoma; line-height: 24px;"></p><p style="font-family: 'Lucida Grande', Helvetica, Arial, sans-serif; line-height: 18px; margin-top: 0.3em; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px; color: #555555;">iOS 支持以无线方式安装企业级应用程序，这可让您在不使用 iTunes 的情况下将内部软件分发给用户。</p><p style="font-family: 'Lucida Grande', Helvetica, Arial, sans-serif; line-height: 18px; margin-top: 0.3em; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px; color: #555555;"><span style="font-style: italic;">要求</span></p><ul style="font-family: 'Lucida Grande', Helvetica, Arial, sans-serif; line-height: 18px; margin: 0.3em 0px 0.9em 1.5em; padding: 0px; list-style: none; color: #555555;"><li style="margin: 0.3em 0px 0.9em; padding: 0px; list-style: disc;"><p style="margin-top: 0.3em; margin-bottom: 0.9em; margin-left: 0.25em; padding-top: 0px; padding-bottom: 0px;">已鉴定的用户可访问的安全 Web 服务器</p></li><li style="margin: 0.3em 0px 0.9em; padding: 0px; list-style: disc;"><p style="margin-top: 0.3em; margin-bottom: 0.9em; margin-left: 0.25em; padding-top: 0px; padding-bottom: 0px;">.ipa 格式的 iOS 应用程序，经构建用于发布/生产（使用了企业级预置描述文件）</p></li><li style="margin: 0.3em 0px 0.9em; padding: 0px; list-style: disc;"><p style="margin-top: 0.3em; margin-bottom: 0.9em; margin-left: 0.25em; padding-top: 0px; padding-bottom: 0px;">本文稿中稍后描述的 XML 清单文件</p></li><li style="margin: 0.3em 0px 0.9em; padding: 0px; list-style: disc;"><p style="margin-top: 0.3em; margin-bottom: 0.9em; margin-left: 0.25em; padding-top: 0px; padding-bottom: 0px;">可让设备访问 Apple iTunes 服务器的网络配置</p></li></ul><p style="font-family: 'Lucida Grande', Helvetica, Arial, sans-serif; line-height: 18px; margin-top: 0.3em; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px; color: #555555;">安装应用程序很简单。用户可以将清单文件从您的网站上下载到他们的 iOS 设备上。该清单文件会指示设备下载和安装该清单文件中所引用的应用程序。</p><p style="font-family: 'Lucida Grande', Helvetica, Arial, sans-serif; line-height: 18px; margin-top: 0.3em; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px; color: #555555;">您可以分发 URL 以便通过短信或电子邮件来下载清单文件，也可以将它嵌入您所创建的其他企业级应用程序中。</p><p style="font-family: 'Lucida Grande', Helvetica, Arial, sans-serif; line-height: 18px; margin-top: 0.3em; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px; color: #555555;">由您设计和主管用于分发应用程序的网站。确定用户已被鉴定（可能是使用基本鉴定或基于目录的鉴定），并确定网站可通过内联网或互联网进行访问。您可以将应用程序和清单文件放入隐藏的目录中，或任何可使用 HTTP 或 HTTPS 来读取的其他位置中。</p><div style="font-family: 'Lucida Grande', Helvetica, Arial, sans-serif; line-height: 18px; margin: 0px; color: #555555;"><p style="margin-top: 1.25em; margin-bottom: 0.25em; padding-top: 0px; padding-bottom: 0px; color: #000000; font-weight: bold;">准备企业级应用程序进行无线分发</p><p style="margin-top: 0px; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px;">若要准备企业级应用程序进行无线分发，您应该构建归档的版本（.ipa 文件），以及构建清单文件以启用应用程序的无线分发和安装。</p><p style="margin-top: 0.3em; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px;">使用 Xcode 来创建应用程序归档。使用您的分发证书给应用程序签名并在归档中包括您的企业级开发预置描述文件。有关清单文件的信息，请参阅以下内容。有关构建和归档应用程序的更多信息，请访问 iOS Dev Center（iOS 开发中心）或参阅《<span style="font-style: italic;">Xcode User Guide</span>》（Xcode 使用手册），可通过 Xcode 中的&#8220;Help&#8221;（帮助）菜单来访问该使用手册。</p></div><div style="font-family: 'Lucida Grande', Helvetica, Arial, sans-serif; line-height: 18px; margin: 0px; color: #555555;"><p style="margin-top: 1.25em; margin-bottom: 0.25em; padding-top: 0px; padding-bottom: 0px; color: #000000; font-weight: bold;">关于无线清单文件</p><p style="margin-top: 0px; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px;">清单文件是 XML plist 格式的。iOS 设备使用它在 Web 服务器上查找应用程序，以及从 Web 服务器上下载和安装应用程序。清单文件是由 Xcode 创建的，使用您在共享归档的应用程序以进行企业级分发时所提供的信息。请参阅上一节<a target="_blank" href="http://help.apple.com/iosdeployment-apps/mac/1.1/#app43ad8905" style="color: #2c81b0; text-decoration: none; line-height: inherit; outline: none; position: relative;">准备应用程序进行分发</a>。</p><p style="margin-top: 0.3em; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px;">以下栏是必填的：</p><table "="" type="2 column" style="border: none; border-collapse: collapse; font-size: 10px; line-height: 1.6; margin-bottom: 2em; margin-left: -0.5em; margin-top: 1.65em; padding-top: 0px; table-layout: fixed; width: 770px;"><thead><tr style="border: none; border-spacing: 1px; background-color: #9ba0af;"><th style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; font-weight: normal; border: none; vertical-align: top;"><p style="margin-top: 0px; margin-bottom: -0.2em; padding-top: 0px; padding-bottom: 0px; color: #ffffff; font-weight: bold;">项目</p></th><th style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; font-weight: normal; border: none; vertical-align: top;"><p style="margin-top: 0px; margin-bottom: -0.2em; padding-top: 0px; padding-bottom: 0px; color: #ffffff; font-weight: bold;">描述</p></th></tr></thead><tbody><tr style="border-right-style: none; border-bottom-style: solid; border-left-style: none; border-bottom-width: 1px; border-bottom-color: #e4e4e4; margin-bottom: 0.75em; margin-top: 0.75em; border-top-style: none !important;"><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">URL</p></td><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">应用程序 (.ipa) 文件的完整合格的 HTTP 或 HTTPS URL。</p></td></tr><tr style="border-right-style: none; border-bottom-style: solid; border-left-style: none; border-bottom-width: 1px; border-bottom-color: #e4e4e4; margin-bottom: 0.75em; margin-top: 0.75em; border-top-style: none !important;"><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">display-image</p></td><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">下载和安装过程中显示的 57 x 57 像素 PNG 图像。指定图像的完整合格的 URL。</p></td></tr><tr style="border-right-style: none; border-bottom-style: solid; border-left-style: none; border-bottom-width: 1px; border-bottom-color: #e4e4e4; margin-bottom: 0.75em; margin-top: 0.75em; border-top-style: none !important;"><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">full-size-image</p></td><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">用来在 iTunes 中表示应用程序的 512 x 512 像素 PNG 图像。</p></td></tr><tr style="border-right-style: none; border-bottom-style: solid; border-left-style: none; border-bottom-width: 1px; border-bottom-color: #e4e4e4; margin-bottom: 0.75em; margin-top: 0.75em; border-top-style: none !important;"><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">bundle-identifier</p></td><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">您应用程序的包标识符，与 Xcode 项目中指定的完全一样。</p></td></tr><tr style="border-right-style: none; border-bottom-style: solid; border-left-style: none; border-bottom-width: 1px; border-bottom-color: #e4e4e4; margin-bottom: 0.75em; margin-top: 0.75em; border-top-style: none !important;"><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">bundle-version</p></td><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">您应用程序的包版本，在 Xcode 项目中指定。</p></td></tr><tr style="border-right-style: none; border-bottom-style: solid; border-left-style: none; border-bottom-width: 1px; border-bottom-color: #e4e4e4; margin-bottom: 0.75em; margin-top: 0.75em; border-top-style: none !important;"><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">title</p></td><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">下载和安装过程中显示的应用程序的名称。</p></td></tr></tbody></table><p style="margin-top: 0.3em; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px;">仅对于&#8220;报刊杂志&#8221;应用程序，需要填写以下栏位：</p><table "="" type="2 column" style="border: none; border-collapse: collapse; font-size: 10px; line-height: 1.6; margin-bottom: 2em; margin-left: -0.5em; margin-top: 1.65em; padding-top: 0px; table-layout: fixed; width: 770px;"><thead><tr style="border: none; border-spacing: 1px; background-color: #9ba0af;"><th style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; font-weight: normal; border: none; vertical-align: top;"><p style="margin-top: 0px; margin-bottom: -0.2em; padding-top: 0px; padding-bottom: 0px; color: #ffffff; font-weight: bold;">项目</p></th><th style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; font-weight: normal; border: none; vertical-align: top;"><p style="margin-top: 0px; margin-bottom: -0.2em; padding-top: 0px; padding-bottom: 0px; color: #ffffff; font-weight: bold;">描述</p></th></tr></thead><tbody><tr style="border-right-style: none; border-bottom-style: solid; border-left-style: none; border-bottom-width: 1px; border-bottom-color: #e4e4e4; margin-bottom: 0.75em; margin-top: 0.75em; border-top-style: none !important;"><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">newsstand-image</p></td><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">完整大小的 PNG 图像，用于显示在&#8220;报刊杂志&#8221;书架上。</p></td></tr><tr style="border-right-style: none; border-bottom-style: solid; border-left-style: none; border-bottom-width: 1px; border-bottom-color: #e4e4e4; margin-bottom: 0.75em; margin-top: 0.75em; border-top-style: none !important;"><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">UINewsstandBindingEdge</p><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.65em !important; margin-bottom: 0.3em !important;">UINewsstandBindingType</p></td><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">这些键必须与&#8220;报刊杂志&#8221;应用程序中的 info.plist 中的键相符。</p></td></tr><tr style="border-right-style: none; border-bottom-style: solid; border-left-style: none; border-bottom-width: 1px; border-bottom-color: #e4e4e4; margin-bottom: 0.75em; margin-top: 0.75em; border-top-style: none !important;"><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">UINewsstandApp</p></td><td style="margin: 0px; padding: 0.25em 0.6em 0.35em 0.5em; border: none; vertical-align: top;"><p style="padding-top: 0px; padding-bottom: 0px; margin-top: 0.4em !important; margin-bottom: 0.3em !important;">指示该应用程序是&#8220;报刊杂志&#8221;应用程序。</p></td></tr></tbody></table><p style="margin-top: 0.3em; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px;">您可以使用的一些可选键如示例清单文件所述。例如，如果应用程序文件太大并且您想要在执行错误检验（TCP 通信通常会执行该操作）的基础上确保下载的完整性，则可以使用 MD5 键。</p><p style="margin-top: 0.3em; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px;">您可以使用单个清单文件安装多个应用程序，方法是指定&nbsp;<span style="font-family: Courier, 'Courier New', monospace;">items</span>&nbsp;数组的附加成员。</p><p style="margin-top: 0.3em; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px;">本文稿末尾列出了示例清单文件。</p></div><div style="font-family: 'Lucida Grande', Helvetica, Arial, sans-serif; line-height: 18px; margin: 0px; color: #555555;"><p style="margin-top: 1.25em; margin-bottom: 0.25em; padding-top: 0px; padding-bottom: 0px; color: #000000; font-weight: bold;">构建网站</p><p style="margin-top: 0px; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px;">将这些项目上传到您网站上已鉴定的用户可以访问的区域：</p><ul style="margin: 0.3em 0px 0.9em 1.5em; padding: 0px; list-style: none;"><li style="margin: 0.3em 0px 0.9em; padding: 0px; list-style: disc;"><p style="margin-top: 0.3em; margin-bottom: 0.9em; margin-left: 0.25em; padding-top: 0px; padding-bottom: 0px;">应用程序 (.ipa) 文件</p></li><li style="margin: 0.3em 0px 0.9em; padding: 0px; list-style: disc;"><p style="margin-top: 0.3em; margin-bottom: 0.9em; margin-left: 0.25em; padding-top: 0px; padding-bottom: 0px;">清单 (.plist) 文件</p></li></ul><p style="margin-top: 0.3em; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px;">您的网站设计可以像用来链接到清单文件的单个页面那么简单。当用户轻按 Web 链接时，清单文件会被下载，并触发它所描述的应用程序的下载和安装。</p><p style="margin-top: 0.3em; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px;">以下是一个示例链接：</p><div style="margin: 0.25em 0px 0.75em; font-family: Courier, 'Courier New', monospace;"><p style="margin-top: 0.25em; margin-bottom: 0.25em; padding-top: 0px; padding-bottom: 0px; overflow: hidden; text-overflow: ellipsis;">&lt;a href="itms-services://?action=download-manifest&amp;url=http://example.com/&#8232;manifest.plist"&gt;Install App&lt;/a&gt;</p></div><p style="margin-top: 0.3em; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px;">请勿添加归档的应用程序 (.ipa) 的 Web 链接。载入清单文件时，设备会下载该 .ipa。虽然 URL 的协议部分是 itms-services，但 iTunes Store 并不参与此过程。</p></div><div style="font-family: 'Lucida Grande', Helvetica, Arial, sans-serif; line-height: 18px; margin: 0px; color: #555555;"><p style="margin-top: 1.25em; margin-bottom: 0.25em; padding-top: 0px; padding-bottom: 0px; color: #000000; font-weight: bold;">设定服务器 MIME 类型</p><p style="margin-top: 0px; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px;">您可能需要配置您的 Web 服务器以便正确地传输清单文件和应用程序文件。</p><p style="margin-top: 0.3em; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px;">对于 OS X Server，将以下 MIME 类型添加到 Web 服务的&#8220;MIME Types&#8221;（MIME 类型）设置中：</p><div style="margin: 0.25em 0px 0.75em; font-family: Courier, 'Courier New', monospace;"><p style="margin-top: 0.25em; margin-bottom: 0.25em; padding-top: 0px; padding-bottom: 0px; overflow: hidden; text-overflow: ellipsis;">application/octet-stream ipa</p><p style="margin-top: 0.25em; margin-bottom: 0.25em; padding-top: 0px; padding-bottom: 0px; overflow: hidden; text-overflow: ellipsis;">text/xml plist</p></div><p style="margin-top: 0.3em; margin-bottom: 0.9em; padding-top: 0px; padding-bottom: 0px;">对于 IIS，使用 IIS Manager 在服务器的&#8220;属性&#8221;页面中添加 MIME 类型：</p><div style="margin: 0.25em 0px 0.75em; font-family: Courier, 'Courier New', monospace;"><p style="margin-top: 0.25em; margin-bottom: 0.25em; padding-top: 0px; padding-bottom: 0px; overflow: hidden; text-overflow: ellipsis; background-color: #ffffff;">.ipa application/octet-stream</p><p style="margin-top: 0.25em; margin-bottom: 0.25em; padding-top: 0px; padding-bottom: 0px; overflow: hidden; text-overflow: ellipsis; background-color: #ffffff;">.plist text/xml</p><div></div></div></div><p style="margin: 0px; padding: 0px;"><span style="font-family: tahoma, helvetica, arial; line-height: 21px; color: #454545; background-color: #ffffff;">openssl使用的是macos系统自带的版本，关键点是不同直接使用ios设备打开https的链接，需要将证书发到系统的mail里，安装到设备，</span><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><span style="font-family: tahoma, helvetica, arial; line-height: 21px; color: #454545; background-color: #ffffff;">如果命令执行不成功，用sudo执行。</span><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><span style="font-family: tahoma, helvetica, arial; line-height: 21px; color: #454545; background-color: #ffffff;">1.生成服务器的私钥</span><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><span style="font-family: tahoma, helvetica, arial; line-height: 21px; color: #454545; background-color: #ffffff;">openssl&nbsp;genrsa&nbsp;-out&nbsp;server.key&nbsp;1024</span><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><span style="font-family: tahoma, helvetica, arial; line-height: 21px; color: #454545; background-color: #ffffff;">2.生成签署申请（注意除Common Name以外可以为空，Common Name必须为服务器的ip或域名）</span><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><span style="font-family: tahoma, helvetica, arial; line-height: 21px; color: #454545; background-color: #ffffff;">openssl&nbsp;req -new&nbsp;-key&nbsp;server.key&nbsp;-out&nbsp;server.csr</span><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><span style="font-family: tahoma, helvetica, arial; line-height: 21px; color: #454545; background-color: #ffffff;">3.生成CA私钥</span><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><span style="font-family: tahoma, helvetica, arial; line-height: 21px; color: #454545; background-color: #ffffff;">openssl&nbsp;genrsa&nbsp;&nbsp;-out&nbsp;ca.key&nbsp;1024&nbsp;</span><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><span style="font-family: tahoma, helvetica, arial; line-height: 21px; color: #454545; background-color: #ffffff;">4.利用CA的私钥产生CA的自签署证书</span><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><span style="font-family: tahoma, helvetica, arial; line-height: 21px; color: #454545; background-color: #ffffff;">openssl req&nbsp; -new -x509 -days 365 -key ca.key -out ca.crt</span><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><span style="font-family: tahoma, helvetica, arial; line-height: 21px; color: #454545; background-color: #ffffff;">5.在当前目录创建demoCA，里面创建文件index.txt和serial，serial内容为01，index.txt为空，以及文件夹newcerts</span><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><span style="font-family: tahoma, helvetica, arial; line-height: 21px; color: #454545; background-color: #ffffff;">openssl&nbsp;ca&nbsp;-in&nbsp;server.csr&nbsp;-out&nbsp;server.crt&nbsp;-cert&nbsp;ca.crt&nbsp;-keyfile&nbsp;ca.key</span><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><span style="font-family: tahoma, helvetica, arial; line-height: 21px; color: #454545; background-color: #ffffff;">将ca.crt文件通过邮件发送到ios设备的Mail上，进行证书的安装</span><br style="color: #454545; font-family: tahoma, helvetica, arial; line-height: 21px; background-color: #ffffff;" /><font color="#454545" face="tahoma, helvetica, arial"><span style="background-color: #ffffff;"><strong>nginx https配置:<br /></strong></span></font><br /><font face="Tahoma"><span style="line-height: 24px;">&nbsp;</span></font></p><div style="display: inline-block;"></div><p>&nbsp;</p><div><font face="Tahoma"><span style="line-height: 24px;">&nbsp; &nbsp; server {</span></font></div><p style="margin: 0px; padding: 0px;"><font face="Tahoma"><span style="line-height: 24px;"></span></font></p><div>&nbsp; &nbsp; &nbsp; &nbsp; listen &nbsp; &nbsp; &nbsp; 443;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; server_name &nbsp;ios.xxx.com;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; error_log &nbsp;/dev/null;</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; ssl &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;on;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ssl_certificate &nbsp; &nbsp; &nbsp;server.crt;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ssl_certificate_key &nbsp;server.key;</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; ssl_session_timeout &nbsp;5m;</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; #ssl_protocols &nbsp;SSLv2 SSLv3 TLSv1;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ssl_protocols &nbsp;SSLv3 TLSv1;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ssl_ciphers &nbsp;ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; ssl_prefer_server_ciphers &nbsp; on;</div><div></div><div>&nbsp; &nbsp; &nbsp; &nbsp; root &nbsp; /workspace/ios;</div><div>&nbsp; &nbsp; &nbsp; &nbsp; #add_header Content-Disposition: 'attachment;';</div><div>&nbsp; &nbsp; }</div></div><img src ="http://www.blogjava.net/xiaomage234/aggbug/415163.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xiaomage234/" target="_blank">小马歌</a> 2014-06-26 21:42 <a href="http://www.blogjava.net/xiaomage234/archive/2014/06/26/415163.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>