﻿<?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>C++博客-franksunny的个人技术空间-随笔分类-Android开发</title><link>http://www.cppblog.com/franksunny/category/17823.html</link><description>获得人生中的成功需要的专注与坚持不懈多过天才与机会。

                       ——C.W. Wendte</description><language>zh-cn</language><lastBuildDate>Mon, 26 Sep 2011 10:07:37 GMT</lastBuildDate><pubDate>Mon, 26 Sep 2011 10:07:37 GMT</pubDate><ttl>60</ttl><item><title>[转]使用internal（com.android.internal）和hidden（@hide）APIs</title><link>http://www.cppblog.com/franksunny/archive/2011/09/26/156865.html</link><dc:creator>frank.sunny</dc:creator><author>frank.sunny</author><pubDate>Mon, 26 Sep 2011 09:52:00 GMT</pubDate><guid>http://www.cppblog.com/franksunny/archive/2011/09/26/156865.html</guid><wfw:comment>http://www.cppblog.com/franksunny/comments/156865.html</wfw:comment><comments>http://www.cppblog.com/franksunny/archive/2011/09/26/156865.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/franksunny/comments/commentRss/156865.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/franksunny/services/trackbacks/156865.html</trackback:ping><description><![CDATA[<h1><span style="font-weight: normal;"><span style="font-size: 8pt; ">由于黏贴后原有图片显示不出来，感兴趣的可以下载word文档，详见如下&nbsp;</span><a href="http://www.cppblog.com/Files/franksunny/Using%20internal%20and%20hide%20api.rar"><span style="font-size: 8pt; ">http://www.cppblog.com/Files/franksunny/Using%20internal%20and%20hide%20api.rar</span></a></span><br />
<br />
使用internal（com.android.internal）和hidden（@hide）APIs </h1>
<h2>Part One</h2>
<p>原文路径：<a href="http://devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-1-introduction/">http://devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-1-introduction/</a> </p>
<p>Android有两种类型的API是不能经由SDK访问的。 </p>
<p>第一种是位于com.android.internal包中的API。我将称之为internal API。第二种API类型是一系列被标记为@hide属性的类和方法。从严格意义上来讲，这不是一个单一的API，而是一组小的被隐藏的API，但我仍将其假设为一种API，并称之为hidden API。 </p>
<p><strong>Hidden API </strong><strong>例子</strong> </p>
<p>你可以查看一下android的源码，并能找到一些变量、函数和类等，都被@hide属性标记了。 </p>
<p>下面的例子就是在WifiManager（API 10源码）中隐藏的变量。 </p>
<p><span><a href="http://devmaze.files.wordpress.com/2011/05/image_thumb13_thumb.png"><span><!--[if gte vml 1]><v:shapetype
id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t"
path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHeight"/>
<v:f eqn="sum @10 21600 0"/>
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
<o:lock v:ext="edit" aspectratio="t"/>
</v:shapetype><v:shape id="_x0000_i1025" type="#_x0000_t75" alt="image_thumb13_thumb"
style='width:445.5pt;height:187.5pt' o:button="t">
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image001.png"
o:href="http://devmaze.files.wordpress.com/2011/05/image_thumb13_thumb_thumb.png?w=594&amp;h=250"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="594" height="250" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image002.gif" alt="image_thumb13_thumb" v:shapes="_x0000_i1025" /><!--[endif]--></span></a></span></p>
<p>另一个例子是在WifiManager（API 10源码）中隐藏了setWifiApEnabled函数。 </p>
<p><span><a href="http://devmaze.files.wordpress.com/2011/05/image_thumb15_thumb.png"><span><!--[if gte vml 1]><v:shape
id="_x0000_i1026" type="#_x0000_t75" alt="image_thumb15_thumb" style='width:450pt;
height:165pt' o:button="t">
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image003.png"
o:href="http://devmaze.files.wordpress.com/2011/05/image_thumb15_thumb_thumb.png?w=600&amp;h=220"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="600" height="220" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image004.gif" alt="image_thumb15_thumb" v:shapes="_x0000_i1026" /><!--[endif]--></span></a></span></p>
<p>因此，只要你看到@hide属性，那你看到的就是hidden API。 </p>
<p><strong>Internal</strong><strong>和</strong><strong>hidden API</strong><strong>的区别</strong> </p>
<p>Hidden API之所以被隐藏，是想阻止开发者使用SDK中那些未完成或不稳定的部分（接口或架构）。举个例子，Bluetooth API在API 5（<span>Android
2.0</span>）上才开放；在API 3 和4上都是用@hide属性隐藏了。当这些API被验证和清理后，Google的开发者会移除@hide属性，并让其在API 5官方化。很多地方在API 4 和5之间发生了变化。如果你的程序依赖某些隐藏的API，当其部署到新的平台上时，就有可能陷入困境。 </p>
<p>对于internal API来说，从来都没有计划将其开放出来。它就是Android的&#8220;内部厨房&#8221;，对开发者来说，应该将其视作黑盒。凡事都会有变化的。如果你依赖某些<span>internal
API</span>，也有可能在新的Android release上，这些internal API发生变化，从而令你失望。 </p>
<p>总结一下区别： </p>
<p>Hidden API = 进行中的工作； </p>
<p>Internal API = 黑盒； </p>
<p><strong>Internal</strong><strong>和</strong><strong>hidden API</strong><strong>的编译时</strong><strong> vs. </strong><strong>运行时</strong> </p>
<p>当你使用Android SDK进行开发的时候，你引用了一个非常重要的jar文件&#8212;&#8212;android.jar。它位于<span>Android
SDK</span>平台的文件夹中（SDK_DIR/platforms/platform-X/android.jar，其中，X表示API等级）。这个android.jar移掉了com.android.internal包中所有的类，也移掉了所有标记有@hide的类，枚举，字段和方法。 </p>
<p>但当你在设备上启动应用程序时，它将加载framework.jar（简单来说，它和android.jar等同），而其未移掉<span>internal
API</span>和hidden API。（但它对开发者来说，并不能友好地访问，因此，我将向大家展示不通过反射如何使用这些API）。 </p>
<p>关于internal API，还有一件事需要说明。Eclipse的ADT插件增加了一个额外的规则，那就是禁止使用com.android.internal包中的任何东西。所以，即便是我们可以拿到最原始的android.jar（未删减版），也没有轻松的办法通过Eclipse使用这些internal API。 </p>
<p>你可以亲自检查一下。创建一个新的Android工程（或者使用已有的）。查看一下它引用的类库（右击<span>project Properties
&#8211;&gt; Java Build Path &#8211;&gt; Libraries</span>）。 </p>
<p><span><a href="http://devmaze.files.wordpress.com/2011/05/image_thumb30_thumb.png"><span><!--[if gte vml 1]><v:shape
id="_x0000_i1027" type="#_x0000_t75" alt="image_thumb30_thumb" style='width:451.5pt;
height:263.25pt' o:button="t">
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image005.png"
o:href="http://devmaze.files.wordpress.com/2011/05/image_thumb30_thumb_thumb.png?w=602&amp;h=351"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="602" height="351" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image006.gif" alt="image_thumb30_thumb" v:shapes="_x0000_i1027" /><!--[endif]--></span></a></span></p>
<p><span><a href="http://devmaze.files.wordpress.com/2011/05/image_thumb29_thumb.png"><span><!--[if gte vml 1]><v:shape
id="_x0000_i1028" type="#_x0000_t75" alt="image_thumb29_thumb" style='width:588pt;
height:201.75pt' o:button="t">
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image007.png"
o:href="http://devmaze.files.wordpress.com/2011/05/image_thumb29_thumb_thumb.png?w=784&amp;h=269"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="784" height="269" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image008.gif" alt="image_thumb29_thumb" v:shapes="_x0000_i1028" /><!--[endif]--></span></a></span></p>
<p>重要的总结：internal和hidden API在SDK中是按照一样的方式处理的（都从android.jar中移除了），但internal API更惨的是，还被Eclipse的ADT插件显式禁止了。 </p>
<p><strong>不通过反射使用</strong><strong>internal</strong><strong>和</strong><strong>hidden API</strong> </p>
<p>这些文章的终极目标是让开发者能够不通过反射使用Internal和Hidden API。如果你完成了接下来部分中描述的步骤，你将能使用这些Internal和Hidden API，如同公开的API。你不再需要使用反射。 </p>
<p><strong>注：如果你正在使用这些非公开的</strong><strong>API</strong><strong>，你必须知道，你的程序有着极大的风险。基本上，无法保证在下一次的</strong><strong>Android OS</strong><strong>更新时，这些</strong><strong>API</strong><strong>不被破坏，也无法保证不同的运营商有着一致的行为。你自己决定吧。</strong> </p>
<p>接下来有三个场景： </p>
<p>1. Internal 和<span>hidden
API</span>都可用（场景A） </p>
<p>2. 只<span>Hidden
API</span>可用（场景B） </p>
<p>3. 只<span>Internal
API</span>可用（场景C） </p>
<p>场景A是B、C的总和。场景B是最简单的一个（不需要对Eclipse的ADT修改）。 </p>
<p>场景A：阅读Part1, 2, 3, 4, 5 </p>
<p>场景B：阅读Part1, 2, 3, 5 </p>
<p>场景C：阅读Part1, 2, 3, 4, 5</p>
<h2>Part 2</h2>
<p>原文路径：<a href="http://devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-2-hacking-around/">http://devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-2-hacking-around/</a></p>
<p>在上一篇中，我解释了为什么我们不通过反射就会很难使用internal和hidden API。这是因为android.jar中就没包含这些API，因此，没人能够在编译时引用这些类。</p>
<p>这篇文章将描述如何还原最初的android.jar。这将允许我们像使用公开的API那样使用internal和hidden API。</p>
<p><strong>如何得到原版</strong><strong>android.jar</strong><strong>？</strong></p>
<p>我们需要修改android.jar，这样它才能包含所有的*.class文件（包括internal和hidden API类）。有两种办法：</p>
<p>1） Android是一个开源工程。我们可以下载源码并搭建编译环境，这样它就不能移除那些internal和hidden的类了。这个办法比较困难；</p>
<p>2） 每个模拟器或真机在运行时都会有一个等同android.jar的东西。我们可以从这里拿到jar文件，提取出原始的.class文件，并拷贝到Android SDK的android.jar中。</p>
<p>我将采用方案2。它易于开始，还不需要搭建Linux环境及编译环境等。</p>
<p><strong>从设备上获取</strong><strong>framework.jar</strong></p>
<p>你可以使用命令行（adb pull）从模拟器或设备上下载文件，或者使用DDMS（借助Eclipse或SDK中的应用）。</p>
<p>注意：模拟器通常在.dex文件中包含代码，而真机一般在优化版的dex文件中包含代码&#8212;&#8212;odex文件。操作odex文件比较困难，这也是为什么我选择模拟器的原因。</p>
<p>与Android SDK中的android.jar等同的文件是framework.jar。这个文件位于设备的：/system/framework/framework.jar</p>
<p>adb pull /system/framework/framework.jar</p>
<p><!--[if gte vml 1]><v:shape id="_x0000_s1026" type="#_x0000_t75"
alt="image" href="http://devmaze.files.wordpress.com/2011/01/image3.png"
style='position:absolute;margin-left:0;margin-top:47.4pt;width:450pt;height:87pt;
z-index:1;mso-wrap-distance-left:0;mso-wrap-distance-right:0;
mso-position-vertical-relative:line' o:allowoverlap="f" o:button="t">
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image009.png"
o:title="image_thumb3"/>
<w:wrap type="square"/>
</v:shape><![endif]--><!--[if !vml]--><a href="http://devmaze.files.wordpress.com/2011/01/image3.png"><img border="0" width="600" height="116" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image010.gif" align="left" alt="image" v:shapes="_x0000_s1026" /></a><!--[endif]-->当framework.jar从设备上下下来之后，重命名为framework.zip并解压到独立的文件夹中，看起来是这个样子的：</p>
<p>&nbsp;</p>
<p>classes.dex正是我们需要的。</p>
<p><strong>创建</strong><strong>framework-classes.zip</strong></p>
<p>首先，我们需要把.dex文件转换成.jar格式。你可以使用通用的工具dex2jar。只需要运行：</p>
<p>dev2jar classes.dex</p>
<p>当转换结束时，你应该得到了classes.dex.dex2jar.jar文件。重命名为framework-classes.zip。使用zip查看器，进入到framework-classes.zip/com/android/internal/：</p>
<p><span><a href="http://devmaze.files.wordpress.com/2011/01/image4.png"><span><!--[if gte vml 1]><v:shape
id="_x0000_i1029" type="#_x0000_t75" alt="image" style='width:360.75pt;
height:443.25pt' o:button="t">
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image011.png"
o:href="http://devmaze.files.wordpress.com/2011/01/image_thumb4.png?w=599&amp;h=736"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="481" height="591" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image012.gif" alt="image" v:shapes="_x0000_i1029" /><!--[endif]--></span></a></span></p>
<p>恭喜你，你已经拥有了所有的.class文件，包括internal和<span>hidden
API</span>（尽管截图只确认了internal部分）。</p>
<p><strong>创建</strong><strong>original-android.jar</strong></p>
<p>Android SDK的android.jar位于ANDROID_SDK/platforms/android-X/android.jar（X表示API等级）。</p>
<p>拷贝android.jar成custom-android.jar。解压至custom-android文件夹。将framework-classes.zip中所有的.class文件拷贝到custom-android文件夹中（你需要覆盖所有已经存在的.class文件）。</p>
<p>然后，压缩custom-android文件成original-android.zip。重命名为original-android.jar。</p>
<p><strong>步骤总结</strong></p>
<p>1. 选择你的目标平台X</p>
<p>2. 创建目标平台X的模拟器</p>
<p>3. 启动模拟器，下载/system/framework/framework.jar</p>
<p>4. 重命名<span>framework.jar
-&gt; framework.zip</span></p>
<p>5. 从framework.zip中抽取classes.dex</p>
<p>6. 使用dex2jar工具，将其转换成classes.jar</p>
<p>7. 重命名<span>classes.jar
-&gt; framework-classes.zip</span></p>
<p>8. 拷贝android.jar &#8211;&gt; custom-android.zip</p>
<p>9. 解压custom-android.zip至custom-android文件夹</p>
<p>10. 将framework-classes.zip中所有文件拷贝至custom-android文件夹（覆盖存在的文件）</p>
<p>11. 压缩custom-android文件夹成original-android.zip</p>
<p>12. 重命名<span>original-android.zip
-&gt;&nbsp;<strong>original-android.jar</strong></span></p>
<p>打完收功。</p>
<p><strong>总结</strong></p>
<p>我们还原了android.jar，使其包含所有的internal和<span>hidden
API</span>的.class文件。这只是第一步。下一步将创建定制的android平台，使其使用未删节版的android.jar，并将其添加到Android SDK platforms文件夹中。</p>
<h2>Part 3</h2>
<p>原文路径：<a href="http://devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-3-custom-android-platform/">http://devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-3-custom-android-platform/</a></p>
<p>在上一篇中，我已经展示了如何创建一个包含所有internal和hidden API的original-android.jar。</p>
<p>接下来的工作就是要修改已经存在的Android平台（SDK_DIR/platforms/platform-X/android.jar，X表示API等级）。你可以直接使用Part2中创建的original-android.jar替换android.jar。但这样的话，你的所有工程都将直接使用internal和hidden API而没有任何限制。这不够方便，因为在多数的工程中你不希望这样。甚至，你可能更希望禁止这些API（ADT/android.jar的默认行为）。但对于一些特定的工程，你希望能够使用这些internal和hidden API。</p>
<p>为了达到这样的灵活性，你需要创建一个新的自定义的Android平台。当不需要访问internal和<span>hidden
API</span>时，你只需使用原有的Android平台。当你使用这些API时，你使用自定义的Android平台。</p>
<p><strong>Android SDK</strong><strong>文件夹结构</strong></p>
<p>让我们看一下<span>Android
SDK</span>树是如何组织的：</p>
<p><span><a href="http://devmaze.files.wordpress.com/2011/01/image5.png"><span><!--[if gte vml 1]><v:shape
id="_x0000_i1030" type="#_x0000_t75" alt="image" style='width:269.25pt;
height:270.75pt' o:button="t">
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image013.png"
o:href="http://devmaze.files.wordpress.com/2011/01/image_thumb5.png?w=359&amp;h=361"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="359" height="361" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image014.gif" alt="image" v:shapes="_x0000_i1030" /><!--[endif]--></span></a></span></p>
<p>我们需要&#8220;platforms&#8221;文件夹。看一下里面：</p>
<p><span><a href="http://devmaze.files.wordpress.com/2011/01/image6.png"><span><!--[if gte vml 1]><v:shape
id="_x0000_i1031" type="#_x0000_t75" alt="image" style='width:307.5pt;
height:210.75pt' o:button="t">
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image015.png"
o:href="http://devmaze.files.wordpress.com/2011/01/image_thumb6.png?w=410&amp;h=281"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="410" height="281" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image016.gif" alt="image" v:shapes="_x0000_i1031" /><!--[endif]--></span></a></span></p>
<p>这里列出了支持的Android平台。</p>
<p>现在，我们看一下它是如何与Eclipse设定关联的。选择你的工程，右击&#8211;&gt; Properties &#8211;&gt; Android。你将会看到一组支持的Android平台（与&#8230;/platforms/folder相似）。下面是截图：</p>
<p><span><a href="http://devmaze.files.wordpress.com/2011/01/image9.png"><span><!--[if gte vml 1]><v:shape
id="_x0000_i1032" type="#_x0000_t75" alt="image" style='width:450pt;height:358.5pt'
o:button="t">
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image017.png"
o:href="http://devmaze.files.wordpress.com/2011/01/image_thumb9.png?w=600&amp;h=478"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="600" height="478" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image018.gif" alt="image" v:shapes="_x0000_i1032" /><!--[endif]--></span></a></span></p>
<p><strong>创建新的平台</strong></p>
<p>为了创建一个新的平台，我们需要拷贝android-9文件夹 -&gt; android-9-internals。让我们做一些修正：</p>
<p>1. 删除其中的android.jar</p>
<p>2. 拷贝original-android.jar，并改名为android.jar</p>
<p>3. 修改build.prop文件：</p>
<p>&#8230;</p>
<p>ro.build.version.sdk=9 -&gt; ro.build.version.sdk=-9</p>
<p>&#8230;</p>
<p><span>ro.build.version.release=2.3 -&gt;
ro.build.version.release=2.3.extended</span></p>
<p>&#8230;</p>
<p>重启Eclipse。并确认你能看到新的平台。下面是我所看到的：</p>
<p><span><a href="http://devmaze.files.wordpress.com/2011/05/image2.png"><span><!--[if gte vml 1]><v:shape
id="_x0000_i1033" type="#_x0000_t75" alt="image" style='width:449.25pt;
height:391.5pt' o:button="t">
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image019.png"
o:href="http://devmaze.files.wordpress.com/2011/05/image_thumb2.png?w=599&amp;h=522"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="599" height="522" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image020.gif" alt="image" v:shapes="_x0000_i1033" /><!--[endif]--></span></a></span></p>
<p>为什么我选择API等级为-9？这是因为它必须是一个数字，而且它不能是9（或者其它已经存在的API等级）。否则，你自定义的平台将不能被使用（它在列表里可见，但选中后也不能正常工作，编译时仍然使用相应API等级的原始平台）。</p>
<p>下面是引用类库的截图（当前工程选中了自定义的平台）：</p>
<p><span><a href="http://devmaze.files.wordpress.com/2011/01/image10.png"><span><!--[if gte vml 1]><v:shape
id="_x0000_i1034" type="#_x0000_t75" alt="image" style='width:450pt;height:275.25pt'
o:button="t">
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image021.png"
o:href="http://devmaze.files.wordpress.com/2011/01/image_thumb10.png?w=600&amp;h=367"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="600" height="367" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image022.gif" alt="image" v:shapes="_x0000_i1034" /><!--[endif]--></span></a></span></p>
<p><strong>总结</strong></p>
<p>在上一篇中，我已经告诉你如何创建一个未删节版的android.jar。在这一篇中，我向你展示了如何创建一个自定义的Android平台，并在其中使用original-android.jar。这对于hidden API来说已经足够了。但对于<span>internal
API</span>来说，还需要另一步。这是因为ADT仍然不允许使用com.android.internal包中的类（参见上图中的&#8220;forbidden&#8221;访问规则）。下一节我将向你展示如何定制ADT来允许使用internal包中的类。</p>
<p>============华丽的分割线=============</p>
<p>在实际的操作过程中，我创建的自定义的android.jar（API 10）不能被Eclipse成功加载，会出现以下的错误框，如同网站上其它人操作的结果一样，期待解决方案。</p>
<p><span><a href="http://images.cnblogs.com/cnblogs_com/xirihanlin/201106/201106051350332191.jpg"><span><!--[if gte vml 1]><v:shape
id="_x0000_i1035" type="#_x0000_t75" alt="clip_image012" style='width:183pt;
height:135.75pt' o:button="t">
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image023.jpg"
o:href="http://images.cnblogs.com/cnblogs_com/xirihanlin/201106/201106051350332714.jpg"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="244" height="181" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image023.jpg" alt="clip_image012" v:shapes="_x0000_i1035" /><!--[endif]--></span></a></span></p>
<p>不过，作者提供了可用的自定义的android.jar，如果不想自己尝试的话，可以直接从网站下载，地址将在Part5中给出，稍等。</p>
<h2>Part 4</h2>
<p>原文路径：<span><a href="http://devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-4-customizing-adt/">http://devmaze.wordpress.com/2011/01/18/using-com-android-internal-part-4-customizing-adt/</a>
</span></p>
<p>在上一篇文章里，我描述了如何创建一个自定义的original-android.jar，以及如何创建一个自定义的Android平台来使用这个original-android.jar。这对Hidden API来说足够了。但对<span>Internal
API</span>来说，仍然还有一个包袱：Eclipse的ADT插件。它限制使用com.android.internal包中的任何类。 </p>
<p><span><!--[if gte vml 1]><v:shape id="_x0000_i1036" type="#_x0000_t75"
alt="" style='width:414.75pt;height:239.25pt'>
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image024.png"
o:href="http://devmaze.files.wordpress.com/2011/01/image.png?w=600"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="553" height="319" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image025.gif" v:shapes="_x0000_i1036" alt="" /><!--[endif]--></span></p>
<p>有几种方法可以解决这个访问限制。 </p>
<p>1） ADT源码可以下载。因此，删除/修改代码中的某些代码，从而编译出一个新的ADT是可以的。麻烦的是你需要搭建64位Linux系统，下载源码，编译等。它需要花费一些时间。当有新的ADT版本时，你需要重来一遍。 </p>
<p>2） 另外的方法就是修改ADT的字节码。用一个类似于&#8220;com/android/internax/**&#8221;的字符串替换&#8220;com/android/internal/**&#8221;。 </p>
<p>第二种方法可以用脚本实现。并且不需要访问源码以及可在Windows上操作。这也是为什么我在这篇中选用第二种解决方案的原因。 </p>
<p><strong>修改</strong><strong>ADT</strong><strong>的字节码</strong> </p>
<p>进入Eclipse的plugins文件夹。找到文件名看起来像&#8220;com.android.ide.eclipse.adt_*.jar&#8221;的文件。备份一下这个文件（以防中间有错误发生）。并拷贝这个文件到一个&#8220;experimental&#8221;文件夹，在这里，我们要完成对其字节码的修改。 </p>
<p>重命名*.jar为*.zip。解压这个文件到单独的文件夹。参看以下图片： </p>
<p><span><a href="http://devmaze.files.wordpress.com/2011/01/image11.png"><span><!--[if gte vml 1]><v:shape
id="_x0000_i1037" type="#_x0000_t75" alt="image" style='width:450pt;height:221.25pt'
o:button="t">
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image026.png"
o:href="http://devmaze.files.wordpress.com/2011/01/image_thumb11.png?w=600&amp;h=295"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="600" height="295" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image027.gif" alt="image" v:shapes="_x0000_i1037" /><!--[endif]--></span></a></span></p>
<p>现在，进入到com/android/ide/eclipse/adt/internal/project子文件夹。 </p>
<p>找到AndroidClasspathContainerInitializer.class文件。 </p>
<p><span><a href="http://devmaze.files.wordpress.com/2011/01/image12.png"><span><!--[if gte vml 1]><v:shape
id="_x0000_i1038" type="#_x0000_t75" alt="image" style='width:450pt;height:138.75pt'
o:button="t">
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image028.png"
o:href="http://devmaze.files.wordpress.com/2011/01/image_thumb12.png?w=600&amp;h=185"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="600" height="185" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image029.gif" alt="image" v:shapes="_x0000_i1038" /><!--[endif]--></span></a></span></p>
<p>这个文件包含&#8220;com/android/internal/**&#8221;字符串。接下来就是要替换这个字符串，例如&#8220;com/android/internax/**&#8221;。改变字符串的长度理论上是安全的，但最好还是替换其中的一个字母，并保持长度一致。 </p>
<p>我使用notepad++修改的，它支持非可印刷字符，因此在对其修改时，不要触碰修改非可印刷字符。 </p>
<p><span><a href="http://devmaze.files.wordpress.com/2011/01/image13.png"><span><!--[if gte vml 1]><v:shape
id="_x0000_i1039" type="#_x0000_t75" alt="image" style='width:450pt;height:334.5pt'
o:button="t">
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image030.png"
o:href="http://devmaze.files.wordpress.com/2011/01/image_thumb13.png?w=600&amp;h=446"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="600" height="446" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image031.gif" alt="image" v:shapes="_x0000_i1039" /><!--[endif]--></span></a></span></p>
<p>当做完这个，保存文件。压缩这个文件夹，保证文件名与原始文件一模一样。在我这里，文件名是：com.android.ide.eclipse.adt_8.0.1.v201012062107-82219.zip。 </p>
<p>注意：确保压缩文件的正确性。比较原始文件和修改文件的根文件结构。 </p>
<p>现在，用修改后的版本替换原来的ADT的*.jar文件。然后，启动Eclipse。 </p>
<p>在使用库窗口，你应该看到下面的样子，一切都变得那么的美好： </p>
<p><span><a href="http://devmaze.files.wordpress.com/2011/01/image14.png"><span><!--[if gte vml 1]><v:shape
id="_x0000_i1040" type="#_x0000_t75" alt="image" style='width:450pt;height:284.25pt'
o:button="t">
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image032.png"
o:href="http://devmaze.files.wordpress.com/2011/01/image_thumb14.png?w=600&amp;h=379"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="600" height="379" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image033.gif" alt="image" v:shapes="_x0000_i1040" /><!--[endif]--></span></a></span></p>
<p><strong>步骤总结</strong> </p>
<p>1. 关闭Eclipse </p>
<p>2. 从Eclipse的plugin文件夹中拷贝出ADT插件的jar文件 </p>
<p>3. 重命名<span>.jar
-&gt; .zip</span>，然后解压至独立的文件夹 </p>
<p>4. 找到<em>com/android/ide/eclipse/adt/internal/project/AndroidClasspathContainerInitializer.class</em><em>文件</em> </p>
<p>5. 用&#8220;com/android/internax/**&#8221;替换&#8220;com/android/internal/**&#8221; </p>
<p>6. 压缩这个文件夹 </p>
<p>7. 重命名<span> .zip
-&gt; .jar </span></p>
<p>8. 用修改后的jar替换原始的ADT jar文件 </p>
<p>9. 启动Eclipse </p>
<p><strong>结论</strong> </p>
<p>这是不使用反射也能使用<span>Internal
API</span>的最后一步。</p>
<h2>Part 5</h2>
<p>&nbsp;</p>
<p>原文路径：<span><a href="https://devmaze.wordpress.com/2011/01/19/using-com-android-internal-part-5-summary-and-example/">https://devmaze.wordpress.com/2011/01/19/using-com-android-internal-part-5-summary-and-example/</a>
</span></p>
<p>为了能够使用Internal和Hidden API，你需要： </p>
<p>1. 创建自定义的original-android.jar，包含所有的.class文件 </p>
<p>2. 创建自定义的Android平台来使用original-android.jar </p>
<p>3. 修改ADT插件，允许使用com.android.internal包（只为Internal API） </p>
<p>4. 创建新的工程，引用自定义的Android平台（本文中的例子） </p>
<p>在本文中，我将向你们展示如何使用那些Internal和Hidden API。 </p>
<p>此外，在本文的结尾，我列出了一些自定义的Android平台，它们都包含Internal和<span>Hidden
API</span>。我附带了它们，是为了可能你不想花太多时间在这方面，但又想快速的尝试什么。 </p>
<p><strong>例子</strong> </p>
<p>创建一个新工程，选择2.3.extender平台： </p>
<p><span><!--[if gte vml 1]><v:shape
id="_x0000_i1041" type="#_x0000_t75" alt="" style='width:300.75pt;height:459.75pt'>
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image034.png"
o:href="http://devmaze.files.wordpress.com/2011/05/image3.png"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="401" height="613" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image035.jpg" v:shapes="_x0000_i1041" alt="" /><!--[endif]--></span></p>
<p>下面是代码： </p>
<p><span><!--[if gte vml 1]><v:shape
id="_x0000_i1042" type="#_x0000_t75" alt="" style='width:513pt;height:339.75pt'>
<v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtml1\01\clip_image036.png"
o:href="http://devmaze.files.wordpress.com/2011/05/image4.png"/>
</v:shape><![endif]--><!--[if !vml]--><img border="0" width="684" height="453" src="file:///C:/Users/ADMINI~1/AppData/Local/Temp/msohtml1/01/clip_image037.jpg" v:shapes="_x0000_i1042" alt="" /><!--[endif]--></span></p>
<p>这个代码使用了<span>Internal
API</span>（PowerProfile）和Hidden API（isWifiApEnabled）。我不用使用反射就能编译并运行这些代码。 </p>
<p><strong>自定义平台</strong> </p>
<p>下面有些平台，是我为自己创建的。只用拷贝它们到SDK_DIR\platforms文件夹下。这只是让Hidden API可用。对于<span>Internal
API</span>，你需要修改你的ADT插件。 </p>
<p>API 3：<span><a href="http://www.megaupload.com/?d=S1F2MKYZ">http://www.megaupload.com/?d=S1F2MKYZ</a>
</span></p>
<p>API 4：<span><a href="http://www.megaupload.com/?d=VUCTRI3Y">http://www.megaupload.com/?d=VUCTRI3Y</a>
</span></p>
<p>API 7：<span><a href="http://www.megaupload.com/?d=7ITNILBK">http://www.megaupload.com/?d=7ITNILBK</a>
</span></p>
<p>API 8：<span><a href="http://www.megaupload.com/?d=EXT5FKKT">http://www.megaupload.com/?d=EXT5FKKT</a>
</span></p>
<p>API 9：<span><a href="http://www.megaupload.com/?d=EXT5FKKT">http://www.megaupload.com/?d=EXT5FKKT</a>
</span></p>
<p>API 10：<span><a href="http://www.megaupload.com/?d=FCV78A9M">http://www.megaupload.com/?d=FCV78A9M</a>
</span></p>
<p>==============华丽的分割线<span>=============
</span></p>
<p>我尝试了其中的几个自定义平台，发现，internal 和hidden API真的是可用了，但也有一些意外的问题，如<span>AlertDialog.Builder(Context
context)</span>居然说Context参数是多余的。。 </p>
<p>没花时间去研究为什么会这样，如果哪位童鞋知道原因，告诉我哈~~</p>
<p>&nbsp;</p>
@import url(http://www.cppblog.com/CuteSoft_Client/CuteEditor/Load.ashx?type=style&amp;file=SyntaxHighlighter.css);@import url(/css/cuteeditor.css);<img src ="http://www.cppblog.com/franksunny/aggbug/156865.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/franksunny/" target="_blank">frank.sunny</a> 2011-09-26 17:52 <a href="http://www.cppblog.com/franksunny/archive/2011/09/26/156865.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>