<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>诗意代码 - PoemCode &#187; Android</title>
	<atom:link href="http://www.poemcode.net/tag/android/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.poemcode.net</link>
	<description>These codes, As beautiful as poetry!</description>
	<lastBuildDate>Wed, 08 Sep 2010 04:57:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Android SDK Add-on Configure, Compile and Release</title>
		<link>http://www.poemcode.net/2010/09/android-sdk-addon/</link>
		<comments>http://www.poemcode.net/2010/09/android-sdk-addon/#comments</comments>
		<pubDate>Wed, 08 Sep 2010 02:25:33 +0000</pubDate>
		<dc:creator>Xu Haojie</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://www.poemcode.net/?p=1530</guid>
		<description><![CDATA[<div class="wp-caption alignright" style="width: 76px"><img class="size-full wp-image-521" title="Android" src="http://www.poemcode.net/wp-content/uploads/2009/09/android.gif" alt="Android" width="76" height="90" /></div> 

SDK Add-on 是一个比较小众的话题，一是通常厂商不会公开自己的add-on，二是即便公开了，应用开发者也很少使用。所以通常是厂商自己的技术团队自娱自乐，框架团队抽取公用的控件，制成一个 add-on，然后公布给自家的应用程序开发团队。

由于是小众的，所以网络中关于这方面的资料比较少。这几天由于工作原因，我有幸接触到 Add-on，因此把这方面的知识进行了汇总，整理成如下内容。这些知识来自于我对 sample 示例的理解，并经过项目实践验证，我竭力保证无误，但差错之处也可能存在，如发现，请指正。

以下内容将分成若个步骤：
<ol>
<li>添加模块；</li>
<li>添加资源文件；</li>
<li>加入编译脚本；</li>
<li>发布；</li>
</ol>]]></description>
			<content:encoded><![CDATA[<p>SDK Add-on 是一个比较小众的话题，一是通常厂商不会公开自己的add-on，二是即便公开了，应用开发者也很少使用。所以通常是厂商自己的技术团队自娱自乐，框架团队抽取公用的控件，制成一个 add-on，然后公布给自家的应用程序开发团队。</p>
<p>由于是小众的，所以网络中关于这方面的资料比较少。这几天由于工作原因，我有幸接触到 Add-on，因此把这方面的知识进行了汇总，整理成如下内容。这些知识来自于我对 sample 示例的理解，并经过项目实践验证，我竭力保证无误，但差错之处也可能存在，如发现，请指正。</p>
<p>以下内容将分成若个步骤：</p>
<ol>
<li>添加模块；</li>
<li>添加资源文件；</li>
<li>加入编译脚本；</li>
<li>发布；</li>
</ol>
<p>在阅读下面内容前，先假设是对 $ANDROID_HOME/device/sample 进行修改。</p>
<h2>一、添加模块（Add Module）</h2>
<p>在自己 <em>product-name</em> 目录下建立 frameworks 文件夹，从 sample 中拷贝 Android.mk 文件到 frameworks。</p>
<p>依照 sample 的方式，在 frameworks 路径下，建立 PlatformLibrary 文件夹，再次从 sample/frameworks 中拷贝 Android.mk 文件，并将其中的 LOCAL_MODULE 和 LOCAL_DROIDDOC_OPTIONS 修改为自己中意的名字。&#8211;这里值得注意的是，LOCAL_MODULE 变量被定义两次，第一次是 library，第二次是 document。</p>
<p>依照 sample/frameworks/com.example.android.platform_library.xml 的形式创建自己的 XML 文件，文件名称、XML 内容中 name 和 file 保持和 LOCAL_MODULE(library) 一致。</p>
<p>完成上述操作之后，建立 java 文件夹，并将自己创建的源文件（java）放入到其中，这里不再赘述。</p>
<h2>二、添加 Overlay(Add Resoruce)</h2>
<p>代码中可能需要访问图片、字符串等资源，但是这些在原有的 Android 中没有，因此需要想办法自行加入，Android 对此提供了两种方式。</p>
<p>第一种就是直接在 $ANDROID_HOME/framework/base/core/res/res 下进行操作，添加文件，追加字符串。这种方式虽然简单，但是破坏了原有的“纯洁性”，因此不予推荐，在第三节修改编译脚本中我采用了第二种方式。</p>
<p>第二种方式就是使用 overlay。在 product-name 目录下建立 overlay 文件夹，依照 framework 的结构建立各级目录，例如想添加图片，可以先依次建立 base/core/res/res/drawable，然后将图片置于其中，同样可以建立 layout 等文件夹。</p>
<p>如果要添加字符串或者 style 资源，就要稍微复杂一点，需要使用 add-resource 来让系统“明白”新添加的内容。</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;?xml</span> <span style="color: #000066;">version</span>=<span style="color: #ff0000;">&quot;1.0&quot;</span> <span style="color: #000066;">encoding</span>=<span style="color: #ff0000;">&quot;utf-8&quot;</span><span style="color: #000000; font-weight: bold;">?&gt;</span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;resources</span> <span style="color: #000066;">xmlns:xliff</span>=<span style="color: #ff0000;">&quot;urn:oasis:names:tc:xliff:document:1.2&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;add-resource</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;string&quot;</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;numwheel_year&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
    <span style="color: #808080; font-style: italic;">&lt;!-- Strings for number wheel --&gt;</span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;string</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;numwheel_year&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>年<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/string<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/resources<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>如果没有 add-resource，则会遇到这样的信息：<cite>Resource at numwheel_year appears in overlay but not in the base package; use <add-resource> to add.<br />
</cite></p>
<p>完了以后，就可以用使用 <code>com.android.internal.R</code> 来访问这些资源了。</p>
<h2>三、加入编译脚本（Add build script）</h2>
<p>在自己 product-name 目录下建立 sdk_addon 文件夹，并依照 sample/sdk_addon 分别拷贝 manifest.xml 和 hardware.xml，注意 manifest.xml 中的内容必须要根据之前第一步的变更同步修改。</p>
<p>接下来最关键，也是最容易出错的环节到了，那就是修改自己 product 的 mk 文件，需要修改 PRODUCT_PACKAGES、PRODUCT_COPY_FILES、DEVICE_PACKAGE_OVERLAYS 的值，定义 PRODUCT_SDK_ADDON_NAME、PRODUCT_SDK_ADDON_COPY_FILES、PRODUCT_SDK_ADDON_COPY_MODULES和PRODUCT_SDK_ADDON_DOC_MODULE。修改和定义的区别就在于，前者使用”+=”，后者使用“:=”。这些变量的值可以参照sample示例。</p>
<p>由于 sample 的示例中没有出现 DEVICE_PACKAGE_OVERLAYS，所以我这里特别解释一下它的作用，除了刚才为 add-on 增加资源以外，它还起到的作用就是替换掉原来的framework中的资源，比如图片等等，惟一的要求就是必须建立和原来图片位置相同的路径。和 add-on 不同的是，如果你是替换原来资源，那么是不用 add-resource 的。DEVICE_PACKAGE_OVERLAYS 的值就是 overlay 文件夹的路径，不包含 $ANDROID_HOME，到 overlay 一级即可。</p>
<p>完成了修改以后，使用 make PRODUCT-product-name-sdk_addon 进行编译。当然也可以直接执行 make sdk_addon，但是需要注意在此之前，你需要使用 chooseproduct 指定 product-name。执行完毕以后，会得到一个 zip 文件，这个就是 add-on 了。</p>
<h2>四、发布（Relase）</h2>
<p>完成上面的环节以后，剩下临门一脚了。所谓发布，就是通过诸如 HTTPD 一类的 HTTP SERVER 将资源公布出去。从 http://httpd.apache.org 下载 httpd，如何安装以及修改监听端口可参看其 document，在此不予赘述。</p>
<p>现在把刚才生成的 zip 文件，放置到 htdoc 目录下。并且创建一个 repository.xml，其内容和形式参看 https://dl-ssl.google.com/android/repository/repository.xml，我把它删减一下得到以下内容：</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:sdk-repository</span></span>
<span style="color: #009900;">    <span style="color: #000066;">xmlns:xsi</span>=<span style="color: #ff0000;">&quot;http://www.w3.org/2001/XMLSchema-instance&quot;</span></span>
<span style="color: #009900;">    <span style="color: #000066;">xmlns:sdk</span>=<span style="color: #ff0000;">&quot;http://schemas.android.com/sdk/android/repository/2&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:add-on<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Google APIs<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:api-level<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>3<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:api-level<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:vendor<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Google Inc.<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:vendor<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:revision<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>03<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:revision<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Android + Google APIs<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:desc-url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>http://developer.android.com/<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:desc-url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:uses-license</span> <span style="color: #000066;">ref</span>=<span style="color: #ff0000;">&quot;android-sdk-license&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:archives<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:archive</span> <span style="color: #000066;">os</span>=<span style="color: #ff0000;">&quot;any&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:size<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>34908058<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:size<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:checksum</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;sha1&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>1f92abf3a76be66ae8032257fc7620acbd2b2e3a<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:checksum<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>google_apis-3-r03.zip<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:url<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:archive<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:archives<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:libs<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:lib<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>com.google.android.maps<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
                <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>API for Google Maps.<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:description<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
            <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:lib<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
        <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:libs<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:add-on<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
&nbsp;
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sdk:license</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;text&quot;</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;android-sdk-license&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
        This is the Android Software Development Kit License Agreement.
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:license<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sdk:sdk-repository<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>接下来的事情，就是替换掉里面的 Google 信息为自己，大部分可以从它们的名称中理解其含义，例如 size 是指文件大小，你可以使用ls –l来查看文件大小。checksum 则要麻烦一些，执行 sha1sum ZIP.zip，即使用 sha1 对刚才生成 zip 文件生成校验码。</p>
<p>修改完成以后，通过浏览器访问 http://IP-address:port/repository.xml，确认是否 OK。确认以后，打开 Android SDK and AVD Manager，点击左侧 Available Packages，选择 “Add Add-on Sites” 填入URL，接下来的安装就不费口舌了。完成以后，你可以在 sdk 下的 add-ons 目录下看到刚刚安装的 add-on。</p>
<p>捎带提一下，应用开发方面使用该 add-on 时，调整工程的 Project Build Target 设定即可。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.poemcode.net/2010/09/android-sdk-addon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux x86 编译 Android 遭遇 gnu/stubs-64.h</title>
		<link>http://www.poemcode.net/2010/07/android-stubs-64/</link>
		<comments>http://www.poemcode.net/2010/07/android-stubs-64/#comments</comments>
		<pubDate>Wed, 07 Jul 2010 07:27:11 +0000</pubDate>
		<dc:creator>Xu Haojie</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[Linux]]></category>

		<guid isPermaLink="false">http://www.poemcode.net/?p=1365</guid>
		<description><![CDATA[<div class="wp-caption alignright" style="width: 76px"><img class="size-full wp-image-521" title="Android" src="http://www.poemcode.net/wp-content/uploads/2009/09/android.gif" alt="Android" width="76" height="90" /></div> 
这两天心血来潮，执行完 repo sync 后，顺手来了一下 make，不料却发现了以下的错误。

兵来将挡，水来土掩，用关键字 android "error: gnu/stubs-64.h: no such file or directory" 来搜一下吧，发现搜索结果寥寥无几，看样子问题比较新，其中有一个 CSDN 的链接，就顺手点了过去。帖子反映的问题和我一模一样，不过它的分析给了我一些提醒。

<pre lang="text">
host C: libclearsilver-jni <= external/clearsilver/java-jni/j_neo_util.c
In file included from /usr/include/features.h:378,
                      from /usr/include/string.h:26,
		      from external/clearsilver/java-jni/j_neo_util.c:1:
/usr/include/gnu/stubs.h:9:27: error: gnu/stubs-64.h: No such file or directory
make: *** [out/host/linux-x86/obj/SHARED_LIBRARIES/libclearsilver-jni_intermediates/j_neo_util.o] Error 1
</pre>]]></description>
			<content:encoded><![CDATA[<p>这两天心血来潮，执行完 repo sync 后，顺手来了一下 make，不料却发现了以下的错误：</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">host C: libclearsilver-jni &lt;= external/clearsilver/java-jni/j_neo_util.c
In file included from /usr/include/features.h:378,
                      from /usr/include/string.h:26,
		      from external/clearsilver/java-jni/j_neo_util.c:1:
/usr/include/gnu/stubs.h:9:27: error: gnu/stubs-64.h: No such file or directory
make: *** [out/host/linux-x86/obj/SHARED_LIBRARIES/libclearsilver-jni_intermediates/j_neo_util.o] Error 1</pre></div></div>

<p>兵来将挡，水来土掩，用关键字 android &#8220;error: gnu/stubs-64.h: no such file or directory&#8221; 来搜一下吧，发现搜索结果寥寥无几，看样子问题比较新，其中有一个 CSDN 的<a href="http://topic.csdn.net/u/20100704/15/06d940c3-2ce9-4a15-a182-98a39c74f77a.html?20065" target="blank">链接</a>，就顺手点了过去。帖子反映的问题和我一模一样，不过它的分析给了我一些提醒。</p>
<p>从错误信息入手，追踪到/usr/include/gnu/stubs.h，看到如下代码：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#if __WORDSIZE == 32</span>
<span style="color: #339933;"># include &lt;gnu/stubs-32.h&gt;</span>
<span style="color: #339933;">#elif __WORDSIZE == 64</span>
<span style="color: #339933;"># include &lt;gnu/stubs-64.h&gt;</span>
<span style="color: #339933;">#else</span>
<span style="color: #339933;"># error &quot;unexpected value for __WORDSIZE macro&quot;</span>
<span style="color: #339933;">#endif</span></pre></div></div>

<p>顺着 WORDSIZE，进入/usr/include/bits/wordsize，发现：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#if defined __x86_64__</span>
<span style="color: #339933;"># define __WORDSIZE	64</span>
<span style="color: #339933;"># define __WORDSIZE_COMPAT32	1</span>
<span style="color: #339933;">#else</span>
<span style="color: #339933;"># define __WORDSIZE	32</span>
<span style="color: #339933;">#endif</span></pre></div></div>

<p>结合报错的信息，可以知道这里一定是有定义__x86_64__，执行一下 uname -a 可以确认 OS 明明是x86，为什么会__x86_64__呢？追根溯源， Android 源码或许能露出蛛丝马迹。</p>
<p>果不其然，从 android.git.kernel.org 的 platform/external/clearsilver.git 上，看到5天前，有个 Ying Wang 的家伙提交一个修改：Fix 64-bit clearsilver shared library issue，参看<a href="http://android.git.kernel.org/?p=platform/external/clearsilver.git;a=commit;h=d36910a8110d8377b22301274d2b5131a732a72b" target="blank">这里</a>，修改内容中 java-jni/Android.mk，和出现本次问题的路径 java-jni/j_neo_util.c，同属一个父目录，看样子有点关系，查看 Android.mk 的修改内容，发现做了如下修改：</p>

<div class="wp_syntax"><div class="code"><pre class="diff" style="font-family:monospace;">+# This forces a <span style="">64</span>-bit build for Java6
<span style="color: #00b000;">+ifneq <span style="">&#40;</span>$<span style="">&#40;</span>filter <span style="">1.6</span>%,$<span style="">&#40;</span>java_version<span style="">&#41;</span><span style="">&#41;</span>,<span style="">&#41;</span></span>
<span style="color: #00b000;">+    LOCAL_CFLAGS += -m64</span>
<span style="color: #00b000;">+    LOCAL_LDFLAGS += -m64</span>
<span style="color: #00b000;">+endif</span></pre></div></div>

<p>当发现你使用Java6时，它将强制使用64-bit，我想这就能解释__x86_64__出现的原因。那么既然它要64-bit，我就满足它。首先要解决 gnu/stubs-64.h: No such file or directory，解决这个问题需要执行以下命令：</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">[xuhj@eniac mydroid]$ apt-get install libc6-dev-amd64</pre></div></div>

<p>完成以后再执行 make，发现有错误：</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">/usr/bin/ld: cannot find -lstdc++</pre></div></div>

<p>那就继续满足它：</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">[xuhj@eniac mydroid]$ apt-get install g++-multilib lib64stdc++6</pre></div></div>

<p>还是不行，又发生下面的错误：</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">/usr/bin/ld: cannot find -lz</pre></div></div>

<p>再来执行命令：</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">[xuhj@eniac mydroid]$ apt-get install lib64z1-dev</pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://www.poemcode.net/2010/07/android-stubs-64/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>从 Remote Service Binding 学习 AIDL 与 IPC</title>
		<link>http://www.poemcode.net/2010/05/aidl-ipc/</link>
		<comments>http://www.poemcode.net/2010/05/aidl-ipc/#comments</comments>
		<pubDate>Thu, 20 May 2010 11:35:56 +0000</pubDate>
		<dc:creator>Xu Haojie</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://www.poemcode.net/?p=1226</guid>
		<description><![CDATA[<div class="wp-caption alignright" style="width: 76px"><img class="size-full wp-image-521" title="Android" src="http://www.poemcode.net/wp-content/uploads/2009/09/android.gif" alt="Android" width="76" height="90" /></div> 

默认情况下，一个应用不管有多少个 Activity、Service 或其他组件，它们都是运行在一个进程上，但是我们可以安排 Service 运行一个新的进程上，但是不同进程之间应该如何通信呢？当需要在不同的进程之间传递对象时，应该怎么做呢？AIDL(Android Interface Definition Language) 便是解决这一问题的钥匙。

使用 AIDL 并不是难事，但是比较繁琐，并且一不小心容易出错。好在 Android Dev Guide 的<em>Designing a Remote Interface Using AIDL</em> 对这个问题讲解非常详细，再结合 Android APIDemo 中的 Remote Service Binding 给出了的示例，这都给了开发者提供了非常到位的帮助。以下内容就是我结合二者，整理出来的笔记，力求真理，但能力有限，差错难免，请读者坚持自己的判断力，本文只供参考，且不可尽信。]]></description>
			<content:encoded><![CDATA[<p>默认情况下，一个应用不管有多少个 Activity、Service 或其他组件，它们都是运行在一个进程上，但是我们可以安排 Service 运行一个新的进程上，但是不同进程之间应该如何通信呢？当需要在不同的进程之间传递对象时，应该怎么做呢？AIDL(Android Interface Definition Language) 便是解决这一问题的钥匙。</p>
<p>使用 AIDL 并不是难事，但是比较繁琐，并且一不小心容易出错。好在 Android Dev Guide 的 <em>Designing a Remote Interface Using AIDL</em> 对这个问题讲解非常详细，再结合 Android APIDemo 中的 Remote Service Binding 给出了的示例，这都给了开发者提供了非常到位的帮助。以下内容就是我结合二者，整理出来的笔记，力求真理，但能力有限，差错难免，请读者坚持自己的判断力，本文只供参考，且不可尽信。</p>
<h2>一、使用 AIDL 实现 IPC</h2>
<p>面对问题，应统揽全局，归纳阶段，划定步骤，共得出四大步，分列如下：</p>
<dl>
<dt>创建.aidl 文件</dt>
<dd>在这个文件里定义 method 和 field</dd>
<dt>把 .aidl 文件加入到 makefile 中去</dt>
<dd>如果使用 Eclipse 则 ADT 会帮你管理</dd>
<dt>实现接口方法</dt>
<dd>AIDL 编译器会根据接口生成一个用 Java 语言编写的interface，这个 interface 有一个抽象的内部类，名字为 <tt>Stub</tt>，你必须创建一个类，继承于它，并且实现 .adil 文件中所声明的方法</dd>
<dt>公开接口给客户端</dt>
<dd>如果创建的是 service，则应该继承自 <tt>Service<tt>，并且重载 <tt>Service.onBind()</tt> 返回实现接口的类的实例</dd>
</dl>
<p>这四个步骤在 Remote Service Binding 中均有所呈现，以下分开阐述。Remote Service Binding 共包含有两个 .java 文件，三个 .aidl 文件，物理结构比较简单，但是逻辑结构就不那么简单，以下用 Class Diagram 来展示其中的关系。</p>
<div id="attachment_1235" class="wp-caption aligncenter" style="width: 610px"><img src="http://www.poemcode.net/wp-content/uploads/2010/05/Remote-Service-Binding.png" alt="Remote Service Binding" title="Remote Service Binding" width="600" height="422" class="size-full wp-image-1235" /><p class="wp-caption-text">Remote Service Binding</p></div>
<h3>1、创建.aidl 文件</h3>
<p>AIDL 语法简单，用来声明接口，其中的方法接收参数和返回值，但是参数和返回值的类型是有约束的，且有些类型是需要 import，另外一些则无需这样做。</p>
<p>AIDL 支持的数据类型划分为四类，第一类是 Java 编程语言中的基本类型，第二类包括 String、List、Map 和 CharSequence，第三类是其他 AIDL 生成的 interface，第四类是实现了 Parcelable protocol 的自定义类。<br />
其中，除了第一类外，其他三类在使用时均需要特别小心。</p>
<p>使用第二类时，首先需要明白这些类不需要 import，是内嵌的。其次注意在使用 List 和 Map 此二者容器类时，需注意其元素必须得是 AIDL 支持的数据类型，List 可支持泛型，但是 Map 不支持，同时另外一端负责接收的具体的类里则必须是 <tt>ArrayList</tt> 和 <tt>HashMap</tt>。</p>
<p>使用第三、四类时，需要留意它们都是需要 import 的，但是前者传递时，传递的是 reference，而后者则是 value。</p>
<p>在创建 .aidl 文件的过程中，应该注意一旦 method 有参数，则需注意在前面加上 in, out 或 inout，它们被称为 directional tag，但是对于基本类型的参数，默认就是 in，并且不会是其他值。</p>
<p>Remote Service Binding 共包括了三个 .aidl 文件，分别是IRemoteService.aidl、IRemoteServiceCallback.aidl、ISecondary.aidl，通过它们可以看到如何使用第一类和第三类的数据类型，稀罕的是，看不到第二类、第四类数据类型的使用，也没有看到 directional tag。</p>
<h3>2、实现 Interface</h3>
<p>AIDL 为你生成一个 interface 文件，文件名称和 .aidl 文件相同。如果使用 Eclipse 插件，则 AIDL 会在构建过程中自动运行，如果不使用插件，则需要先使用 AIDL。</p>
<p>生成的 interface 会包含一个抽象内部类 Stub，它声明了在 .aidl 文件里的所有方法。Stub 也定义了一些帮助方法，比较常用的有 <tt>asInterface()</tt>，其接收一个 <tt>IBinder</tt> 作为参数，并且返回一个 interface 的实例用来调用IPC方法。</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">    <span style="color: #000000; font-weight: bold;">private</span> <span style="color: #000000; font-weight: bold;">static</span> INotificationManager sService<span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000000; font-weight: bold;">private</span> INotificationManager getService<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>sService <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">return</span> sService<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        sService <span style="color: #339933;">=</span> INotificationManager.<span style="color: #003399;">Stub</span>.<span style="color: #006633;">asInterface</span><span style="color: #009900;">&#40;</span>ServiceManager.<span style="color: #006633;">getService</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;notification&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000000; font-weight: bold;">return</span> sService<span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>要实现 interface，需要继承 Stub，实现其方法，这在 <tt>RemoteService</tt> 和 <tt>RemoteServiceBinding</tt> 都可以找到相关代码。</p>
<p>这个环节是重中之重，需要特别小心的有两点，其一是抛出的所有异常均不会发给调用者；其二是IPC调用是同步的，这意味IPC服务一旦花费较长时间完成的话，就会引起ANR，应该将这样的操作放在单独的线程里。</p>
<h3>3、向客户端公开 Interface</h3>
<p>独乐乐不如众乐乐，需要将服务公开出去，要达成这个目的，须得创建一个 <tt>Service</tt> 的子类，并且实现 <tt>Service.onBind(Intent)</tt>，通过这个方法将实现了接口的类的实例返回回来。通过查看 <tt>RemoteService</tt> 一目了然。</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">    @Override
    <span style="color: #000000; font-weight: bold;">public</span> IBinder onBind<span style="color: #009900;">&#40;</span>Intent intent<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">// Select the interface to return.  If your service only implements</span>
        <span style="color: #666666; font-style: italic;">// a single interface, you can just return it here without checking</span>
        <span style="color: #666666; font-style: italic;">// the Intent.</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>IRemoteService.<span style="color: #000000; font-weight: bold;">class</span>.<span style="color: #006633;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span>intent.<span style="color: #006633;">getAction</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">return</span> mBinder<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>ISecondary.<span style="color: #000000; font-weight: bold;">class</span>.<span style="color: #006633;">getName</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span>intent.<span style="color: #006633;">getAction</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000000; font-weight: bold;">return</span> mSecondaryBinder<span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>其中的 mBinder 和 mSecondaryBinder 分别是实现了 <tt>IRemoteService</tt> 和 <tt> ISecondary </tt> 接口的类的实例。</p>
<h3>4、使用Parcelables传值</h3>
<p>前文中提到 Remote Servcie Binding 没有使用第四类数据类型作为参数，这是示例的不足，要想让一个类变成第四类，需要遵照以下步骤：</p>
<ol>
<li>引入 <tt>Parcelable</tt> 接口</li>
<li>实现 <tt>writeToParcel(Parcel out)</tt></li>
<li>增加一个静态的field，其实现 <tt>Parcelable.Creator</tt> 接口</li>
<li>创建一个 .aidl 文件，用以声明你的 parcelables 类</li>
</ol>
<p>在 <em>Designing a Remote Interface Using AIDL</em> 中，类 <tt>Rect</tt> 是一个不错的示例，弥补了 Remote Service Binding 的不足。</p>
<h2>二、调用 IPC 方法</h2>
<p>万事具备，只欠东风，IPC 备妥，只待调用。在 Remote Service Binding 中，RemoteServiceBinding 正是  IPC 的调用者，</p>
<p>既然要使用接口，那就先声明 interface 类型的变量，</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">    <span style="color: #008000; font-style: italic; font-weight: bold;">/** The primary interface we will be calling on the service. */</span>
    IRemoteService mService <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
    <span style="color: #008000; font-style: italic; font-weight: bold;">/** Another interface we use on the service. */</span>
    ISecondary mSecondaryService <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span></pre></div></div>

<p>实现 <tt>ServiceConnection</tt>，在 <tt>onServiceConnected(ComponentName className,       IBinder service)</tt> 中完成对 <tt>mService</tt> 和 <tt>mSecondaryService</tt> 的赋值。</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">    <span style="color: #000000; font-weight: bold;">private</span> ServiceConnection mConnection <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> ServiceConnection<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000066; font-weight: bold;">void</span> onServiceConnected<span style="color: #009900;">&#40;</span>ComponentName className,
                IBinder service<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            mService <span style="color: #339933;">=</span> IRemoteService.<span style="color: #003399;">Stub</span>.<span style="color: #006633;">asInterface</span><span style="color: #009900;">&#40;</span>service<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #666666; font-style: italic;">// ... 以下省略</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>接着别忘了调用 <tt>Context.bindService()</tt>，完成任务以后，调用 <tt>Context.unbindService()</tt>。如果在 connection 中断的情况下，调用 IPC 方法，你会遇到 <tt>DeadObjectException</tt>，这是 remote method 能抛出的唯一异常。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.poemcode.net/2010/05/aidl-ipc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>读《Multitasking the Android Way》(一)</title>
		<link>http://www.poemcode.net/2010/05/multitasking-the-android-way1/</link>
		<comments>http://www.poemcode.net/2010/05/multitasking-the-android-way1/#comments</comments>
		<pubDate>Wed, 05 May 2010 11:28:45 +0000</pubDate>
		<dc:creator>Xu Haojie</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://www.poemcode.net/?p=1201</guid>
		<description><![CDATA[<div class="wp-caption alignright" style="width: 76px"><img class="size-full wp-image-521" title="Android" src="http://www.poemcode.net/wp-content/uploads/2009/09/android.gif" alt="Android" width="76" height="90" /></div> 

同时运行多个应用程序，即 Multitask，对于现在的 OS 来说，是个稀松平常的事情，--IPhone OS 另当别论。Android 对 Multitask 的处理方式有着自己独到之处，这让从其他平台转来的开发者有点发懵。凡事知其然，更要知其所以然，要设计出和 Android 完美“融合”的应用程序，理解 Multitask 是非常有必要的。这篇博文从设计考量出发，告诉你问题的大环境是什么，然后讲述现在的处理机制对于应用程序的影响，最后引出开发者应该如何利用好这一机制。

移动设备，例如手机等，有着苛刻的技术限制，内存、电量、运算速度等都不能和 PC 相提并论，用户体验更不能照搬桌面软件或者 web 系统，任何试图在移动设备上建立起和 PC 相等的用户体验是一种不怎么明智的想法。 ]]></description>
			<content:encoded><![CDATA[<p><i>Android Developers Blog 发表了一篇题为《Multitasking the Android Way》的博文，读起来颇为有趣。我将博文中的关键信息加以自己的理解，简单整理成以下文字，以便日后查阅之便。能力有限，误读和错读难以避免，阅读者应该坚持怀疑的态度来阅读本文，尽信书不如无书。</i></p>
<p>同时运行多个应用程序，即 Multitask，对于现在的 OS 来说，是个稀松平常的事情，&#8211;IPhone OS 另当别论。Android 对 Multitask 的处理方式有着自己独到之处，这让从其他平台转来的开发者有点发懵。凡事知其然，更要知其所以然，要设计出和 Android 完美“融合”的应用程序，理解 Multitask 是非常有必要的。这篇博文从设计考量出发，告诉你问题的大环境是什么，然后讲述现在的处理机制对于应用程序的影响，最后引出开发者应该如何利用好这一机制。</p>
<p>移动设备，例如手机等，有着苛刻的技术限制，内存、电量、运算速度等都不能和 PC 相提并论，用户体验更不能照搬桌面软件或者 web 系统，任何试图在移动设备上建立起和 PC 相等的用户体验是一种不怎么明智的想法。 </p>
<p>Android 设计者在设计 multitask 时充分考虑到了这些，并归纳成四点设计考量：</p>
<ol>
<li>应用程序在完成后，无需关闭。</li>
<li>系统交换空间并不充裕，内存使用有苛刻的限制。</li>
<li>应用程序间切换十分关键，启动一项新应用的时间被限制在1秒之内。</li>
<li>API 不仅要能满足第三方开发者，并且必须足以支持创建内置的 Google 应用，<q>all applications are created equal</q> 。</li>
</ol>
<p>很明显，前两点是冲突的。Android 淡化“关闭应用程序”这一常见的操作，相反 Android 想让用户感觉到所有的应用程序一直都在运行当中。与此同时，移动设备都有着比较苛刻的内存限制，因此一旦它需要的内存超过了可用的内存，系统就会很快变慢。这一对矛盾一直伴随着 Android 设计过程。</p>
<p>对 Android multitask 的一个常见误解是混淆进程和应用之间的差别。Android 里，用户可能看到了应用，实际上却没有进程在运行；多个应用可能共享一个进程，也可能一个应用使用了多个进程；应用可能没有在做任何事情，但是进程却会一直被保留。</p>
<p>事实上，进程正在“运行”，并不能等同应用就在运行，或者说在执行什么操作。用户离开应用，Android 会自行处置进程，如果判定稍后还需要这个它，则就会保留它，也有可能用户刚刚离开应用，Android 就清除掉了这个进程，但是这并不妨碍用户返回到刚刚离开的地方。</p>
<p>这种处理方式的关键是要明白进程并没有被彻底地关闭。当用户离开应用，应用进程会被保留在后台，需要的话，会允许它继续工作。如果用户返回应用，则进程立即进入到前台。假设设备从不会用完内存，那么 Android 就会保留所有的进程，并且让它们一直“运行”下去。</p>
<p>当然了，只有人的欲望才是无限的，机器的内存总是有限的，Android 在这一点上是非常清楚，因此它必须决定在什么时间清除掉不必要的进程。Android 会有规则来判断每一个进程的重要性以及哪一个进程应该被清除。这些规则基于两个因素：该进程对当前用户体验的重要性和距离上次使用到该进程的时间间隔有多久。</p>
<p>一旦 Android 决定要清除掉某个进程，那么它就会用简单粗暴的方式直接 KILL 它，同时内核会立即跟进，不管三七二十一，回收这个进程持有的所有资源。</p>
<p>如果用户返回到了进程已被杀死的应用，Android 需要有一种方法能够重新启动，并且恢复到此前的最后状态。通过跟踪用户关心的 Activity，记录观察到的状态信息，并使用最后的状态信息重新启动 Activity，Android 成功营造出了营造“all applications are running all of the time”的假象。用户每次离开 Activity，系统就会生成新的状态，&#8211;注意不是在进程被KILL时！正因为保留了最后的状态信息，所以内核才可以“肆无忌惮”地杀死进程。</p>
<p>某种意义上讲，Android 的进程管理可以被视为一种 swap space：应用进程代表了正在使用的内存的大小；当内存少了，一些进程会被杀死（相当于 swapped out）；当这些进程被再次需要的时候，它们就会从最后保存的状态（swapped in）中恢复，重新启动。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.poemcode.net/2010/05/multitasking-the-android-way1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Activity Task 与 Intent Filter Flag</title>
		<link>http://www.poemcode.net/2010/04/activity-task-intent-filter-flag/</link>
		<comments>http://www.poemcode.net/2010/04/activity-task-intent-filter-flag/#comments</comments>
		<pubDate>Thu, 15 Apr 2010 12:34:07 +0000</pubDate>
		<dc:creator>Xu Haojie</dc:creator>
				<category><![CDATA[Software]]></category>
		<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://www.poemcode.net/?p=1165</guid>
		<description><![CDATA[<div class="wp-caption alignright" style="width: 76px"><img class="size-full wp-image-521" title="Android" src="http://www.poemcode.net/wp-content/uploads/2009/09/android.gif" alt="Android" width="76" height="90" /></div> 
接触 Android 以来，一直觉得对 task、affinity 和 launch mode 一知半解，这几天潜心阅读 Dev Guide 中的 Activities and Tasks，简单做下笔记，梳理下这部分的知识。

Android 的一个特色就是 application A 的 activity 可以启动 application B 的 activity，尽管 A 和 B 是毫无干系的，而在用户看来，两个场景紧密联系，视觉上二者构成了一个整体。Android 就是把这种误觉定义为 Task，它既不是 class，也不是 AndroidMainifest.xml 中的一个元素。从表现上看 Task 就像是一个 stack，一个一个的 activity是构成 stack 的元素，做着入栈 (push) 和出栈 (pop-up)这样简单重复性的劳动。]]></description>
			<content:encoded><![CDATA[<p><i>接触 Android 以来，一直觉得对 task、affinity 和 launch mode 一知半解，这几天潜心阅读<strong> Dev Guide </strong>中的<strong> Activities and Tasks</strong>，简单做下笔记，梳理下这部分的知识。</i></p>
<p>Android 的一个特色就是 application A 的 activity 可以启动 application B 的 activity，尽管 A 和 B 是毫无干系的，而在用户看来，两个场景紧密联系，视觉上二者构成了一个整体。Android 就是把这种误觉定义为 Task，它既不是 class，也不是 AndroidMainifest.xml 中的一个元素。从表现上看 Task 就像是一个 stack，一个一个的 activity 是构成 stack 的元素，做着入栈 (push) 和出栈 (pop-up)这样简单重复性的劳动。</p>
<p>默认的规则总是满足大多数的应用场景，但是也总会有一些例外打破习以为常的惯例。Task 的默认规则同样并非牢不可破，修改的方法还是有的。借助 Intent 中的 flag 和 AndroidMainifest.xml 中 activity 元素的属性，就可以控制到 Task 里 Activity 的关联关系和行为。</p>
<p>在 <tt>android.content.Intent</tt> 中一共定义了20种不同的 flag，其中和 Task 紧密关联的有四种：</p>
<ol>
<li><tt>FLAG_ACTIVITY_NEW_TASK</tt></li>
<li><tt>FLAG_ACTIVITY_CLEAR_TOP</tt></li>
<li><tt>FLAG_ACTIVITY_RESET_TASK_IF_NEEDED</tt></li>
<li><tt>FLAG_ACTIVITY_SINGLE_TOP</tt></li>
</ol>
<p>在使用这四个 flag 时，一个 Intent 可以设置一个 flag，也可以选择若干个进行组合。</p>
<p>默认情况下，通过 <tt>startActivity()</tt> 启动一个新的 Activity，新的 Activity 将会和调用者在同一个 stack 中。但是，如果在传递给 <tt>startActivity()</tt>  的 Intent 对象里包含了  <tt>FLAG_ACTION_NEW_TASK</tt>，情况将发生变化，&#8211;系统将为新的 Activity “寻找”一个不同于调用者的 Task。不过要找的 Task 是不是一定就是 NEW 呢？如果是第一次执行，则这个设想成立，如果说不是，也就是说已经有一个包含此 Activity 的Task 存在，则不会再启动 Activity。</p>
<p>如果 flag 是 <tt>FLAG_ACTIVITY_CLEAR_TOP</tt>，同时当前的 Task 里已经有了这个 Activity，那么情形又将不一样。Android 不但不会启动新的 Activity 实例，而且还会将 Task 里 该 Activity 之上的所有 Activity 一律结束掉，然后将 Intent 发给这个已存在的 Activity。Activity 收到 Intent 之后，可以在 <tt>onNewIntent()</tt> 里做下一步的处理，也可以自行结束然后重新创建自己。如果 Activity 在 AndroidMainifest.xml 里将启动模式设置成<q>multiple</q>，&#8211; 默认模式，并且 Intent 里也没有设置 <tt>FLAG_ACTIVITY_SINGLE_TOP</tt>，那么它将选择后者。否则，它将选择前者。<tt>FLAG_ACTIVITY_CLEAR_TOP</tt> 还可以和 <tt>FLAG_ACTION_NEW_TASK</tt> 配合使用。</p>
<p>如果 flag 设置的是 <tt>FLAG_ACTIVITY_SINGLE_TOP</tt>，则意味着如果 Activity 已经是运行在 Task 的 top，则该 Activity 将不会再被启动。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.poemcode.net/2010/04/activity-task-intent-filter-flag/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
