﻿<?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++博客-xiaoguozi's Blog-随笔分类-Android &amp; Ios</title><link>http://www.cppblog.com/guojingjia2006/category/17161.html</link><description>Pay it forword - 我并不觉的自豪，我所尝试的事情都失败了······习惯原本生活的人不容易改变，就算现状很糟，他们也很难改变，在过程中，他们还是放弃了······他们一放弃，大家就都是输家······让爱传出去，很困难，也无法预料，人们需要更细心的观察别人，要随时注意才能保护别人，因为他们未必知道自己要什么·····</description><language>zh-cn</language><lastBuildDate>Sun, 24 Feb 2013 09:33:44 GMT</lastBuildDate><pubDate>Sun, 24 Feb 2013 09:33:44 GMT</pubDate><ttl>60</ttl><item><title>phonegap js 和 本地代码 调用原理(转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/198001.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Fri, 22 Feb 2013 07:16:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/198001.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/198001.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/198001.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/198001.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/198001.html</trackback:ping><description><![CDATA[<div><p><strong>iOS</strong><strong>：</strong>通过让本地代码拦截JavaScript中调用的 window.location=&#8221;gap://Class.method/args&#8221;命令，来实现从JavaScript到本地代码之间的通信。在本地 代码拦截该命令后，解析获取的参数，然后调用对应的类、方法并传递参数。对应的，使用 UIWebView.stringByEvaluatingJavaScriptFromString来实现本地代码调用JavaScript。</p><p><strong>Android</strong><strong>：</strong>通 过拦截JavaScript的prompt命令实现从JavaScript到本地代码的通信。JavaScript  prompt命令默认会弹出对话框，而PhoneGap的Android本地代码会拦截该对话框，并进一步取得JavaScript数据。相应 的，Android上的PhoneGap内部，使用Java实现了一个HTTP服务器，通过持久性的XHR连接，JavaScript可以不断轮询内部 XHR服务器存储的信息，从而实现了从Java到JavaScript方向的通信。</p><p><strong>BlackBerry 4.x</strong><strong>：</strong>JavaScript 与本地代码之间的唯一通信方式是通过document.cookie实现的。JavaScript设定Cookie，本地代码从Cookie中获取信息。 对应的，本地代码也可以设定Cookie，允许JavaScript从Cookie中获取本地代码信息。</p><p><strong>BlackBerry WebWorks</strong><strong>：</strong>新 的BlackBerry WebWorks  SDK更好地支持了Java与JavaScript之间的交互通信。通过ScriptEngine.addExtension，Java对象可以被暴露给 JavaScript，而对应的Java可以使用ScriptEngine.executeScript来调用JavaScript。</p><p><strong>Windows Phone 7</strong><strong>：</strong>在Windows Phone 7中，JavaScript通过window.external.Notify可以将信息发送给本地代码。而相应的，WebBrowser.InvokeScript允许本地代码调用JavaScript。</p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/198001.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-22 15:16 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/22/198001.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>浏览器探究——执行网页跳转 (转) </title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/197999.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Fri, 22 Feb 2013 07:07:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/197999.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197999.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/22/197999.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197999.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197999.html</trackback:ping><description><![CDATA[<div><div id="article_content">  <p align="center">浏览器探究&#8212;&#8212;执行网页跳转</p> <p>Main线程中执行。</p> <p>UrlInputView</p> <p>控件UrlInputView执行OnEditorAction-&gt;finishInput</p> <p>/**</p> <p>&nbsp;*url/search input view</p> <p>&nbsp;*handling suggestions</p> <p>&nbsp;*/</p> <p>public class UrlInputView extendsAutoCompleteTextView</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;implements OnEditorActionListener,</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CompletionListener, OnItemClickListener, TextWatcher</p> <p>由此可见，UrlInputView即输入网址的那个控件，该控件包括输入URL和执行搜索输入。</p> <p>Controller</p> <p>在经过UrlInputView的处理后，会调用Controller.handleNewIntent。</p> <p>Controller是浏览器中最重要的类，作为整个浏览器的主控类。Controller中有IntentHandler，这里会调用IntentHandler.onNewIntent</p> <p>IntentHandler</p> <p>//Handle all browser related intents</p> <p>这里对一些特殊的URL做处理这里还包含了一些debug信息，比如&#8221;about:debug.dom.file"这种形式的网址。如果是普通的 url，不需要做特殊处理，则执行到最后执行Controller.loadUrlDataIn，即经过了IntentHandler后又回到了 Controller。</p> <p>Controller</p> <p>/**</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;* Load UrlData into a Tab and update the title bar to reflect the new</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;* load.&nbsp; Call this instead ofUrlData.loadIn directly.</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;* @param t The Tab used to load.</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;* @param data The UrlData being loaded.</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;*/</p> <p>经过简单的处理，会把要加载的url作为参数调用被显示的tab，即执行Tab.loadUrl。这样看来Controller还只是个桥梁的作 用，把从UrlInputView得到的url，交给IntentHandler做处理，然后再把url交给Tab做实际的加载。</p> <p>Tab</p> <p>//Class for maintaining Tabs with a mainWebView and a subwindow.</p> <p>Tab作为一个窗口的抽象概念而存在，对一个窗口的操作都需要通过Tab来进入。另外有个TabControl用来管理所有的Tab.</p> <p>执行语句mMainView.loadUrl。这个mMainView是个WebView。从这终于进入了framework的webkit层了。</p> <p>WebView</p> <p>WebView作为Tab的核心控件，负责网页的真正的加载，显示等操作，是framework/webkit中最主要的类。通过Tab来找到WebView.</p> <p>在WebView.loadUrl-&gt;WebView.loadUrlImpl中会向WebViewCore发消息，</p> <p>WebViewCore</p> <p>该类在一个独立的线程中运行，该类主要通过Message，Handler的机制在WebView与WebViewCore之间通讯的，这里 WebView是在Main线程中，而WebViewCore是在单独的&nbsp;WebViewCoreThread线程中。WebViewCore是 framework/webkit核心类，它在单独的线程中来接收消息，每个消息相当于一个请求的任务，而这个WebViewCore相当于一个服务，它 在消息循环中不停的接收任务（消息），然后处理任务，然后再接收下一个任务（消息）。任务的执行很多是通过jni调用c层webkit来操作的。在c层 webkit有webkit/Source/WebKit/android/jni/WebViewCore.cpp与该java层的 WebViewCore对应。即这个WebViewCore是java层与c层的一个主要桥梁。</p> <p>在WebView.loadUrlImpl在执行了mWebViewCore.sendMessage(EventHub.LOAD_URL, arg);则WebViewCore接收到LOAD_URL任务，执行对它的处理。</p> <p>WebViewCore中有BrowserFrame成员</p> <p>BrowserFrame</p> <p>BrowserFrame extends  Handler它也有很多JNI与C层的webkit的Webkit/Source/WebKit/android/jni /WebCoreFrameBridge.cpp对应。它用来处理页面的具体情况，即Frame，这个Frame是一个具体的页面的概念。</p> <p>WebViewCore.loadUrl会调用BrowserFrame.loadUrl。BrowserFrame会调用到WebCoreFrameBridge.cpp的LoadUrl。</p> <p>这里略去c层的处理部分。</p> <p>WebCoreFrameBridge.cpp的LoadUrl执行后会执行到WebCoreFrameBridge.cpp的loadStarted，这里又会回调BrowserFrame.loadStarted函数。</p> <p>/**</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;* native callback</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;* Indicates the beginning of a new load.</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;* This method will be called once for the main frame.</p> <p>&nbsp;&nbsp;&nbsp;&nbsp;*/</p> <p>即通过BrowserFrame的loadUrl在c层做处理后，又回调到BrowserFrame的loadStarted。</p> <p>这里在理一下，主线程中有Tab，Tab里有WebView。即WebView也是运行在主线程的。而WebView里有WebViewCore，WebViewCore又是运行在一个单独的线程里的。</p> <p>那么多个WebView是否就对应多个WebViewCore和多个WebViewCore线程呢？</p> <p>看下WebView，WebView的构造函数中会mWebViewCore= new WebViewCore(context, this,  mCallbackProxy,  javaScriptInterfaces);创建了WebViewCore对象，即每个WebView都有个WebViewCore对象。但是 WebViewCore中的WebCoreThread是一个静态的，即一个单例的。而这个WebCoreThread中运行的 privatestatic Handler sWebCoreHandler;也是个静态的。</p> <p>由此可见WebViewCore类本身就是个外壳，真正处理任务的是WebCoreThread及其里面的sWebCoreHandler，这个真 正处理任务的是静态的，只有一份，WebViewCore这个外壳只是沟通webView与WebCoreThread的桥梁，相当于一个代理类。是 WebCoreThread提供给外面的处理接口。</p> <p>那么BrowserFrame呢？在WebViewCore的构造最后会发送一个INITIALIZE的消息给 WebCoreThread，WebCoreThread接收到后会执行WebViewCore.initialize，这个函数会构造 mrowserFrame。即每次构造WebViewCore时同样会构造一个BrowserFrame。但是为什么不在主线程中创建呢？一方面它是继承 自Handler，这个Handler需要在WebViewCoreThread线程中运行，所以需要在该线程来创建。另一方面在它的构造中需要创建 JWebCoreJavaBridge这个是C层的类，貌似这个类也需要在WebViewCoreThread线程中创建和销毁才行。</p> <p>由上分析可知，WebView包含一个WebViewCore，WebViewCore包含一个BrowserFrame。多个 WebViewCore共同对应唯一的一个WebCoreThread。WebViewCore只是个外壳，WebCoreThread作为任务的处 理，WebCoreThread主要就是个大Handler不停的处理接收到的任务，WebCoreThread会调用很多jni来调用webkit接 口，BrowserFrame也有很多jni来调用webkit接口。由他们的组成情况又可知WebCoreThread直接调的jni是多个 WebView共同的，即不跟具体的WebView相关，而通过BrowserFrame调用的则跟一个具体的WebView相关了。</p> <p>CallBackProxy</p> <p>/**</p> <p>&nbsp;*This class is a proxy class for handling WebCore -&gt; UI thread messaging. All</p> <p>&nbsp;*the callback functions are called from the WebCore thread and messages are</p> <p>&nbsp;*posted to the UI thread for the actual client callback.</p> <p>&nbsp;*/</p> <p>/*</p> <p>&nbsp;*This class is created in the UI thread so its handler and any private classes</p> <p>&nbsp;*that extend Handler will operate in the UI thread.</p> <p>&nbsp;*/</p> <p>class CallbackProxy extends Handler {</p> <p>另外还有个类CallBackProxy。它存在于WebView，WebViewCore，BrowserFrame中。在WebView构造函 数中创建，并在WebViewCore和BrowserFrame构造函数中作为参数传入并赋值给它们内部的引用。可见CallBackProxy是 WebViewCore和BrowserFrame向WebView回调的桥梁。</p> <p>CallBackProxy是一个Handler，它在主线程中被创建，即WebViewCore和BrowserFrame会通过发消息的方式将 需求传递到主线程的CallBackProxy中，CallBackProxy的事件处理循环会执行相应的处理。可见主线程中WebView通过 WebViewCore发消息给WebViewCoreThread线程执行操作，WebViewCoreThread线程又会通过 CallBackProxy回调消息给主线程执行处理。</p> <p>再回到BrowserFrame.loadStarted处。</p> <p>BrowserFrame.loadStarted会调用 CallBackProxy.onPageStarted，CallBackProxy.onPageStarted中会给发PAGE_STARTED消 息，主线程中的CallBackProxy的handleMessage会执行处理。在处理时会执行 WebViewClient.onPageStarted。</p> <p>WebViewClient</p> <p>mWebViewClient本身只是提供一个接口基类，Tab中private finalWebViewClient mWebViewClient = new WebViewClient()</p> <p>// WebViewClient implementation for themain WebView</p> <p>//Set the WebViewClient that will receivevarious notifications and requests. This will replace the current handler.</p> <p>这个WebViewClient会传给Tab中的WebView的CallbackProxy。这个WebViewClient会让CallbackProxy返回信息或回调处理给Tab。</p> <p>回到WebViewClient.onPageStarted，这里做了一些判断处理后，调用WebViewController.onPageStarted。</p> <p>WebViewController</p> <p>//WebView aspect of the controller</p> <p>public interface WebViewController</p> <p>在Tab的构造时，WebViewController会作为参数传入，并设置给Tab。那么Tab中的WebViewController到底是什么？Tab是在TabController中创建的，而Tab构造时传入的是Controller。</p> <p>public class Controller implementsWebViewController, UiController</p> <p>由此可见Tab中的WebViewController其实就是对应Controller。只是通过WebViewController接口作为引用的。即Tab中只关心Controller的WebViewController接口部分。</p> <p>这样就可以看出BrowserFrame通过消息与主线程中的CallbackProxy处理循环关联，CallbackProxy又通过 WebViewClient与Tab关联，回调了Tab提供的接口，而Tab又通过WebViewController接口，调用了Controller 这个核心类的函数。即调用到WebViewController.onPageStarted，也即是 Controller.onPageStarted.</p> <p>Controller.onPageStarted中一个主要的处理是</p> <p>if (!mNetworkHandler.isNetworkUp())  {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;view.setNetworkAvailable(false);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}这里判断网络是否是激活状态，如果不是激活 状态则执行WebView.SetNetworkAvailable(Boolean networkUp)</p> <p>/**&nbsp;&nbsp;&nbsp;&nbsp; * Inform WebView ofthe network state. This is used to  set&nbsp;&nbsp;&nbsp;&nbsp;* the JavaScript property window.navigator.isOnline and&nbsp;&nbsp;&nbsp;&nbsp; *  generates the online/offline event asspecified in HTML5, sec. 5.7.7&nbsp;&nbsp;&nbsp;&nbsp;  *@param networkUp boolean indicating if network is  available&nbsp;&nbsp;&nbsp;&nbsp; */</p> <p>该函数其实就是像WebViewCore发送SET_NETWORK_STATE消息，好吧，又回到了WebViewCoreThread线程了， 处理的方式是直接BrowserFrame.sJavaBridge.setNetworkOnLine。这个函数是个jni函数，其调用的是c层 JavaBridge的函数。这个jni函数主要就是通知c层WebCore网路状态已经变化，并把最新的网络状态告诉WebCore。</p> <p>由此可见WebView.setNetworkAvailable还是个挺重要的函数，通过它才能告诉底层网络的状态。</p> <p>那么额外看下网络状态如何获取并传递的，在loadUrl发起加载url这块判断了一次，即当无网络时主动通知一次。其他的呢？</p> <p>在NetworkStateHandler中会注册一个BroadcastReceiver，该receiver会关注 ConnectivityManager.CONNECTIVITY_ACTION广播，该广播是在网络发生连接变化时被发出，该receiver在接收 到网络连接变化的广播后，会查询当前的连接情况，然后执行NetworkStarteHandler.onNetworkToggle，这个函数里面就会 调用WebView.setNetworkAvailable，也即跟上述描述的那样，给WebViewCoreThread线程发消息，通知c层 WebCore网络的最新状态。</p> <p>这样就清楚了，网络广播时会通知C层最新状态，在执行loadUrl时，如果网络不可用也会通知C层网络最新状态。</p> <p>这里先跨过Controller.onPageStarte的其他处理过程。此次任务处理完毕。</p> <p>此时WebViewCoreThread线程中BrowserFrame仍然处于c层的LoadUrl中，此时的调用栈为:</p> <p>BrowserFrame.nativeLoadUrl</p> <p>BrowserFrame.loadUrl</p> <p>WebViewCore.loadUrl</p> <p>这里又会回调BrowserFrame.shouldInterceptRequest，它会调用BrowserFrame.inputStreamForAndroidResource函数</p> <p align="left">&nbsp;/**<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Get&nbsp;the&nbsp;InputStream&nbsp;for&nbsp;an&nbsp;Android&nbsp;resource<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;There&nbsp;are&nbsp;three&nbsp;different&nbsp;kinds&nbsp;of&nbsp;android&nbsp;resources:<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;-&nbsp;file:///android_res<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;-&nbsp;file:///android_asset<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;-&nbsp;content://<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@param&nbsp;url&nbsp;The&nbsp;url&nbsp;to&nbsp;load.<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;@return&nbsp;An&nbsp;InputStream&nbsp;to&nbsp;the&nbsp;android&nbsp;resource<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/ </p> <p>这个函数会对几种特殊的url做不同的处理，当输入一个标准的http的url时，该函数不起什么作用。</p> <p>BrowserFrame.shouldInterceptReques接下来会调用 CallbackProxy.shouldInterceptRequest，看到调用CallbackProxy的函数，基本上就是要发消息给主线程让 主线程去处理任务了，这里发送了LOAD_RESOURCE消息，主线程接收后执行WebViewClient.onLoadResource。回到 BrowserFrame.nativeLoadUrl处，此时这个jni的函数终于执行完毕，也不再回调其他函数了，该函数完 成，WebViewCoreThread线程执行完LoadUrl的处理。</p> <p>当没有连接网络时，有个单独的线程会执行JWebCoreJavaBridge.signalServiceFuncPtrQueue这个JNI的 回调函数，该回调函数会发FYBCPTR_MESSAGE消息给WebViewCoreThread线程，但处理函数是 JWebCoreJavaBridge.handle，由此可见WebViewCoreThread线程不仅仅有一个Handler在处理事件.</p> <p>JWebCoreJavaBridge</p> <p>JWebCoreJavaBridge extends Handler  可见JWebCoreJavaBridge也是个Handler也是在WebViewCoreThread线程中运行的，只是发送消息的线程不是主线程， 是另一个单独的线程，并且消息的发送来源是JNI的回调。</p> <p>JWebCoreJavaBridge对应的JNI是webkit/Source/WebKit/android/jni/JavaBridge.cpp的函数。</p> <p>JWebCoreJavaBridge处理FYBCPTR_MESSAGE消息时会调用一个JNI函数，在JNI函数里又会回调BrowserFrame.reportError。</p> <p>又是跟上面类似的流程，BrowserFrame.reportError调用CallbackProxy.onReceiveError，这个 CallbackProxy里会发消息REPORT_ERROR，然后主线程接收消息，执行 WebViewClient.onReceivedError。</p> <p>接着又是收到FUNCPTR_MESSAGE消息，调用nativeServiceFuncPtrQueue，但是这里回调了 BrowserFrame.loadStarted，然后的处理流程跟上述的LoadUrl中调用BrowserFrame.loadStarted过程 一样。</p> <p>接着WebViewCoreThread线程又是收到FUNCPTR_MESSAGE消息，调用 JWebCoreJavaBridge.nativeServiceFuncPtrQueue，WebViewCore.contentDraw被调用， 该函数发送WEBKIT_DRAW，处理该消息会执行绘制的操作。</p> <p>接着WebViewCoreThread线程中JWebCoreJavaBridge.handleMessage又被调用，还是 FUNCPTR_MESSAGE消息，仍然是调用nativeServiceFuncPtrQueue。但此时BrowserFrame收到 loadFinished的回调，发PAGE_FINISHED消息，主线程接收消息处理时会执行WebView.onPageFinished和 WebViewClient.onFinished.</p>  </div></div><div>http://blog.csdn.net/hxwwf/article/details/7281318</div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197999.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-22 15:07 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/22/197999.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android root权限获取大揭秘(转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/20/197955.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Wed, 20 Feb 2013 08:07:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/20/197955.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197955.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/20/197955.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197955.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197955.html</trackback:ping><description><![CDATA[<div><div> 				   <div id="content"> <p><a style="color:black;text-decoration:none;border-bottom:1px dashed #333;" href="http://os-android.liqucn.com/" target="_blank">android</a> <a style="color:black;text-decoration:none;border-bottom:1px dashed #333;" href="http://www.liqucn.com/rj/18902.shtml" target="_blank">root</a>权限获取的教程有很多，为了让大家更进一步的了解root的奥秘所在，灵客风特为您奉献本文，希望对您有所帮助。</p> <p>Android的<a style="color:black;text-decoration:none;border-bottom:1px dashed #333;" href="http://www.liqucn.com/" target="_blank">应用</a>程序入口肯定是<a style="color:black;text-decoration:none;border-bottom:1px dashed #333;" href="http://os-java.liqucn.com/" target="_blank">java</a>程序。应用程序的启动者是由<a style="color:black;text-decoration:none;border-bottom:1px dashed #333;" href="http://www.liqucn.com/rj/c/298/" target="_blank">系统</a>临时根据Androidmanifest.xml中定义的权限而创建的临时用户。而不像linux那样是使用登陆者的身份启动，从而使得进程具有登陆者的所有权限。这也是Android的安全机制之一。</p> <p>新的权限机制也带来新的问题，Android给应用程序的权限是按功能来分，java虽然可以访问文件系统。但由于应用程序本身是临时用户启动，这个临时用户权限十分有限。因此诞生了&lt;<a style="color:black;text-decoration:none;border-bottom:1px dashed #333;" href="http://www.liqucn.com/article/39745.shtml" target="_blank">越狱</a>/root机器&gt;这样的产物。</p> <p>其实root机器不是真正能让你的应用程序具有root权限。它原理就跟linux下的像sudo这样的命令。在系统的bin目录下放个su程序并属主是root并有suid权限。则通过su执行的命令都具有Android root权限。</p> <p>Su的源代码网上也有，有兴趣的同学去google下。</p> <p>当然使用临时用户权限想把su拷贝的/system/bin目录并改属性并不是一件容易的事情。这里用到2个工具跟2个命令。工具就是busybox。不熟悉的同学可以去网上google下。这个太有名了我就不多说了。</p> <p>把busybox拷贝到你有权限访问的目录然后给他赋予4755权限，你就可以用它做很多事了。</p> <p>当然busybox只能不能提升权限，真正提升权限的是ratc这个程序，这个程序中一键root包里面可以找到，作用是rooting在adb的shell。</p> <p>网上介绍Ratc的文章不多，它是rage against the cage  的缩写。是真正的提升权限的破解程序。虽然我没看过源代码，但估计是利用adb源代码部分内容来实现的，原理估计跟模拟器使用adb  shell登陆可以获得root shell差不多。（因为它运行需要adb连接才会成功）。</p> <p>使用busybox前先运行ratc，这样运行busybox的UID将是0，也就是root。</p> <p>首先把system目录改成可读性的：busybox mount -o remount,rw /system，</p> <p>当然你还不能改下面的文件，因为system下文件的所有者都不是你。</p> <p>但你可以偷梁换柱把system下的目录给换掉。</p> <p>使用命令Busybox mount -t tmpfs none /system/xbin，呵呵这下xbin目录你随便写了。</p> <p>将su跟busybox弄过去cp /data/data/xxx/su /system/xbin。然后赋权限chmod 4755 /system/xbin/su。</p> <p>然后使目录生效busybox --install -s /system/xbin，</p> <p>别忘善后busybox mount -o remount,ro /system去掉system可写。</p> <p>这样只是临时的，只能用su跟busybox能执行一些原来系统没有权限执行的命令而已。当系统重启后/system/xbin又变为原来的文件。 真正要改系统的话需要自己写内核代码（相当于windows的驱动程序）。内核文件拥有所有权限。使用busybox命令insmod  /data/data/xxx/xxx.ko装载内核文件，你想干嘛就可以干嘛了。</p> <p>当然我们不是搞破解的没必要去改别人的机器，我们只是想让自己应用程序具有root权限而已。所以临时的su就可以了。我们用c++写一个可执行文 件。使用socket可以跟java的程序通讯。然后将需要使用root权限才能执行的代码放在c++程序里，然后java程序中创建新的su进程，将 c++程序带全路径作为参数1。启动后就可以通过socket调用c++函数去执行你想干的事了。</p> <p>最后程序执行完了别忘了善后busybox umount /system/xbin。</p> <p>最后说说要注意的事情，如果机器已经拥有Android root权限的话就不需要做这些事情了，但root过的机器都有装有个权限管理的程序。会弹出对话框。但这个程序管理能力有限，如果不想让他弹出的话。也许可以通过改su文件名来解决。有兴趣的同学不妨试试。</p></div>							</div></div><br /><div><div id="article_content">  <span style="font-size:18px">现在Android系统的root破解基本上成为大家的必备技能！网上也有很多中一键破解的 软件，使root破解越来越容易。但是你思考过root破解的原理吗？root破解的本质是什么呢？难道是利用了Linux  kernal的漏洞吗？本文将简单对root的破解原理进行分析。</span> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp; 网上有一篇文章已经对root破解的基本原理进行了简单介绍，大家可以先参考一下《</span><a href="http://hi.baidu.com/%CF%B1%B8%BE%C2%B1%C3%E6/blog/item/14c5dc296003ce225243c170.html" target="_blank"><span style="font-size:18px">android root权限破解分析</span></a><span style="font-size:18px">》，本文只能说对root原理进行了方向性的描述，但是在一些具体的方面没有描述清楚。本文将会对其进行一些必要的扩展和补充。</span></p> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp; 如果你进行过程序开发，在root过的手机上面获得root权限的代码如下：</span> </p> <div id="codeSnippetWrapper" style="border-bottom:silver 1px solid; text-align:left; border-left:silver 1px solid; padding-bottom:4px; line-height:12pt; background-color:#f4f4f4; margin:20px 0px 10px; padding-left:4px; width:97.5%; padding-right:4px; font-family:'Courier New',courier,monospace; direction:ltr; max-height:200px; font-size:8pt; overflow:auto; border-top:silver 1px solid; border-right:silver 1px solid; padding-top:4px"> <div id="codeSnippet" style="border-bottom-style:none; text-align:left; padding-bottom:0px; line-height:12pt; background-color:#f4f4f4; border-left-style:none; padding-left:0px; width:100%; padding-right:0px; font-family:'Courier New',courier,monospace; direction:ltr; border-top-style:none; color:black; border-right-style:none; font-size:8pt; overflow:visible; padding-top:0px"> <div bg_java"=""><div><div><strong>[java]</strong> <a href="http://blog.csdn.net/vvipxwj/article/details/7420240#" title="view plain">view plain</a><a href="http://blog.csdn.net/vvipxwj/article/details/7420240#" title="copy">copy</a><a href="http://blog.csdn.net/vvipxwj/article/details/7420240#" title="print">print</a><a href="http://blog.csdn.net/vvipxwj/article/details/7420240#" title="?">?</a></div></div><ol start="1"><li><span>Runtime.getRuntime().exec("su");&nbsp;DataOutputStream&nbsp;os&nbsp;=&nbsp;new&nbsp;DataOutputStream(process.getOutputStream());&nbsp;&nbsp;</span></li><li>......&nbsp;&nbsp;</li><li>os.writeBytes(<span>"exit\n");&nbsp;&nbsp;</span></li><li>os.flush();&nbsp;&nbsp;</li></ol></div></div> </div> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp; 从上面代码我们可以看到首先要运行su程序，其实root的秘密都在su程序中，《</span><a href="http://hi.baidu.com/%CF%B1%B8%BE%C2%B1%C3%E6/blog/item/14c5dc296003ce225243c170.html" target="_blank"><span style="font-size:18px">android root权限破解分析</span></a><span style="font-size:18px">》中讲到Android系统默认的su程序只能root和shell可以用运行su，这个是安全的。如果把这个限制拿掉，就是root破解了！</span></p> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp; 下面我们仔细分析一下程序是怎样获得root权限的，如果对Linux的su命令熟悉的朋友可能知道su程序都设置SUID位，我们查看一下我的手机（已经root破解）上的su权限设置，</span></p> <p><img src="http://api.photoshop.com/v1.0/accounts/a6dba90e84ba45f8aa3ec8f7953a00d0/assets/8e179ed1b58e45e68b843c3cfe37788d" alt="" height="121" width="649" /> </p> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们发现su的所有者和所有组都是root，是其实是busybox的软链接，我们查看busybox的属性发现，其设置了SUID和SGID，并且所有者和所有组都是root。SUID和SGID的作用是什么呢？如果你不太清楚，请参考《</span><a href="http://my.unix-center.net/%7ESimon_fu/?p=607"><span style="font-size:18px">Linux进程的实际用户ID和有效用户ID</span></a><span style="font-size:18px">》，这样运行busybox的普通用户，busybox运行过程中获得的是root的有效用户。su程序则是把自己启动一个新的程序，并把自己权限提升至root（我们前面提到su其实就是busybox，运行期它的权限是root，当然也有权限来提升自己的权限）。</span></p> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp; 再强调一下不光root手机上su需要设置SUID，所有的Linux系统上的su程序都需要设置SUID位。请参考一下UC服务器的su的权限情况：</span></p> <p><img src="http://api.photoshop.com/v1.0/accounts/a6dba90e84ba45f8aa3ec8f7953a00d0/assets/96ceaa76358442fe96cb08297e77a53d" alt="" height="69" width="446" /> </p> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp; 我们发现su也设置了SUID位，这样普通用户也可以运行su程序，su程序会验证root密码，如果正确su程序可以把用户权限提高的root（因为其设置SUID位，运行期是root权限，这样其有权限提升自己的权限）。</span></p> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp;  这样我们就可以看出其实Android系统的破解的根本原理就是替换掉系统中的su程序，因为系统中的默认su程序需要验证实际用户权限（只有root和 shell用户才有权运行系统默认的su程序，其他用户运行都会返回错误）。而破解后的su将不检查实际用户权限，这样普通的用户也将可以运行su程序， 也可以通过su程序将自己的权限提升。</span></p> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp;  到这里大家对root破解不感到神秘了吧。root破解没有利用什么Linux内核漏洞（Linux内核不可能有这么大的漏洞存在），可以理解成root 破解就是在你系统中植入&#8220;木马su&#8221;，说它是&#8220;木马&#8221;一点儿都不为过，假如恶意程序在系统中运行也可以通过su来提升自己的权限的这样的结果将会是灾难性 的。所以一般情况下root过手机都会有一个SuperUser应用程序来让用户管理允许谁获得root权限，也算是给系统加了一层保险吧！ </span></p> <p><span style="font-size:18px">&nbsp;&nbsp;&nbsp;&nbsp; 如上是Simon的个人对root破解的一些认识，如果有错误的地方，欢迎朋友们指正.</span></p>  </div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197955.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-20 16:07 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/20/197955.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[CyanogenMOD移植教程]第二章：android 源码总体结构 (转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/20/197952.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Wed, 20 Feb 2013 06:16:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/20/197952.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197952.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/20/197952.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197952.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197952.html</trackback:ping><description><![CDATA[<div><div style="text-indent: 2em;">&#8211; Makefile (全局的Makefile文件)</div> <div style="text-indent: 2em;">&#8211; bionic (Bionic含义为仿生,这里面是一些基础的C库源代码)</div> <div style="text-indent: 2em;">&#8211; bootloader (引导加载器)</div> <div style="text-indent: 2em;"> build目录中的内容不是目标所用的代码,而是编译和配置所需要的脚本和工具)</div> <div style="text-indent: 2em;">&#8211; build (build目录中的内容不是目标所用的代码,而是编译和配置所需要的脚本和工具)</div> <div style="text-indent: 2em;">&#8211; cts (Android兼容性测试套件标准)</div> <div style="text-indent: 2em;">&#8211; libcore (核心库相关)</div> <div style="text-indent: 2em;">Dalvik虚拟机 针对嵌入式设备优化的Java</div> <div style="text-indent: 2em;">Java虚拟机)</div> <div style="text-indent: 2em;">&#8211; dalvik ( Dalvik虚拟机,针对嵌入式设备优化的Java虚拟机)</div> <div style="text-indent: 2em;">&#8211; development (创建应用程序所需要的模板和工具)</div> <div style="text-indent: 2em;">qcom,</div> <div style="text-indent: 2em;">&#8211; device (与具体设备相关的一些编译脚本和库,如htc,qcom,samsung等)</div> <div style="text-indent: 2em;">&#8211; external (Android使用的一些外部的开源框架和库)</div> <div style="text-indent: 2em;">(应用程序的框架层,SDK</div> <div style="text-indent: 2em;">SDK的接口基本都是在这里实现的)</div> <div style="text-indent: 2em;">&#8211; frameworks (应用程序的框架层,SDK的接口基本都是在这里实现的)</div> <div style="text-indent: 2em;">&#8211; hardware (与硬件相关的库)</div> <div style="text-indent: 2em;">Linux2.6</div> <div style="text-indent: 2em;">&#8211; kernel (Linux2.6的内核源代码)</div> <div style="text-indent: 2em;">&#8211; ndk (本地开发套件--C语言开发套件)</div> <div style="text-indent: 2em;">--C</div> <div style="text-indent: 2em;">Android的各种应用程序)</div> <div style="text-indent: 2em;">&#8211; packages (Android的各种应用程序)</div> <div style="text-indent: 2em;">&#8211; prebuilt (Android在各种平台下编译的预置脚本)</div> <div style="text-indent: 2em;">&#8211; sdk (SDK及模拟器)</div> <div style="text-indent: 2em;">Android的底层的一些库)</div> <div style="text-indent: 2em;">&#8211; system (Android的底层的一些库)</div> <div style="text-indent: 2em;">`&#8211; vendor (厂商私有的代码)</div> <div style="text-indent: 2em;"></div> <div style="text-indent: 2em;"></div> <div style="text-indent: 2em;">~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</div> <div style="text-indent: 2em;"> <div>packages/</div> <div>|&#8211; apps (各种应用程序,如联系人、浏览器等)</div> <div>|&#8211; experimental (一些实验性的项目,如错误报告)</div> <div>|&#8211; inputmethods (输入法相关)</div> <div>|&#8211; providers (各种数据源实现,如联系人数据、媒体库等信息)</div> <div>|&#8211; wallpapers (各种壁纸程序)</div> </div> <div style="text-indent: 2em;"></div> <div style="text-indent: 2em;"> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</div>  <div style="text-indent: 2em;">Android Framework功能介绍</div> <div style="text-indent: 2em;">android.app :提供高层的程序模型和基本的运行环境。</div> <div style="text-indent: 2em;">android.content :包含对各种设备上的数据进行访问和发布。</div> <div style="text-indent: 2em;">android.database :通过内容提供者浏览和操作数据库。</div> <div style="text-indent: 2em;">android.graphics :底层图形库,包含画布、点、矩形等,可以将其直接绘制到屏幕上。</div> <div style="text-indent: 2em;">android.location :定位和相关服务的类。</div> <div style="text-indent: 2em;">android.media :提供一些类管理多种音频、视频的媒体接口。</div> <div style="text-indent: 2em;">android.net :提供帮助网络访问的类,超过通常的 java.net.* 接口。</div> <div style="text-indent: 2em;">android.os :提供了系统服务、消息传输和 IPC 机制。</div> <div style="text-indent: 2em;">android.opengl :提供 OpenGL 的工具。</div> <div style="text-indent: 2em;">android.provider :提供访问 Android 内容提供者的类。</div> <div style="text-indent: 2em;">android.telephony :提供与拨打电话相关的 API 交互。</div> <div style="text-indent: 2em;">android.view :提供基础的用户界面接口框架。</div> <div style="text-indent: 2em;">android.util :涉及工具性的方法,例如时间日期的操作。</div> <div style="text-indent: 2em;">android.webkit :默认浏览器操作接口。</div> <div style="text-indent: 2em;">android.widget :包含各种 UI 元素(大部分是可见的)在应用程序的布局中使用</div> <div>~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</div> <div> <div>build/</div> <div>|&#8211; buildspec.mk.default</div> <div>|&#8211; cleanspec.mk</div> <div>|&#8211; core (各种以mk为结尾的文件,它门是编译所需要的Makefile)</div> <div>|&#8211; envsetup.sh</div> <div>|&#8211; libs</div> <div>|&#8211; target (包含board和product两个目录,为目标所需要文件)</div> <div>|&#8211; tools (编译过程中主机所需要的工具,一些需要经过编译生成)</div> <div>其中,core中的Makefile是整个Android编译所需要的真正的<span style="text-indent: 2em;">Makefile,它被顶层目录的Makefile引用。</span></div> <div></div> </div> <div></div> <div>基本介绍到此，文章参考网络中各种文章，如果有侵权啥行为的，请联系删除。</div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197952.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-20 14:16 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/20/197952.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android 启动Launcher </title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/18/197913.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Mon, 18 Feb 2013 09:37:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/18/197913.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197913.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/18/197913.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197913.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197913.html</trackback:ping><description><![CDATA[<div><span style="font-size:14px"><span style="border-collapse: collapse; color: #444444; font-family: 'DejaVu Sans', 'Lucida Grande', Tahoma, 'Hiragino Sans GB', STHeiti, SimSun, sans-serif; line-height: 21px; ">一LauncherApplication-&gt;onCreate<br style="word-wrap: break-word; " />　　1.//设置最小堆内存4M<br style="word-wrap: break-word; " />　　2.//建立应用图标缓存器<br style="word-wrap: break-word; " />　　3.//建立LauncherModel<br style="word-wrap: break-word; " />　　4.//注册Intent.ACTION_PACKAGE_ADDED，Intent.ACTION_PACKAGE_REMOVED，Intent.ACTION_PACKAGE_CHANGED事件监听器<br style="word-wrap: break-word; " />　　LauncherModel作为广播接收器对上面3中事件进行监听<br style="word-wrap: break-word; " />　　5.//添加对桌面favorites content provider 数据变化监听器<br style="word-wrap: break-word; " />　　二Launcher-&gt;onCreate<br style="word-wrap: break-word; " />　　1.获取LauncherApplication LauncherModel mIconCache等LauncherApplication初始化的对象<br style="word-wrap: break-word; " />　　2.新建拖放控制器new DragController（this）<br style="word-wrap: break-word; " />　　4.//获取桌面组件管理器，启动桌面组件host<br style="word-wrap: break-word; " />　　5.//从array.hotseats中加载所有的hotseats（热键 如挂机按钮，<a href="http://dev.10086.cn/cmdn/wiki/index.php?doc-view-1483">google</a>浏览器）<br style="word-wrap: break-word; " />　　6.从launcher.preferences加载本地设置<br style="word-wrap: break-word; " />　　7.//设置壁纸尺寸宽度=display.getWidth（）* WALLPAPER_SCREENS_SPAN，高度=display.getHeight（）<br style="word-wrap: break-word; " />　　8.//加载布局文件<br style="word-wrap: break-word; " />　　9.//初始化所有控件<br style="word-wrap: break-word; " />　　10.//从Bundle savedInstanceState获取桌面持久化数据 设置mRestoring = true；<br style="word-wrap: break-word; " />　　11.如果mRestoring == false，调用LauncherModel加载桌面项 mModel.startLoader（this， true，isLanguageChange）；<br style="word-wrap: break-word; " />　　a.LauncherModel.Loader.startLoader（） 代码同步处理<br style="word-wrap: break-word; " />　　b.新建LauncherModel.Loader.LoaderThread线程并启动线程（桌面项加载，详细见第三步）<br style="word-wrap: break-word; " />　　12.注册Intent.ACTION_CLOSE_SYSTEM_DIALOGS广播监听<br style="word-wrap: break-word; " />　　三 桌面项加载 LauncherModel.Loader.LoaderThread.run：新线程执行<br style="word-wrap: break-word; " />　　1.等待主线程运行结束才开始加载<br style="word-wrap: break-word; " />　　2.判断是否先加载桌面；loadWorkspaceFirst = cbk ！= null ？ （！cbk.isAllAppsVisible（）） ： true；<br style="word-wrap: break-word; " />　　3.loadWorkspaceFirst==true<br style="word-wrap: break-word; " />　　a.loadAndBindWorkspace（）<br style="word-wrap: break-word; " />　　loadWorkspace（）：从数据库launcher.db中查询中所有桌面项构造对应类型的ItemInfo对象存入<br style="word-wrap: break-word; " />　　mItems，mAppWidgets，mFolders列表.<br style="word-wrap: break-word; " />　　bindWorkspace（）：<br style="word-wrap: break-word; " />　　1.laucher.startBinding（），异步调用，在主线程中handle<br style="word-wrap: break-word; " />　　//do no things<br style="word-wrap: break-word; " />　　2.laucher.bindItems（），异步调用，在主线程中handle<br style="word-wrap: break-word; " />　　1.根据ItemInfo对象创建桌面图标view对象<br style="word-wrap: break-word; " />　　2.获取item.screen， item.cellX， item.cellY， spanX， spanY，<br style="word-wrap: break-word; " />　　调用workspace.addInScreen添加到对应桌面的cell<br style="word-wrap: break-word; " />　　1.重新设置桌面图标view 的layoutparam（类型为cellLayout.layoutparam）<br style="word-wrap: break-word; " />　　2.根据item.screen获取桌面的celllayout对象，也就是workspace下5个用户桌面中的一个<br style="word-wrap: break-word; " />　　3.调用celllayout.addview方法把桌面图标view对象添加为celllayout的child，也就是为用户桌面添加一个桌面图标<br style="word-wrap: break-word; " />　　4.桌面图标view对象添加OnLongClickListener=laucher，由laucher负责监听桌面图标view的longclick事件<br style="word-wrap: break-word; " />　　5.如果桌面图标是DropTarget对象，拖放控制器mDragController添加该view到拖放目的地列表<br style="word-wrap: break-word; " />　　3.laucher.bindFolders（），异步调用，在主线程中handle<br style="word-wrap: break-word; " />　　//launcher.mFolders.putAll（mFolders）；<br style="word-wrap: break-word; " />　　4.laucher.bindAppWidget（），异步调用，在主线程中handle<br style="word-wrap: break-word; " />　　1.获取LauncherAppWidgetInfo的appWidgetId<br style="word-wrap: break-word; " />　　2.获取AppWidgetProviderInfo appWidgetInfo mAppWidgetManager.getAppWidgetInfo（appWidgetId）<br style="word-wrap: break-word; " />　　3.根据appWidgetInfo创建桌面组件的view AppWidgetHostView对象<br style="word-wrap: break-word; " />　　4.调用workspace.addInScreen添加到对应桌面的cell<br style="word-wrap: break-word; " />　　5.laucher.finishBindingItems（），异步调用，在主线程中handle<br style="word-wrap: break-word; " />　　mWorkspaceLoading=false<br style="word-wrap: break-word; " />　　b.loadAndBindAllApps（）；<br style="word-wrap: break-word; " />　　如果没有加载apps或者改变了语言设置<br style="word-wrap: break-word; " />　　loadAllAppsByBatch（）；<br style="word-wrap: break-word; " />　　1.//设置package 查询条件Intent.ACTION_MAIN Intent.CATEGORY_LAUNCHER<br style="word-wrap: break-word; " />　　2.//清空mAllAppsList mAllAppsList.clear（）；<br style="word-wrap: break-word; " />　　3.//packageManager 查询所有应用pakages<br style="word-wrap: break-word; " />　　4.分批次mAllAppsList.add 应用pakages<br style="word-wrap: break-word; " />　　5.laucher.bindAllApplications（）//异步调用<br style="word-wrap: break-word; " />　　mAllAppsGrid.setApps（apps）<br style="word-wrap: break-word; " />　　6.若分多个批次加载 laucher.bindAppsAdded（）//异步调用<br style="word-wrap: break-word; " />　　mAllAppsGrid.addApps（apps）；<br style="word-wrap: break-word; " />　　否则<br style="word-wrap: break-word; " />　　onlyBindAllApps（）；<br style="word-wrap: break-word; " />　　1.mAllAppsList.data.clone（）；<br style="word-wrap: break-word; " />　　2.laucher.bindAllApplications（）//异步调用<br style="word-wrap: break-word; " />　　mAllAppsGrid.setApps（apps）<br style="word-wrap: break-word; " />　　4.loadWorkspaceFirst==false<br style="word-wrap: break-word; " />　　a.loadAndBindAllApps（）；<br style="word-wrap: break-word; " />　　b.loadAndBindWorkspace（）；<br /><br /></span></span></div><div>http://www.cnblogs.com/playing/archive/2011/04/22/2024980.html</div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197913.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-18 17:37 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/18/197913.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android各种访问权限Permission详解</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/18/197911.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Mon, 18 Feb 2013 07:58:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/18/197911.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197911.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/18/197911.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197911.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197911.html</trackback:ping><description><![CDATA[<div><p>在Android的设计中，资源的访问或者网络连接，要得到这些服务都需要声明其访问权限，否则将无法正常工作。在Android中这样的权限有很多种，这里将各类访问权限一一罗列出来，供大家使用时参考之用。</p> <p>&nbsp;</p> <p>&nbsp;</p> <p>android.permission.EXPAND_STATUS_BAR <br /> 允许一个程序扩展收缩在状态栏,android开发网提示应该是一个类似Windows Mobile中的托盘程序</p> <p>android.permission.FACTORY_TEST <br /> 作为一个工厂测试程序，运行在root用户</p> <p>android.permission.FLASHLIGHT <br /> 访问闪光灯,android开发网提示HTC Dream不包含闪光灯</p> <p>android.permission.FORCE_BACK <br /> 允许程序强行一个后退操作是否在顶层activities</p> <p>android.permission.FOTA_UPDATE <br /> 暂时不了解这是做什么使用的，android开发网分析可能是一个预留权限.</p> <p>android.permission.GET_ACCOUNTS <br /> 访问一个帐户列表在Accounts Service中</p> <p>android.permission.GET_PACKAGE_SIZE <br /> 允许一个程序获取任何package占用空间容量</p> <p>android.permission.GET_TASKS <br /> 允许一个程序获取信息有关当前或最近运行的任务，一个缩略的任务状态，是否活动等等</p> <p>android.permission.HARDWARE_TEST <br /> 允许访问硬件</p> <p>android.permission.INJECT_EVENTS <br /> 允许一个程序截获用户事件如按键、触摸、轨迹球等等到一个时间流，android 开发网提醒算是hook技术吧</p> <p>android.permission.INSTALL_PACKAGES <br /> 允许一个程序安装packages</p> <p>android.permission.INTERNAL_SYSTEM_WINDOW <br /> 允许打开窗口使用系统用户界面</p> <p>android.permission.ACCESS_CHECKIN_PROPERTIES <br /> 允许读写访问&#8220;properties&#8221;表在checkin数据库中，改值可以修改上传。</p> <p>android.permission.ACCESS_COARSE_LOCATION <br /> 允许一个程序访问CellID或WiFi热点来获取粗略的位置</p> <p>android.permission.ACCESS_FINE_LOCATION <br /> 允许一个程序访问精良位置(如GPS)</p> <p>android.permission.WRITE_CONTACTS <br /> 允许程序写入但不读取用户联系人数据</p> <p>android.permission.WRITE_GSERVICES <br /> 允许程序修改Google服务地图</p> <p>android.permission.WRITE_OWNER_DATA <br /> 允许一个程序写入但不读取所有者数据</p> <p>android.permission.WRITE_SETTINGS <br /> 允许程序读取或写入系统设置</p> <p>android.permission.WRITE_SMS <br /> 允许程序写短信</p> <p>android.permission.WRITE_SYNC_SETTINGS <br /> 允许程序写入同步设置</p> <p>android.permission.ACCESS_LOCATION_EXTRA_COMMANDS <br /> 允许应用程序访问额外的位置提供命令</p> <p>android.permission.ACCESS_MOCK_LOCATION <br /> 允许程序创建模拟位置提供用于测试</p> <p>android.permission.ACCESS_NETWORK_STATE <br /> 允许程序访问有关GSM网络信息</p> <p>android.permission.ACCESS_SURFACE_FLINGER <br /> 允许程序使用SurfaceFlinger底层特性</p> <p>android.permission.ACCESS_WIFI_STATE <br /> 允许程序访问Wi-Fi网络状态信息</p> <p>android.permission.ADD_SYSTEM_SERVICE <br /> 允许程序发布系统级服务</p> <p>android.permission.BATTERY_STATS <br /> 允许程序更新手机电池统计信息</p> <p>android.permission.BLUETOOTH <br /> 允许程序连接到已配对的蓝牙设备</p> <p>android.permission.BLUETOOTH_ADMIN <br /> 允许程序发现和配对蓝牙设备</p> <p>android.permission.BROADCAST_PACKAGE_REMOVED <br /> 允许程序广播一个提示消息在一个应用程序包已经移除后</p> <p>android.permission.BROADCAST_STICKY <br /> 允许一个程序广播常用intents</p> <p>android.permission.CALL_PHONE <br /> 允许一个程序初始化一个电话拨号不需通过拨号用户界面需要用户确认</p> <p>android.permission.DELETE_CACHE_FILES <br /> 允许程序删除缓存文件</p> <p>android.permission.DELETE_PACKAGES <br /> 允许一个程序删除包</p> <p>android.permission.DEVICE_POWER <br /> 允许访问底层电源管理</p> <p>android.permission.DIAGNOSTIC <br /> 允许程序RW诊断资源</p> <p>android.permission.DISABLE_KEYGUARD <br /> 允许程序禁用键盘锁</p> <p>android.permission.DUMP <br /> 允许程序返回状态抓取信息从系统服务</p> <p>android.permission.CALL_PRIVILEGED <br /> 允许一个程序拨打任何号码，包含紧急号码无需通过拨号用户界面需要用户确认</p> <p>android.permission.CAMERA <br /> 请求访问使用照相设备</p> <p>android.permission.CHANGE_COMPONENT_ENABLED_STATE <br /> 允许一个程序是否改变一个组件或其他的启用或禁用</p> <p>android.permission.CHANGE_CONFIGURATION <br /> 允许一个程序修改当前设置，如本地化</p> <p>android.permission.CHANGE_NETWORK_STATE <br /> 允许程序改变网络连接状态</p> <p>android.permission.CHANGE_WIFI_STATE <br /> 允许程序改变Wi-Fi连接状态</p> <p>android.permission.CLEAR_APP_CACHE <br /> 允许一个程序清楚缓存从所有安装的程序在设备中</p> <p>android.permission.CLEAR_APP_USER_DATA <br /> 允许一个程序清除用户设置</p> <p>android.permission.CONTROL_LOCATION_UPDATES <br /> 允许启用禁止位置更新提示从无线模块</p> <p>android.permission.REBOOT <br /> 请求能够重新启动设备</p> <p>android.permission.RECEIVE_BOOT_COMPLETED <br /> 允许一个程序接收到 ACTION_BOOT_COMPLETED广播在系统完成启动</p> <p>android.permission.RECEIVE_MMS <br /> 允许一个程序监控将收到MMS彩信,记录或处理</p> <p>android.permission.RECEIVE_SMS <br /> 允许程序监控一个将收到短信息，记录或处理</p> <p>android.permission.RECEIVE_WAP_PUSH <br /> 允许程序监控将收到WAP PUSH信息</p> <p>android.permission.RECORD_AUDIO <br /> 允许程序录制音频</p> <p>android.permission.REORDER_TASKS <br /> 允许程序改变Z轴排列任务</p> <p>android.permission.RESTART_PACKAGES <br /> 允许程序重新启动其他程序</p> <p>android.permission.SEND_SMS <br /> 允许程序发送SMS短信</p> <p>android.permission.INTERNET <br /> 允许程序打开网络套接字</p> <p>android.permission.MANAGE_APP_TOKENS <br /> 允许程序管理(创建、催后、 z- order默认向z轴推移)程序引用在窗口管理器中</p> <p>android.permission.MASTER_CLEAR目前还没有明确的解释，android开发网分析可能是清除一切数据，类似硬格机</p> <p>android.permission.MODIFY_AUDIO_SETTINGS <br /> 允许程序修改全局音频设置</p> <p>android.permission.MODIFY_PHONE_STATE <br /> 允许修改话机状态，如电源，人机接口等</p> <p>android.permission.MOUNT_UNMOUNT_FILESYSTEMS <br /> 允许挂载和反挂载文件系统可移动存储</p> <p>android.permission.PERSISTENT_ACTIVITY <br /> 允许一个程序设置他的activities显示</p> <p>android.permission.PROCESS_OUTGOING_CALLS <br /> 允许程序监视、修改有关播出电话</p> <p>android.permission.READ_CALENDAR <br /> 允许程序读取用户日历数据</p> <p>android.permission.READ_CONTACTS <br /> 允许程序读取用户联系人数据</p> <p>android.permission.READ_FRAME_BUFFER <br /> 允许程序屏幕波或和更多常规的访问帧缓冲数据</p> <p>android.permission.READ_INPUT_STATE <br /> 允许程序返回当前按键状态</p> <p>android.permission.READ_LOGS <br /> 允许程序读取底层系统日志文件</p> <p>android.permission.READ_OWNER_DATA <br /> 允许程序读取所有者数据</p> <p>android.permission.READ_SMS <br /> 允许程序读取短信息</p> <p>android.permission.READ_SYNC_SETTINGS <br /> 允许程序读取同步设置</p> <p>android.permission.READ_SYNC_STATS <br /> 允许程序读取同步状态</p> <p>android.permission.SET_ACTIVITY_WATCHER <br /> 允许程序监控或控制activities已经启动全局系统中</p> <p>android.permission.SET_ALWAYS_FINISH <br /> 允许程序控制是否活动间接完成在处于后台时</p> <p>android.permission.SET_ANIMATION_SCALE <br /> 修改全局信息比例</p> <p>android.permission.SET_DEBUG_APP <br /> 配置一个程序用于调试</p> <p>android.permission.SET_ORIENTATION <br /> 允许底层访问设置屏幕方向和实际旋转</p> <p>android.permission.SET_PREFERRED_APPLICATIONS <br /> 允许一个程序修改列表参数PackageManager.addPackageToPreferred() 和PackageManager.removePackageFromPreferred()方法</p> <p>android.permission.SET_PROCESS_FOREGROUND <br /> 允许程序当前运行程序强行到前台</p> <p>android.permission.SET_PROCESS_LIMIT <br /> 允许设置最大的运行进程数量</p> <p>android.permission.SET_TIME_ZONE <br /> 允许程序设置时间区域</p> <p>android.permission.SET_WALLPAPER <br /> 允许程序设置壁纸</p> <p>android.permission.SET_WALLPAPER_HINTS <br /> 允许程序设置壁纸hits</p> <p>android.permission.SIGNAL_PERSISTENT_PROCESSES <br /> 允许程序请求发送信号到所有显示的进程中</p> <p>android.permission.STATUS_BAR <br /> 允许程序打开、关闭或禁用状态栏及图标Allows an application to open, close, or disable the status bar and its icons.</p> <p>android.permission.SUBSCRIBED_FEEDS_READ <br /> 允许一个程序访问订阅RSS Feed内容提供</p> <p>android.permission.SUBSCRIBED_FEEDS_WRITE <br /> 系统暂时保留改设置,android开发网认为未来版本会加入该功能。</p> <p>android.permission.SYSTEM_ALERT_WINDOW <br /> 允许一个程序打开窗口使用 TYPE_SYSTEM_ALERT，显示在其他所有程序的顶层</p> <p>android.permission.VIBRATE <br /> 允许访问振动设备</p> <p>android.permission.WAKE_LOCK <br /> 允许使用PowerManager的 WakeLocks保持进程在休眠时从屏幕消失</p> <p>android.permission.WRITE_APN_SETTINGS <br /> 允许程序写入API设置</p> <p>android.permission.WRITE_CALENDAR <br /> 允许一个程序写入但不读取用户日历数据</p> <p>可以看出Android中对资源以及服务的访问都非常严格，另外，在程序打包成APK的时候也需要对软件进行签名。</p><p><br /></p><p><div><table border="0" cellpadding="5" cellspacing="1" width="100%"><tbody><tr bgcolor="#ffffff"><td bgcolor="#d8d8d8" valign="top" width="152">访问登记属性</td> <td bgcolor="#d8d8d8" valign="top" width="616">android.permission.ACCESS_CHECKIN_PROPERTIES ，读取或写入登记check-in数据库属性表的权限</td> </tr> <tr bgcolor="#ffffff"> <td valign="top" width="152">获取错略位置</td> <td valign="top">android.permission.ACCESS_COARSE_LOCATION，通过WiFi或移动基站的方式获取用户错略的经纬度信息，定位精度大概误差在30~1500米</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top" width="152">获取精确位置</td> <td bgcolor="#d8d8d8" valign="top">android.permission.ACCESS_FINE_LOCATION，通过GPS芯片接收卫星的定位信息，定位精度达10米以内</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">访问定位额外命令</td> <td valign="top">android.permission.ACCESS_LOCATION_EXTRA_COMMANDS，允许程序访问额外的定位提供者指令</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top" width="152">获取模拟定位信息</td> <td bgcolor="#d8d8d8" valign="top">android.permission.ACCESS_MOCK_LOCATION，获取模拟定位信息，一般用于帮助开发者调试应用</td> </tr> <tr bgcolor="#ffffff"> <td valign="top" width="152">获取网络状态</td> <td valign="top">android.permission.ACCESS_NETWORK_STATE，获取网络信息状态，如当前的网络连接是否有效</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top" width="152">访问Surface Flinger</td> <td bgcolor="#d8d8d8" valign="top">android.permission.ACCESS_SURFACE_FLINGER，Android平台上底层的图形显示支持，一般用于游戏或照相机预览界面和底层模式的屏幕截图</td> </tr> <tr bgcolor="#ffffff"> <td valign="top" width="152">获取WiFi状态</td> <td valign="top">android.permission.ACCESS_WIFI_STATE，获取当前WiFi接入的状态以及WLAN热点的信息</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">账户管理</td> <td bgcolor="#d8d8d8" valign="top">android.permission.ACCOUNT_MANAGER，获取账户验证信息，主要为GMail账户信息，只有系统级进程才能访问的权限</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">验证账户</td> <td valign="top">android.permission.AUTHENTICATE_ACCOUNTS，允许一个程序通过账户验证方式访问账户管理ACCOUNT_MANAGER相关信息</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top" width="152">电量统计</td> <td bgcolor="#d8d8d8" valign="top">android.permission.BATTERY_STATS，获取电池电量统计信息</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">绑定小插件</td> <td valign="top">android.permission.BIND_APPWIDGET，允许一个程序告诉appWidget服务需要访问小插件的数据库，只有非常少的应用才用到此权限</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">绑定设备管理</td> <td bgcolor="#d8d8d8" valign="top">android.permission.BIND_DEVICE_ADMIN，请求系统管理员接收者receiver，只有系统才能使用</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">绑定输入法</td> <td valign="top">android.permission.BIND_INPUT_METHOD ，请求InputMethodService服务，只有系统才能使用</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">绑定RemoteView</td> <td bgcolor="#d8d8d8" valign="top">android.permission.BIND_REMOTEVIEWS，必须通过RemoteViewsService服务来请求，只有系统才能用</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">绑定壁纸</td> <td valign="top">android.permission.BIND_WALLPAPER，必须通过WallpaperService服务来请求，只有系统才能用</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">使用蓝牙</td> <td bgcolor="#d8d8d8" valign="top">android.permission.BLUETOOTH，允许程序连接配对过的蓝牙设备</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">蓝牙管理</td> <td valign="top">android.permission.BLUETOOTH_ADMIN，允许程序进行发现和配对新的蓝牙设备</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">变成砖头</td> <td bgcolor="#d8d8d8" valign="top">android.permission.BRICK，能够禁用手机，非常危险，顾名思义就是让手机变成砖头</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">应用删除时广播</td> <td valign="top">android.permission.BROADCAST_PACKAGE_REMOVED，当一个应用在删除时触发一个广播</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">收到短信时广播</td> <td bgcolor="#d8d8d8" valign="top">android.permission.BROADCAST_SMS，当收到短信时触发一个广播</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">连续广播</td> <td valign="top">android.permission.BROADCAST_STICKY，允许一个程序收到广播后快速收到下一个广播</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">WAP PUSH广播</td> <td bgcolor="#d8d8d8" valign="top">android.permission.BROADCAST_WAP_PUSH，WAP PUSH服务收到后触发一个广播</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">拨打电话</td> <td valign="top">android.permission.CALL_PHONE，允许程序从非系统拨号器里输入电话号码</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">通话权限</td> <td bgcolor="#d8d8d8" valign="top">android.permission.CALL_PRIVILEGED，允许程序拨打电话，替换系统的拨号器界面</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">拍照权限</td> <td valign="top">android.permission.CAMERA，允许访问摄像头进行拍照</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">改变组件状态</td> <td bgcolor="#d8d8d8" valign="top">android.permission.CHANGE_COMPONENT_ENABLED_STATE，改变组件是否启用状态</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">改变配置</td> <td valign="top">android.permission.CHANGE_CONFIGURATION，允许当前应用改变配置，如定位</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">改变网络状态</td> <td bgcolor="#d8d8d8" valign="top">android.permission.CHANGE_NETWORK_STATE，改变网络状态如是否能联网</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">改变WiFi多播状态</td> <td valign="top">android.permission.CHANGE_WIFI_MULTICAST_STATE，改变WiFi多播状态</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">改变WiFi状态</td> <td bgcolor="#d8d8d8" valign="top">android.permission.CHANGE_WIFI_STATE，改变WiFi状态</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">清除应用缓存</td> <td valign="top">android.permission.CLEAR_APP_CACHE，清除应用缓存</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">清除用户数据</td> <td bgcolor="#d8d8d8" valign="top">android.permission.CLEAR_APP_USER_DATA，清除应用的用户数据</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">底层访问权限</td> <td valign="top">android.permission.CWJ_GROUP，允许CWJ账户组访问底层信息</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">手机优化大师扩展权限</td> <td bgcolor="#d8d8d8" valign="top">android.permission.CELL_PHONE_MASTER_EX，手机优化大师扩展权限</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">控制定位更新</td> <td valign="top">android.permission.CONTROL_LOCATION_UPDATES，允许获得移动网络定位信息改变</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">删除缓存文件</td> <td bgcolor="#d8d8d8" valign="top">android.permission.DELETE_CACHE_FILES，允许应用删除缓存文件</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">删除应用</td> <td valign="top">android.permission.DELETE_PACKAGES，允许程序删除应用</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">电源管理</td> <td bgcolor="#d8d8d8" valign="top">android.permission.DEVICE_POWER，允许访问底层电源管理</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">应用诊断</td> <td valign="top">android.permission.DIAGNOSTIC，允许程序到RW到诊断资源</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">禁用键盘锁</td> <td bgcolor="#d8d8d8" valign="top">android.permission.DISABLE_KEYGUARD，允许程序禁用键盘锁</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">转存系统信息</td> <td valign="top">android.permission.DUMP，允许程序获取系统dump信息从系统服务</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">状态栏控制</td> <td bgcolor="#d8d8d8" valign="top">android.permission.EXPAND_STATUS_BAR，允许程序扩展或收缩状态栏</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">工厂测试模式</td> <td valign="top">android.permission.FACTORY_TEST，允许程序运行工厂测试模式</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">使用闪光灯</td> <td bgcolor="#d8d8d8" valign="top">android.permission.FLASHLIGHT，允许访问闪光灯</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">强制后退</td> <td valign="top">android.permission.FORCE_BACK，允许程序强制使用back后退按键，无论Activity是否在顶层</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">访问账户Gmail列表</td> <td bgcolor="#d8d8d8" valign="top">android.permission.GET_ACCOUNTS，访问GMail账户列表</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">获取应用大小</td> <td valign="top">android.permission.GET_PACKAGE_SIZE，获取应用的文件大小</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">获取任务信息</td> <td bgcolor="#d8d8d8" valign="top">android.permission.GET_TASKS，允许程序获取当前或最近运行的应用</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">允许全局搜索</td> <td valign="top">android.permission.GLOBAL_SEARCH，允许程序使用全局搜索功能</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">硬件测试</td> <td bgcolor="#d8d8d8" valign="top">android.permission.HARDWARE_TEST，访问硬件辅助设备，用于硬件测试</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">注射事件</td> <td valign="top">android.permission.INJECT_EVENTS，允许访问本程序的底层事件，获取按键、轨迹球的事件流</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">安装定位提供</td> <td bgcolor="#d8d8d8" valign="top">android.permission.INSTALL_LOCATION_PROVIDER，安装定位提供</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">安装应用程序</td> <td valign="top">android.permission.INSTALL_PACKAGES，允许程序安装应用</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">内部系统窗口</td> <td bgcolor="#d8d8d8" valign="top">android.permission.INTERNAL_SYSTEM_WINDOW，允许程序打开内部窗口，不对第三方应用程序开放此权限</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">访问网络</td> <td valign="top">android.permission.INTERNET，访问网络连接，可能产生GPRS流量</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">结束后台进程</td> <td bgcolor="#d8d8d8" valign="top">android.permission.KILL_BACKGROUND_PROCESSES，允许程序调用killBackgroundProcesses(String).方法结束后台进程</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">管理账户</td> <td valign="top">android.permission.MANAGE_ACCOUNTS，允许程序管理AccountManager中的账户列表</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">管理程序引用</td> <td bgcolor="#d8d8d8" valign="top">android.permission.MANAGE_APP_TOKENS，管理创建、摧毁、Z轴顺序，仅用于系统</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">高级权限</td> <td valign="top">android.permission.MTWEAK_USER，允许mTweak用户访问高级系统权限</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">社区权限</td> <td bgcolor="#d8d8d8" valign="top">android.permission.MTWEAK_FORUM，允许使用mTweak社区权限</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">软格式化</td> <td valign="top">android.permission.MASTER_CLEAR，允许程序执行软格式化，删除系统配置信息</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">修改声音设置</td> <td bgcolor="#d8d8d8" valign="top">android.permission.MODIFY_AUDIO_SETTINGS，修改声音设置信息</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">修改电话状态</td> <td valign="top">android.permission.MODIFY_PHONE_STATE，修改电话状态，如飞行模式，但不包含替换系统拨号器界面</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">格式化文件系统</td> <td bgcolor="#d8d8d8" valign="top">android.permission.MOUNT_FORMAT_FILESYSTEMS，格式化可移动文件系统，比如格式化清空SD卡</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">挂载文件系统</td> <td valign="top">android.permission.MOUNT_UNMOUNT_FILESYSTEMS，挂载、反挂载外部文件系统</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">允许NFC通讯</td> <td bgcolor="#d8d8d8" valign="top">android.permission.NFC，允许程序执行NFC近距离通讯操作，用于移动支持</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">永久Activity</td> <td valign="top">android.permission.PERSISTENT_ACTIVITY，创建一个永久的Activity，该功能标记为将来将被移除</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">处理拨出电话</td> <td bgcolor="#d8d8d8" valign="top">android.permission.PROCESS_OUTGOING_CALLS，允许程序监视，修改或放弃播出电话</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">读取日程提醒</td> <td valign="top">android.permission.READ_CALENDAR，允许程序读取用户的日程信息</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">读取联系人</td> <td bgcolor="#d8d8d8" valign="top">android.permission.READ_CONTACTS，允许应用访问联系人通讯录信息</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">屏幕截图</td> <td valign="top">android.permission.READ_FRAME_BUFFER，读取帧缓存用于屏幕截图</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">读取收藏夹和历史记录</td> <td bgcolor="#d8d8d8" valign="top">com.android.browser.permission.READ_HISTORY_BOOKMARKS，读取浏览器收藏夹和历史记录</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">读取输入状态</td> <td valign="top">android.permission.READ_INPUT_STATE，读取当前键的输入状态，仅用于系统</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">读取系统日志</td> <td bgcolor="#d8d8d8" valign="top">android.permission.READ_LOGS，读取系统底层日志</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">读取电话状态</td> <td valign="top">android.permission.READ_PHONE_STATE，访问电话状态</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">读取短信内容</td> <td bgcolor="#d8d8d8" valign="top">android.permission.READ_SMS，读取短信内容</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">读取同步设置</td> <td valign="top">android.permission.READ_SYNC_SETTINGS，读取同步设置，读取Google在线同步设置</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">读取同步状态</td> <td bgcolor="#d8d8d8" valign="top">android.permission.READ_SYNC_STATS，读取同步状态，获得Google在线同步状态</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">重启设备</td> <td valign="top">android.permission.REBOOT，允许程序重新启动设备</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">开机自动允许</td> <td bgcolor="#d8d8d8" valign="top">android.permission.RECEIVE_BOOT_COMPLETED，允许程序开机自动运行</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">接收彩信</td> <td valign="top">android.permission.RECEIVE_MMS，接收彩信</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">接收短信</td> <td bgcolor="#d8d8d8" valign="top">android.permission.RECEIVE_SMS，接收短信</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">接收Wap Push</td> <td valign="top">android.permission.RECEIVE_WAP_PUSH，接收WAP PUSH信息</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">录音</td> <td bgcolor="#d8d8d8" valign="top">android.permission.RECORD_AUDIO，录制声音通过手机或耳机的麦克</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">排序系统任务</td> <td valign="top">android.permission.REORDER_TASKS，重新排序系统Z轴运行中的任务</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">结束系统任务</td> <td bgcolor="#d8d8d8" valign="top">android.permission.RESTART_PACKAGES，结束任务通过restartPackage(String)方法，该方式将在外来放弃</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">发送短信</td> <td valign="top">android.permission.SEND_SMS，发送短信</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">设置Activity观察其</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SET_ACTIVITY_WATCHER，设置Activity观察器一般用于monkey测试</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">设置闹铃提醒</td> <td valign="top">com.android.alarm.permission.SET_ALARM，设置闹铃提醒</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">设置总是退出</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SET_ALWAYS_FINISH，设置程序在后台是否总是退出</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">设置动画缩放</td> <td valign="top">android.permission.SET_ANIMATION_SCALE，设置全局动画缩放</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">设置调试程序</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SET_DEBUG_APP，设置调试程序，一般用于开发</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">设置屏幕方向</td> <td valign="top">android.permission.SET_ORIENTATION，设置屏幕方向为横屏或标准方式显示，不用于普通应用</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">设置应用参数</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SET_PREFERRED_APPLICATIONS，设置应用的参数，已不再工作具体查看addPackageToPreferred(String) 介绍</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">设置进程限制</td> <td valign="top">android.permission.SET_PROCESS_LIMIT，允许程序设置最大的进程数量的限制</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">设置系统时间</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SET_TIME，设置系统时间</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">设置系统时区</td> <td valign="top">android.permission.SET_TIME_ZONE，设置系统时区</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">设置桌面壁纸</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SET_WALLPAPER，设置桌面壁纸</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">设置壁纸建议</td> <td valign="top">android.permission.SET_WALLPAPER_HINTS，设置壁纸建议</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">发送永久进程信号</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SIGNAL_PERSISTENT_PROCESSES，发送一个永久的进程信号</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">状态栏控制</td> <td valign="top">android.permission.STATUS_BAR，允许程序打开、关闭、禁用状态栏</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">访问订阅内容</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SUBSCRIBED_FEEDS_READ，访问订阅信息的数据库</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">写入订阅内容</td> <td valign="top">android.permission.SUBSCRIBED_FEEDS_WRITE，写入或修改订阅内容的数据库</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">显示系统窗口</td> <td bgcolor="#d8d8d8" valign="top">android.permission.SYSTEM_ALERT_WINDOW，显示系统窗口</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">更新设备状态</td> <td valign="top">android.permission.UPDATE_DEVICE_STATS，更新设备状态</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">使用证书</td> <td bgcolor="#d8d8d8" valign="top">android.permission.USE_CREDENTIALS，允许程序请求验证从AccountManager</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">使用SIP视频</td> <td valign="top">android.permission.USE_SIP，允许程序使用SIP视频服务</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">使用振动</td> <td bgcolor="#d8d8d8" valign="top">android.permission.VIBRATE，允许振动</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">唤醒锁定</td> <td valign="top">android.permission.WAKE_LOCK，允许程序在手机屏幕关闭后后台进程仍然运行</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">写入GPRS接入点设置</td> <td bgcolor="#d8d8d8" valign="top">android.permission.WRITE_APN_SETTINGS，写入网络GPRS接入点设置</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">写入日程提醒</td> <td valign="top">android.permission.WRITE_CALENDAR，写入日程，但不可读取</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">写入联系人</td> <td bgcolor="#d8d8d8" valign="top">android.permission.WRITE_CONTACTS，写入联系人，但不可读取</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">写入外部存储</td> <td valign="top">android.permission.WRITE_EXTERNAL_STORAGE，允许程序写入外部存储，如SD卡上写文件</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">写入Google地图数据</td> <td bgcolor="#d8d8d8" valign="top">android.permission.WRITE_GSERVICES，允许程序写入Google Map服务数据</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">写入收藏夹和历史记录</td> <td valign="top">com.android.browser.permission.WRITE_HISTORY_BOOKMARKS，写入浏览器历史记录或收藏夹，但不可读取</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">读写系统敏感设置</td> <td bgcolor="#d8d8d8" valign="top">android.permission.WRITE_SECURE_SETTINGS，允许程序读写系统安全敏感的设置项</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">读写系统设置</td> <td valign="top">android.permission.WRITE_SETTINGS，允许读写系统设置项</td> </tr> <tr bgcolor="#ffffff"> <td bgcolor="#d8d8d8" valign="top">编写短信</td> <td bgcolor="#d8d8d8" valign="top">android.permission.WRITE_SMS，允许编写短信</td> </tr> <tr bgcolor="#ffffff"> <td valign="top">写入在线同步设置</td> <td valign="top">android.permission.WRITE_SYNC_SETTINGS，写入Google在线同步设置</td></tr></tbody></table></div><br /></p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197911.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-18 15:58 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/18/197911.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【APK教程】合并odex与apk至完整apk</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197883.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sun, 17 Feb 2013 06:57:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197883.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197883.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197883.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197883.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197883.html</trackback:ping><description><![CDATA[<div><strong>Android的 ROM中有很多odex文件，相对于APK中的dex文件而言这个odex有什么作用呢?  如果你仔细观察会发现文件名时一一对应的，同时那些对应的apk文件中没有dex文件。这样做可以使其厂商保证一定的反盗版，因为没有没有dex文件的  apk是无法正常安装的，而厂商直接将odex和不完整的apk文件放到手机rom固化到/system/bin中可以让一般用户无法正常导出使用<br /> <br /> 可能想到的是合并odex和apk变成apk中包含dex文件的，这样合并后最终apk文件安装在/data/中，而rom存放在 /system/app中，所以最终导致了用户可装在Android手机中的软件会变少，占用系统空间。<br /> &nbsp;&nbsp;1. 下载 </strong><a href="http://smali.googlecode.com/files/smali-1.2.2.jar" target="_blank"><strong>http://smali.googlecode.com/files/smali-1.2.2.jar</strong></a><strong>&nbsp;&nbsp;和 </strong><a href="http://smali.googlecode.com/files/baksmali-1.2.2.jar" target="_blank"><strong>http://smali.googlecode.com/files/baksmali-1.2.2.jar</strong></a><strong> ，既然是需要盗版，还需要odex所在rom中的一些引用类，一般在 /system/framework 目录中<br /> <br /> &nbsp;&nbsp;2 .&nbsp;&nbsp;通过odex生成class文件<br /> <br /> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; java -jar baksmali-1.2.2.jar -x android123.odex<br /> <br /> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;执行完上面这行命令后，会生成一个out 文件夹里面是android123.odex的class文件。出现问题，根据提示可以从rom的 /system/framework 中的**.jar放到pc上的java环境变量中一起生成。<br /> <br /> &nbsp;&nbsp;3. 通过class生成classes.dex 文件。<br /> <br /> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;java -Xmx512M -jar smali-1.2.2.jar out -o classes.dex<br /> <br /> &nbsp;&nbsp;4. 将classes.dex放到apk文件<br /> <br /> &nbsp; &nbsp;&nbsp; &nbsp;&nbsp;&nbsp;因为apk是zip的mime编码类型，使用winzip或winrar直接拖入到apk改名为zip的压缩包中即可。<br /> <br /> &nbsp;&nbsp;5. 不要忘记了签名，使用jdk中的arsigner和keytool打包重新签名即可。 <br /> 有时候发现别人手机里有一款 apk 挺好，想弄出来装自己手机上，可是却发现那个 apk 是残缺的，里面没有 classes.dex  文件，却有个跟 apk 同名的 odex 文件。残缺的 apk 是装不了的，只能把这个 apk 跟 odex 合并成一个完整的 apk  才能安装。 需要的工具： <br /> 1 ． smali-1.2.2.jar 和 baksmali-1.2.2.jar <br /> 2 ． 还需要这个 apk 所在的 rom 里面的一些 jar 文件，都在 /system/framework 里面： core.jar,  ext. jar, framework. jar, android.policy. jar, services. Jar 。 <br /> 当然，这五个是最基本的，有可能还不够，这种情况下面会讲到。 <br /> <br /> <br /> 总共分四步： <br /> 1 ． 把下载好的 smali-1.2.2.jar 和 baksmali-1.2.2.jar ，还有 rom 里面抠出来的 5 个 jar ，放到工作目录，然后 apk 和 odex 也放到一起。 <br /> 2 ． 分解 odex 文件为 class 文件。命令： java -jar baksmali-1.2.2.jar -x 处是你要分解的  odex 文件的名字，命令完成之后，会生成一个 out 文件夹，里面就是所有的 class  文件。如果出现问题，比如什么异常，缺少包什么的，就更到 rom 里面把出错信息里面要求的包拿出来，放到当前目录下。 <br /> 3． 将 class 生成为 classes.dex 文件。命令： java -Xmx512M -jar smali-1.2.2.jar out -o classes.dex 这一步应该不会有什么问题，然后会生成 classes.dex 文件。 <br /> 4． 把 classes.dex 放入 apk 里面，把盖子盖上。最后这一步最简单了，用解压缩软件打开 apk ，然后把千辛万苦生成的  classes.dex 塞进去，就 ok 了。这个 apk 就能用了。如果想给他重新签个名的话，去找个 Auto Sign  签名工具签署一下就行。 </strong></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197883.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-17 14:57 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197883.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android Rom修改制作工具软件集合</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197882.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sun, 17 Feb 2013 06:56:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197882.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197882.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197882.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197882.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197882.html</trackback:ping><description><![CDATA[<div><p><strong>1.SIN2IMG</strong>&nbsp;&nbsp; &nbsp;</p> <p>　　用于固件ftf中system.sin的解包&nbsp;&nbsp;&nbsp;</p> <p>　　下载地址: SIN2IMG.rar &nbsp;</p> <p>　　使用方法:将固件ftf文件用rar打开，解压出system.sin文件，将该文件于SIN2IMG.exe放在同一个文件夹里面，比如说 X:\下，进入CMD，用cd命令进入X:\目录，输入SIN2IMG.exe system.sin  system.img稍等一会，system.img就解包出来了。</p> <p><strong>2.unyaffs&nbsp;&nbsp;&nbsp;</strong> &nbsp;</p> <p>　　用于system.img文件的解包&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址:&nbsp; Unyaffs.rar &nbsp;</p> <p>　　使用方法:将上一步解包出来的system.img文件与下载好的unayffs.exe文件放在同一个文件夹里面，比如说X:\下，进入 CMD，用cd命令进入X:\目录，输入unyaffs.exe  system.img稍等一会，system.img中的内容即可解包出来，包含有rom的全部程序和其他内容。</p> <p><strong>3.Cygwin&nbsp;&nbsp;</strong></p> <p>　　Htc厨房，适用于win环境下自制rom(非linux下使用的版本)，包括预root、创建刷机脚本、App2SD、开机脚本设定等以及rom打包签名。&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址:http://u.115.com/file/bhzeovtf ( 已修复不能解压问题 )&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　使用方法:解压下载好的rar文件，比如解压到X:\目录下。进入X:\Cygwin目录，找到Cygwin.bat文件，右键选择编辑,看到 这一行:chdir d:\cygwin\bin，将其改为chdir  X:\cygwin\bin，然后进入X:\Cygwin\home，将user目录改名为你当前操作系统用户的名字（即登录windows时候显示的用 户名），然后返回上级目录双击Cygwin.bat即可打开厨房</p> <p><strong>4.Rom-Sign&nbsp;&nbsp;&nbsp;</strong> &nbsp;</p> <p>　　rom签名工具&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址: Rom-Sign.rar &nbsp;</p> <p>　　使用方法:解压到X:\目录下，将需要签名的rom包(zip包)改名为update.zip，然后双击Sign.bat，生成的update_sign.zip就是签名好的rom。</p> <p>　　5.APKtool&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　反编译和回编译以及签名apk工具(如何修改框架、布局、资源文件请自行学习)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p> <p>　　下载地址: 1) Apktool_v1.rar这版画面比较亲和适合小白使用&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;</p> <p>　　2) APKtoolv132.rar 这版比较给力，使用说明程序已经很直白了，就不多说了</p> <p><strong>6.Xtemp&nbsp;&nbsp;&nbsp;</strong> &nbsp;</p> <p>　　dex解包和打包工具&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址: Xtemp.rar &nbsp;</p> <p>　　使用方法:将需要解包的.dex文件放置于Xtemp目录下，将.dex文件拖动至dex.bat文件，即可出现批处理窗口，然后选择1解包即 可。解压后是一个完整的文件夹，打包的时候将文件夹拖动至dex.bat文件，即可出现批处理窗口，选择2打包即可完成打包，之后生成打包好的.dex文 件</p> <p><strong>7.APK manager&nbsp;&nbsp;&nbsp;</strong> &nbsp;</p> <p>　　批量处理APK工具&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址: Apk Manager.rar &nbsp;</p> <p>　　使用方法:程序本身已经写的很清楚了，不再过多解释</p> <p><strong>8.draw9patch&nbsp;&nbsp;&nbsp;</strong> &nbsp;</p> <p>　　用于索引png文件修改和打包工具&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址: 9png.rar &nbsp;</p> <p>　　使用方法:先用PS等软件处理图片，然后再用9png来处理，最后用X那个软件打包。</p> <p><strong>9.Java JDK&nbsp;</strong></p> <p>　　Java环境安装程序，这个必须装，不然以上以下的程序有可能运行不了。&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址:http://u.115.com/file/bhze9xyf</p> <p><strong>10.Android-sdk</strong></p> <p>　　安卓SDK这个就不说了，下了选择你需要的API下载&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址:http://u.115.com/file/clg28r43</p> <p><strong>11.eclipse&nbsp;&nbsp;&nbsp;</strong></p> <p>　　最新的Eclipse JAVA编译环境&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;</p> <p>　　下载地址:http://u.115.com/file/bhzeezng</p> <p><strong>12.ADT&nbsp;&nbsp;&nbsp;&nbsp;</strong>&nbsp;&nbsp;&nbsp;</p> <p>　　下载地址:http://u.115.com/file/bhze92e2</p> <p><strong>13.Repo:</strong></p> <div> <pre><span style="color: #008080;">1</span> mkdir -p ~/bin <br /><span style="color: #008080;">2</span> curl <span style="color: #800000;">"</span><span style="color: #800000;">http://php.webtutor.pl/en/wp-content/uploads/2011/09/repo</span><span style="color: #800000;">"</span>&gt; ~/bin/repo <br /><span style="color: #008080;">3</span> chmod a+x ~/bin/repo</pre> </div> <p><strong>14.ROM源代码</strong></p> <p>CM7完整源码:</p> <div> <pre><span style="color: #008080;">1</span> mkdir -p ~/android/system<br /><span style="color: #008080;">2</span> cd ~/android/system/<br /><span style="color: #008080;">3</span> repo init -u git:<span style="color: #008000;">//</span><span style="color: #008000;">github.com/CyanogenMod/android.git -b gingerbread</span><span style="color: #008000;"><br /></span><span style="color: #008080;">4</span> repo sync</pre> </div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197882.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-17 14:56 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197882.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于Android软件破解的经验总结 (转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197881.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sun, 17 Feb 2013 06:52:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197881.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197881.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197881.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197881.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197881.html</trackback:ping><description><![CDATA[<div>android软件破解的工具：<br /> smali.jar&#8212;&#8212;google官方提供，主要作用是把smali文件打包成class.dex文件<br /> baksmali.jar&#8212;&#8212;google官方提供，主要作用是把*.odex文件反编译为smali文件<br /> apktool.jar&#8212;&#8212;第三方提供？用于解析*.apk文件，生成smali文件和解析资源文件<br /> signapk.jar&#8212;&#8212;apk签名工具<br /> ddms&#8212;&#8212;ADT中的一个调试工具<br /> <br /> <br /> 破解工具的使用方法：<br /> http://sin90lzc.iteye.com/blog/1198173<br /> <br /> <br /> 除了这些破解工具之外，还需要对smali语法有一定的了解。下面的网址对smali的语法有详细的说明：<br /> http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html<br /> <br /> <br /> 最后，最好对Android的应用开发有一定的了解，至少对Android的四大组件有深刻的认识：Activity,Service,ContentProvider,BroadcastReceiver<br /> <br /> <br /> Android应用程序在某些机器上不能运行、崩溃的原因不外乎以下几点：<br /> 原因一：该应用程序需要依赖于生产厂商的框架（像三星，它对android的framework做过大量的修改）<br /> 错误提示：找不到field，找不到对应的方法，找不到相应的类<br /> 解决途径：<br /> 1.在smali中尝试屏蔽掉相应的field,method,或类的调用，然后进行大量测试，确保不影响正常使用<br /> 2.反编译framework，找到缺少的field,method,类的相应smali文件，根据smali文件编写java源码。（当smali文件比较小的时候，这个方法才可行，否则尽量避免用这种方法）<br /> 3.实在无招的情况下，只能把第三方的framework的smali文件复制到自己的framework里面（非常槽糕的方法）。<br /> 4.对于应用程序需要依赖第三方低层的功能实现时，而我们的低层却没有这样的功能（比如说视频通话等），此时可以使用上面的方法一解决，也可以参考技术四。<br /> <br /> <br /> 原因二：资源文件不存在，像color，drawable,string等等的资源<br /> 错误提示：资源文件找不到<br /> 解决途径：<br /> 在技巧一中有详细说明。<br /> <br /> <br /> 原因三：应用程序需要一些函数库的支持（在目录/system/lib中缺少相应的函数库）。<br /> 错误提示：一般都会抛出UnSatisfiedException异常，后面紧跟所缺函数库的库名。<br /> 解决途径：<br /> 1.在第三方的函数库中找到对应的so文件，然后复制到自己的函数库中。<br /> 2.如果函数库与函数库之间有着各种耦合的时候，方法一可能就会不适用了（看运气呗）。这时候就只能反编译so文件了（这个是C/C++的反编译的应用了，需要再学习）<br /> <br /> <br /> 原因四：应用程序没有相应的权限<br /> 错误提示：nopermission<br /> 解决途径：<br /> 1.在AndroidMenifest.xml文件中添加&lt;user-permision /&gt;添加相应的权限<br /> <br /> <br /> 原因五：由于应用程序本身的一些安全机制或条件判断影响程序的表现<br /> 解决途径：<br /> 1.反编译成smali文件，使用技巧三的方法跟踪程序的运行，耐心地分析程序的逻辑，找到可疑smali代码，屏蔽或修改代码。<br /> <br /> <br /> 原因六：数据库的结构不一样<br /> 错误提示：缺少某个字段或类型不匹配<br /> 场情：比如android的音乐播放器与三星的音乐播放器，它们的数据库结构由MediaProvider.apk这个包提供。然而两者在MediaProvider.apk中关于数据库结构的定义是不一样的，三星音乐播放器需要更多的字段去保存信息。<br /> 解决途径：<br /> 1.拿上面场情为例，反编译MediaProvider.apk，从smali文件中找到组件ContentProvider的定义（smali文件）， 在该smali文件中找到关于SQL生成表结构的字符串（如：create  table...)，修改该SQL语句来适合三星音乐播放器的需要，然后重新打包回apk文件。<br /> <p><br /> </p> <p>原因七：应用程序需要引用第三方提供商自定义的框架（比如，三星的/system/framework目录下有twframework.jar、twframework-res.apk，这个就是三星的UI框架)</p> 错误提示：<br /> 解决途径：<br /> 1.屏蔽AndroidMenifest.xml文件中&lt;uses-library android:name="sec_feature" /&gt;的代码，一般这样改动是不可行的。<br /> 2.在/system/etc/permission目录下添加库的声明，如添加touchwiz.xml文件，文件内容如下：<br /> &lt;?xml version="1.0" encoding="utf-8"?&gt;<br /> &lt;permissions&gt;<br /> &nbsp; &nbsp; &lt;library name="touchwiz" file="/system/framework/twframework.jar"/&gt;<br /> &lt;/permissions&gt;<br /> 最后，还需要把三星的twframework.jar、twframework-res.apk复制到/system/framework目录下<br /> <br /> 反编译或破解的技巧总结：<br /> 一、对无应用程序源码的情况下，对资源文件的增删改。<br /> 概述：在无程序源码，不重新编译的情况下，删除或修改资源文件都是非常简单的一件事情，网上也有很多的文章提到过。但是网上却找不到在不重新编译的情况下添加资源文件的方法。<br /> 在不重新编译的情况下添加资源文件的步骤：<br /> 1.按正常的应用程序开发添加资源。比如，要添加一个string资源，在values/strings.xml上加上：<br /> &lt;string name="newstring"&gt;content&lt;/string&gt;<br /> <br /> <br /> 2.一个编译后的apk会在values目录下多生成了一个public.xml文件，这个文件记录了每个资源的引用编号。以添加string资源为例， 在public.xml文件中找到&lt;public type="string" ...&gt;中最后一个元素，在这个元素后添加<br /> &lt;public type="string" name="newstring" id="0x7f0700a0"  /&gt;&lt;!--此时id就是string资源newstring的引用编号，注意该id应该是public.xml文件中是唯一值--&gt;<br /> <br /> <br /> 3.修改smali文件，使用新增的资源<br /> invoke-virtual {p0}, Lcom/sini/SfsdfsActivity;-&gt;getResources()Landroid/content/res/Resources;<br /> <br /> <br /> move-result-object v0<br /> <br /> <br /> const v1, 0x7f0700a0<br /> <br /> <br /> invoke-virtual {v0, v1}, Landroid/content/res/Resources;-&gt;getString(I)Ljava/lang/String;<br /> <br /> <br /> 二、编写smali文件<br /> 概述：自己一手一脚去写smali文件是件超级困难的事情，如何快速地得到smali代码呢？<br /> 技巧：使用eclipse开发工具，新建一个Android项目，用正常的开发方式写一段java代码（这个代码就是你想在smali中完成的东西）。使 用eclipse的run-&gt;Android Application选项  生成apk文件，再把apk文件反编译，找到需要的smali代码，然后复制这段代码到需要的地方。NOTIC：复制的时候需要注意smali的变量 v0,v1...的正确性。<br /> <br /> <br /> 三、跟踪程序运行<br /> 概述：没源码=寸步难行！为了能跟踪无源码的apk程序的运行，只能辛苦地修改smali添加跟踪信息了。值得庆幸的是，android本身自带有方便的日志API(Log.i()\Log.w()...);<br /> 技巧：按技巧二的方法得到Log.i()的smali代码，然后把这段代码插入到你想跟踪信息的地方。<br /> <br /> <br /> 四、只修改smali中影响UI的代码，保留功能代码（适用于必须得把smali写回java源码的情况）<br /> 概述：这里最好的例子就是破解三星的通话界面。三星的通话界面程序Phone.apk中包含了视频通话的功能，这个功能又需要依赖三星的一些低层实现。而 我们的系统中没有视频通话的功能，也没有相应的低层实现。但Phone.apk的主要功能是打电话，而这个功能android本身就自带的。也就是说三星 的Phone.apk与android的Phone.apk的核心功能是一样的，只是UI不太一样而已。此时应该只修改smali中的影响UI的代码，屏 蔽掉<br /> smali中对视频通话的调用。<br /> 技巧：找到程序中影响UI的Actvity，然后根据smali文件的内容，写java源码  </div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197881.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-17 14:52 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197881.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>让你自己写的Android的Launcher成为系统中第一个启动的，也是唯一的Launcher. (转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197880.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sun, 17 Feb 2013 06:51:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197880.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197880.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197880.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197880.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197880.html</trackback:ping><description><![CDATA[<div><span style="font-size: 14px; line-height: 21px; font-family: verdana, sans-serif">原文:<div>http://1622511.blog.51cto.com/1612511/581011</div><br />如果你要定制一个Android系统，你想用你自己的Launcher(Home)作主界面来替换Android自己的Home，而且不希望用户安装的Launcher来替换掉你的Launcher.<br /> 我们可以通过修改Framework来实现这样的功能。<br /> <br /> 这里以Android2.1的源代码为例来实际说明。<br /> <br /> 1)首先了解一下Android的启动过程。<br /> &nbsp; Android系统的启动先从Zygote开始启动，然后......(中间的过程就不说了).....一直到了SystemServer(framework)这个地方，看到这段代码：<br /> <br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**<br /> &nbsp;&nbsp;&nbsp;&nbsp; * This method is called from Zygote to initialize the system. This will cause the native<br /> &nbsp;&nbsp;&nbsp;&nbsp; * services (SurfaceFlinger, AudioFlinger, etc..) to be started. After that it will call back<br /> &nbsp;&nbsp;&nbsp;&nbsp; * up into init2() to start the Android services.<br /> &nbsp;&nbsp;&nbsp;&nbsp; */<br /> &nbsp;&nbsp;&nbsp; native public static void init1(String[] args);<br /> <br /> &nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (SamplingProfilerIntegration.isEnabled()) {<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SamplingProfilerIntegration.start();<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timer = new Timer();<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timer.schedule(new TimerTask() {<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @Override<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void run() {<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SamplingProfilerIntegration.writeSnapshot("system_server");<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br /> <br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // The system server has to run all of the time, so it needs to be<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // as efficient as possible with its memory usage.<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);<br /> <br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.loadLibrary("android_servers");<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; init1(args);<br /> &nbsp;&nbsp;&nbsp; }<br /> <br /> &nbsp;&nbsp;&nbsp; public static final void init2() {<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Log.i(TAG, "Entered the Android system server!");<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread thr = new ServerThread();<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thr.setName("android.server.ServerThread");<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thr.start();<br /> &nbsp;&nbsp;&nbsp; }<br /> }<br /> <br /> 从SystemServer的main函数开始启动各种服务。<br /> 首先启动init1,然后启动init2.<br /> 从上面的注释可以看到：init1这个方法时被Zygote调用来初始化系统的，init1会启动native的服务如SurfaceFlinger,AudioFlinger等等，这些工作做完以后会回调init2来启动Android的service。<br /> <br /> 这里我们主要来关注init2的过程。<br /> init2中启动ServerThread线程，<br /> ServerThread中启动了一系列的服务，比如这些：<br /> <br /> ActivityManagerService<br /> EntropyService<br /> PowerManagerService<br /> TelephonyRegistry<br /> PackageManagerService<br /> AccountManagerService<br /> BatteryService<br /> HardwareService<br /> Watchdog<br /> SensorService<br /> BluetoothService<br /> StatusBarService<br /> ClipboardService<br /> InputMethodManagerService<br /> NetStatService<br /> ConnectivityService<br /> AccessibilityManagerService<br /> NotificationManagerService<br /> MountService<br /> DeviceStorageMonitorService<br /> LocationManagerService<br /> SearchManagerService<br /> FallbackCheckinService<br /> WallpaperManagerService<br /> AudioService<br /> BackupManagerService<br /> AppWidgetService<br /> <br /> 这些大大小小的服务起来以后，开始<br /> &nbsp;((ActivityManagerService)ActivityManagerNative.getDefault()).systemReady()<br /> 在systemReady后开始开始启动Launcher。<br /> <br /> 在寻找Launcher的时候是根据HOME的filter（在Manifest中定义的&lt;category android:name="android.intent.category.HOME" /&gt;）来过滤。<br /> 然后根据filter出来的HOME来启动，如果只有一个HOME，则启动这个HOME，如果用户自己装了HOME，那就会弹出来一个列表供用户选择。<br /> <br /> 我们现在希望从这里弹出我们自己定制的Launcher,同时也不希望弹出选择HOME的界面，我们不希望用户修改我们的home，比如我们的home上放了好多广告，以及强制安装的程序，不希望用户把它干掉。<br /> <br /> 我们可以通过这样来实现：<br /> <br /> 2) 定义一个私有的filter选项，然后用这个选项来过滤HOME.<br /> &nbsp;&nbsp; 一般情况下我们使用Manifest中定义的&lt;category android:name="android.intent.category.HOME"来过滤的，我们现在增加一个私有的HOME_FIRST过滤。<br /> <br /> &nbsp;&nbsp;&nbsp;&nbsp; 在Intent.java(frameworks/base/core/java/android/content/Intent.java)中添加两行代码<br /> <br /> &nbsp;&nbsp;&nbsp; //lixinso:添加CATEGORY_HOME_FIRST<br /> &nbsp;&nbsp;&nbsp; @SdkConstant(SdkConstantType.INTENT_CATEGORY)<br /> &nbsp;&nbsp;&nbsp; public static final String CATEGORY_HOME_FIRST = "android.intent.category.HOME_FIRST";<br /> <br /> 3）修改和CATEGORY_HOME相关的所有的地方，都改成HOME_FIRST，主要是framework中的这几个地方：<br /> <br /> &nbsp;&nbsp;&nbsp; frameworks/base/services/java/com/android/server/am/ActivityManagerService.java中<br /> &nbsp;&nbsp;&nbsp; //intent.addCategory(Intent.CATEGORY_HOME);<br /> &nbsp;&nbsp;&nbsp; 改成intent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso:<br /> &nbsp;&nbsp;&nbsp; //if (r.intent.hasCategory(Intent.CATEGORY_HOME)) {<br /> &nbsp;&nbsp;&nbsp; 改成if (r.intent.hasCategory(Intent.CATEGORY_HOME_FIRST)) { //lixinso: Intent.CATEGORY_HOME -&gt; Intent.CATEGORY_HOME_FIRST<br /> &nbsp;<br /> &nbsp;&nbsp; frameworks/base/services/java/com/android/server/am/HistoryRecorder.java中<br /> &nbsp;&nbsp; // _intent.hasCategory(Intent.CATEGORY_HOME) &amp;&amp;<br /> &nbsp;&nbsp; 改成 _intent.hasCategory(Intent.CATEGORY_HOME_FIRST) &amp;&amp; //lixinso: Intent.CATEGORY_HOME-&gt;Intent.CATEGORY_HOME_FIRST<br /> <br /> &nbsp;&nbsp; frameworks/policies/base/mid/com/android/internal/policy/impl/MidWindowManager.java中<br /> &nbsp;&nbsp; //mHomeIntent.addCategory(Intent.CATEGORY_HOME);&nbsp;<br /> &nbsp;&nbsp; 改成 mHomeIntent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso<br /> &nbsp;<br /> &nbsp; frameworks/policies/base/mid/com/android/internal/policy/impl/RecentApplicationsDialog.java中<br /> &nbsp;&nbsp; //new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),0);<br /> &nbsp;&nbsp; 改成 new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME_FIRST),0); //lixinso<br /> <br /> &nbsp; frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindowManager.java中<br /> &nbsp;&nbsp; //mHomeIntent.addCategory(Intent.CATEGORY_HOME);<br /> &nbsp;&nbsp; 改成 mHomeIntent.addCategory(Intent.CATEGORY_HOME_FIRST); //lixinso<br /> <br /> &nbsp; frameworks/policies/base/phone/com/android/internal/policy/impl/RecentApplicationsDialog.java中<br /> &nbsp;&nbsp; //ResolveInfo homeInfo = pm.resolveActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME),0);<br /> &nbsp;&nbsp; 改成 ResolveInfo homeInfo = pm.resolveActivity(new  Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME_FIRST),0);  //lixinso<br /> <br /> <br /> <br /> 4) 写一个自己的Launcher.<br /> &nbsp;&nbsp; 可以参考android sample中的Launcher，或者android源代码中的 /packages/apps/Launcher 来写。<br /> &nbsp;&nbsp; 在Launcher中标记其是不是Launcher的最关键的代码时Manifest中的filter:android:name="android.intent.category.HOME"<br /> &nbsp;&nbsp; 现在我们定义了自己的filter,那么，我们在我们自己写的Launcher中将Manifest改为：<br /> &nbsp;&nbsp;&nbsp; &lt;application&nbsp; android:process="android.process.acore3" android:icon="@drawable/icon" android:label="@string/app_name"&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;activity android:name=".FirstAppActivity"<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; android:label="@string/app_name"&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;intent-filter&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;action android:name="android.intent.action.MAIN" /&gt;<br /> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;category android:name="android.intent.category.HOME_FIRST" /&gt;<br /> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;category android:name="android.intent.category.DEFAULT" /&gt;<br /> &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &lt;category android:name="android.intent.category.MONKEY" /&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/intent-filter&gt;<br /> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/activity&gt;<br /> &nbsp;&nbsp;&nbsp; &lt;/application&gt;<br /> <br /> 然后将编译好的apk放到/out/target/product/generic/system/app目录下。<br /> <br /> 5)将Android自带的Launcher删除掉，包括源代码(packages/apps/Launcher)和apk(/out/target/product/generic/system/app/Launcher.apk)。<br /> <br /> 6)<br /> 做完这些工作，就可以重新编译Android了，我们可以编译修改过的几个相关的包。<br /> 如果之前编译过了Android源码，可以用mmm命令来编译部分的改动。<br /> 这里需要这样编译：<br /> <br /> $ . build/envsetup.sh&nbsp;<br /> $ mmm frameworks/base<br /> $ mmm frameworks/base/services/java<br /> $ mmm frameworks/policies/base/mid<br /> $ mmm frameworks/policies/base/phone<br /> <br /> 7)<br /> 编译完成后重新生成img文件。<br /> $ make snod<br /> <br /> 8) 现在可以启动Android模拟器来看效果了。<br /> 首先设置环境变量：<br /> $ export ANDROID_PRODUCT_OUT= ./out/target/product/generic<br /> 然后切换到<br /> $ cd ./out/host/linux-x86/bin<br /> 运行<br /> $ ./emulator<br /> <br /> 这样我们启动的模拟器里面用的image就是我们刚才编译好的自己定制的东西了。<br /> 从模拟器上可以看到启动的Launcher是我们自己的Launcher，不会出现默认的Launcher了，也不会出现选择界面。<br /> <br /> 9)我们再验证一下，如果用户装上了一个其他的Launcher(Home)会怎么样。<br /> &nbsp; 从网上找一个一般的Launcher或者自己写一个一般的Launcher装上去，重新启动，不会出现选择界面。<br /> &nbsp; 按HOME键也不会出来两个HOME来选择。<br /> <br /> <br /> 这样我们就牢牢控制了用户的桌面。<br /> 只有我们自己定制的HOME才能装上。 这对于定制Android设备的厂商很有用处。</span></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197880.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-17 14:51 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197880.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>android 移植 (1)</title><link>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197879.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sun, 17 Feb 2013 06:48:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197879.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/197879.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197879.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/197879.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/197879.html</trackback:ping><description><![CDATA[<div>要移植，就要了解系统的结构和打包解包：<br /> 打包很容易，只需要制作成ZIP格式的压缩包就行了，里面包含2个文件夹和1个boot.img文件，boot.img是内核，没有内核的系统是不能运行 的，另外两个文件夹一个是system，也就是Android系统所在地，另一个是META-INF，这里一般存放是刷机脚本，我们移植一般需要改的就是 system文件夹里的内容。<br /> 解包就是解压缩。<br /> 首先说结构，system下有：<br /> App文件夹（存放内置软件的地方，每个软件都有自己的名字标注着，很容易识别，在移植上除USB.apk必须用咱们自己的版本以外，其他可以用同分辨率机型的APP直接替换）<br /> Bin文件夹（本文件夹一般存放的是开机运行的脚本和一些系统必备代码，一般移植出了问题不能开机就是这里的问题，一般我们用702的或者720的ROM 里的，注意除了NETD需要用701的外，其他也可以直接用702或者720ROM的，不过一般系统升级不会修改这里，在移植的时候，要删除2nd- init以及所有.sh脚本文件，这些对701是没有效果的，如果电池显示？，那么可以通过替换battd文件来修複）<br /> Etc文件夹（本文件夹里存放着这种配置文件，包括WIFI，蓝牙和基带{\etc\motorola\bp_nvm_default}配置文件，A- GPS的文件和Hosts文件也在这里，media_profiles.xml可以控制录像质量，cameraCalFileDef5M.bin与 cameraCalFileDef8M.bin是照相的数据库文件，都可以修改，子文件夹init.d文件夹下可以写入自己的开机脚本，来实现一些程序或 者脚本开机啓动，如果想要执行某模块，可以添加一个文件，不要有后缀名，格式爲00aaa&nbsp;&nbsp;00是执行序号，系统开机时会按顺序执行，aaa是爲了区别 每个脚本的名称，可以随便写）<br /> Font文件夹（字体文件夹，没什么好解释的，你可以替换爲你喜欢的字体）<br /> Framework文件夹（系统框架结构文件目录，这个目录下是系统服务和系统界面的所在地，一般不可以单独替换，要移植的话必须全部替换，不然会卡 M，framework-res.apk文件就是系统语言，界面的所在文件，修改他就可以直接修改系统界面，framework-res.apk必须与 app文件夹中systemui.apk配套，不然开机会出现状态栏FC，不同版本不可以乱用，比如CM7.1.0.5不能用CM7.1.0.4的文件）<br /> Lib文件夹（本文件夹是系统所需要用到的驱动，库文件的所在，如果某程序FC或者无法正常运转，可能是这里的问题，我把我知道的一些文件的用途说一下：<br /> ***Lib/dsp文件夹 DSP驱动所在，一般不需要改<br /> ***lib/egl 显示芯片驱动，一般不需要改<br /> ***libaudio.so 话筒及音频驱动 必须用701的<br /> ***libaudioflinger.so 音频附属驱动 必须用701的<br /> ***libbridge.so 相机方面 <br /> ***libbattd.so&nbsp;&nbsp;电池驱动<br /> ***libcamera.so 相机驱动 必须用701的<br /> ***libcameraservice.so 相机服务驱动<br /> ***libfmradio.so FM驱动<br /> ***libHPImgApi.so 图片接口驱动 必须用701的<br /> ***libLCML.so 未知驱动&nbsp;&nbsp;必须用701的<br /> ***liboemcamera.so 相机驱动&nbsp;&nbsp;必须用701的<br /> ***libOMX.TI.JPEG.Encoder.so 照片编码器&nbsp;&nbsp;必须用701的 否则照片黑<br /> ***libOMX.TI.AAC.decode.so&nbsp;&nbsp;此类型的都是编码器和解码器驱动（多媒体）<br /> 除上述红色文件必须用701外，其他文件可以直接用702或者720的。<br /> Media文件夹（铃声及开机动画）<br /> TTS文件夹（文字转语音文件夹）<br /> Usr文件夹（键盘文件与各类数据库）<br /> Xbin文件夹（系统工具文件夹）<br /> Build.prop文件（系统参数文件，修改这里可以调节系统部分参数与性能）<br /> 如：默认虚拟机大小，铃声延迟，系统版本等</div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/197879.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2013-02-17 14:48 <a href="http://www.cppblog.com/guojingjia2006/archive/2013/02/17/197879.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>不同android 版本的webview底层实现有差异</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/12/18/196429.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Tue, 18 Dec 2012 12:09:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/12/18/196429.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/196429.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/12/18/196429.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/196429.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/196429.html</trackback:ping><description><![CDATA[今天弄了下android webview下的几个页面。原先以为android 4+把 webview的viewport属性忽略掉了。<br />但是今天弄了下。加了个 authorizationView.getSettings().setUseWideViewPort(true);<br />viewport 的几个属性重新起作用。(测试环境，4.0+的几个版本）<br /><br />但是又遇到几个问题，就是html里有input的时候。获取焦点的时候，android会重新缩放到原来模式,看源码：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; font-family: Comic Sans MS;">/**</span><span style="color: #008000; "><br /></span><span style="color: #008000; font-family: Comic Sans MS;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;Called&nbsp;in&nbsp;response&nbsp;to&nbsp;a&nbsp;message&nbsp;from&nbsp;webkit&nbsp;telling&nbsp;us&nbsp;that&nbsp;the&nbsp;soft<br /></span><span style="color: #008000; font-family: Comic Sans MS;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*&nbsp;keyboard&nbsp;should&nbsp;be&nbsp;launched.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-family: Comic Sans MS;">*/</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Comic Sans MS;">private</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-family: Comic Sans MS;">void</span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;displaySoftKeyboard(</span><span style="color: #0000ff; font-family: Comic Sans MS;">boolean</span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;isTextView)&nbsp;{<br /></span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InputMethodManager&nbsp;imm&nbsp;</span><span style="color: #000000; font-family: Comic Sans MS;">=</span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;(InputMethodManager)<br /></span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getContext().getSystemService(Context.INPUT_METHOD_SERVICE);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-family: Comic Sans MS;">//</span><span style="color: #008000; font-family: Comic Sans MS;">&nbsp;bring&nbsp;it&nbsp;back&nbsp;to&nbsp;the&nbsp;default&nbsp;level&nbsp;scale&nbsp;so&nbsp;that&nbsp;user&nbsp;can&nbsp;enter&nbsp;text</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Comic Sans MS;">boolean</span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;zoom&nbsp;</span><span style="color: #000000; font-family: Comic Sans MS;">=</span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;mZoomManager.getScale()&nbsp;</span><span style="color: #000000; font-family: Comic Sans MS;">&lt;</span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;mZoomManager.getDefaultScale();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Comic Sans MS;">if</span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;(zoom)&nbsp;{<br /></span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mZoomManager.setZoomCenter(mLastTouchX,&nbsp;mLastTouchY);<br /></span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mZoomManager.setZoomScale(mZoomManager.getDefaultScale(),&nbsp;</span><span style="color: #0000ff; font-family: Comic Sans MS;">false</span><span style="color: #000000; font-family: Comic Sans MS;">);<br /></span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Comic Sans MS;">if</span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;(isTextView)&nbsp;{<br /></span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rebuildWebTextView();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Comic Sans MS;">if</span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;(inEditingMode())&nbsp;{<br /></span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imm.showSoftInput(mWebTextView,&nbsp;</span><span style="color: #000000; font-family: Comic Sans MS;">0</span><span style="color: #000000; font-family: Comic Sans MS;">,&nbsp;mWebTextView.getResultReceiver());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Comic Sans MS;">if</span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;(zoom)&nbsp;{<br /></span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;didUpdateWebTextViewDimensions(INTERSECTS_SCREEN);<br /></span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Comic Sans MS;">return</span><span style="color: #000000; font-family: Comic Sans MS;">;<br /></span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-family: Comic Sans MS;">//</span><span style="color: #008000; font-family: Comic Sans MS;">&nbsp;Used&nbsp;by&nbsp;plugins&nbsp;and&nbsp;contentEditable.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-family: Comic Sans MS;">//</span><span style="color: #008000; font-family: Comic Sans MS;">&nbsp;Also&nbsp;used&nbsp;if&nbsp;the&nbsp;navigation&nbsp;cache&nbsp;is&nbsp;out&nbsp;of&nbsp;date,&nbsp;and<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-family: Comic Sans MS;">//</span><span style="color: #008000; font-family: Comic Sans MS;">&nbsp;does&nbsp;not&nbsp;recognize&nbsp;that&nbsp;a&nbsp;textfield&nbsp;is&nbsp;in&nbsp;focus.&nbsp;&nbsp;In&nbsp;that<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-family: Comic Sans MS;">//</span><span style="color: #008000; font-family: Comic Sans MS;">&nbsp;case,&nbsp;use&nbsp;WebView&nbsp;as&nbsp;the&nbsp;targeted&nbsp;view.<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-family: Comic Sans MS;">//</span><span style="color: #008000; font-family: Comic Sans MS;">&nbsp;see&nbsp;</span><span style="color: #008000; text-decoration: underline; font-family: Comic Sans MS;">http://b/issue?id=2457459</span><span style="color: #008000; "><br /></span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;imm.showSoftInput(</span><span style="color: #0000ff; font-family: Comic Sans MS;">this</span><span style="color: #000000; font-family: Comic Sans MS;">,&nbsp;</span><span style="color: #000000; font-family: Comic Sans MS;">0</span><span style="color: #000000; font-family: Comic Sans MS;">);<br /></span><span style="color: #000000; font-family: Comic Sans MS;">&nbsp;&nbsp;&nbsp;&nbsp;}</span></div>从源码可以看到，webview当要弹起键盘的时候，会判定当前的缩放比例与默认大小（我测试了下，我自己的版本的默认值是1.5),<br />当你网页viewport设置initial-scale=0.5时，当input 获取焦点的时候，android会放大到原来模式，不是我们想要的，网上查了下相关，<br />有个解决方案：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; font-family: Courier;">wv.setOnFocusChangeListener(</span><span style="color: #0000ff; font-family: Courier;">new</span><span style="color: #000000; font-family: Courier;">&nbsp;View.OnFocusChangeListener()&nbsp;{<br /><br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Courier;">public</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-family: Courier;">void</span><span style="color: #000000; font-family: Courier;">&nbsp;onFocusChange(View&nbsp;v,&nbsp;</span><span style="color: #0000ff; font-family: Courier;">boolean</span><span style="color: #000000; font-family: Courier;">&nbsp;hasFocus)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-family: Courier;">//</span><span style="color: #008000; font-family: Courier;">&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Courier;">try</span><span style="color: #000000; font-family: Courier;">&nbsp;{<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Field&nbsp;defaultScale&nbsp;</span><span style="color: #000000; font-family: Courier;">=</span><span style="color: #000000; font-family: Courier;">&nbsp;WebView.</span><span style="color: #0000ff; font-family: Courier;">class</span><span style="color: #000000; "><br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getDeclaredField(</span><span style="color: #000000; font-family: Courier;">"</span><span style="color: #000000; font-family: Courier;">mDefaultScale</span><span style="color: #000000; font-family: Courier;">"</span><span style="color: #000000; font-family: Courier;">);<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaultScale.setAccessible(</span><span style="color: #0000ff; font-family: Courier;">true</span><span style="color: #000000; font-family: Courier;">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Courier;">float</span><span style="color: #000000; font-family: Courier;">&nbsp;_s&nbsp;</span><span style="color: #000000; font-family: Courier;">=</span><span style="color: #000000; font-family: Courier;">&nbsp;defaultScale.getFloat(wv);<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaultScale.setFloat(wv,&nbsp;scale);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Courier;">float</span><span style="color: #000000; font-family: Courier;">&nbsp;x&nbsp;</span><span style="color: #000000; font-family: Courier;">=</span><span style="color: #000000; font-family: Courier;">&nbsp;wv.getScale();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Courier;">int</span><span style="color: #000000; font-family: Courier;">&nbsp;i&nbsp;</span><span style="color: #000000; font-family: Courier;">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-family: Courier;">0</span><span style="color: #000000; font-family: Courier;">;<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff; font-family: Courier;">catch</span><span style="color: #000000; font-family: Courier;">&nbsp;(Exception&nbsp;e)&nbsp;{<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Courier;">try</span><span style="color: #000000; font-family: Courier;">&nbsp;{<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Field&nbsp;defaultZoom&nbsp;</span><span style="color: #000000; font-family: Courier;">=</span><span style="color: #000000; font-family: Courier;">&nbsp;WebView.</span><span style="color: #0000ff; font-family: Courier;">class</span><span style="color: #000000; "><br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getDeclaredField(</span><span style="color: #000000; font-family: Courier;">"</span><span style="color: #000000; font-family: Courier;">mZoomManager</span><span style="color: #000000; font-family: Courier;">"</span><span style="color: #000000; font-family: Courier;">);<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaultZoom.setAccessible(</span><span style="color: #0000ff; font-family: Courier;">true</span><span style="color: #000000; font-family: Courier;">);<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Field&nbsp;defaultScale&nbsp;</span><span style="color: #000000; font-family: Courier;">=</span><span style="color: #000000; font-family: Courier;">&nbsp;defaultZoom.getType()<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getDeclaredField(</span><span style="color: #000000; font-family: Courier;">"</span><span style="color: #000000; font-family: Courier;">mDefaultScale</span><span style="color: #000000; font-family: Courier;">"</span><span style="color: #000000; font-family: Courier;">);<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaultScale.setAccessible(</span><span style="color: #0000ff; font-family: Courier;">true</span><span style="color: #000000; font-family: Courier;">);<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaultScale.setFloat(defaultZoom.get(wv),&nbsp;scale);<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000ff; font-family: Courier;">catch</span><span style="color: #000000; font-family: Courier;">&nbsp;(Exception&nbsp;ee)&nbsp;{<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ee.printStackTrace();<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;});</span></div>但是作者碰到另外一个问题，引用自原话：<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">as&nbsp;it&nbsp;showed,&nbsp;I&nbsp;using&nbsp;reflect&nbsp;to&nbsp;find&nbsp;the&nbsp;field&nbsp;</span><span style="color: #000000; ">'</span><span style="color: #000000; ">mDefaultScale</span><span style="color: #000000; ">'</span><span style="color: #000000; ">&nbsp;to&nbsp;control&nbsp;the&nbsp;WebView.<br />But&nbsp;it&nbsp;doesn</span><span style="color: #000000; ">'</span><span style="color: #000000; ">t&nbsp;work&nbsp;on&nbsp;Android&nbsp;4.1.1&nbsp;(Google&nbsp;Nexus),&nbsp;and&nbsp;I&nbsp;catch&nbsp;an&nbsp;exception&nbsp;&#8212;&#8212;&nbsp;java.lang.NoSuchFieldException:&nbsp;mDefaultScale.</span><span style="color: #000000; "><br /></span><span style="color: #000000; ">Then&nbsp;I&nbsp;list&nbsp;the&nbsp;fileds&nbsp;and&nbsp;found&nbsp;the&nbsp;framework&nbsp;source&nbsp;seems&nbsp;being&nbsp;changed(I&nbsp;can&nbsp;only&nbsp;reach&nbsp;a&nbsp;field&nbsp;called&nbsp;</span><span style="color: #000000; ">'</span><span style="color: #000000; ">mProvider</span><span style="color: #000000; ">'</span><span style="color: #000000; ">).<br /><br />So&nbsp;how&nbsp;can&nbsp;I&nbsp;fix&nbsp;the&nbsp;problem&nbsp;(I&nbsp;haven</span><span style="color: #000000; ">'</span><span style="color: #000000; ">t&nbsp;got&nbsp;the&nbsp;source&nbsp;yet)?&nbsp;Thanks&nbsp;for&nbsp;reading&nbsp;my&nbsp;question&nbsp;with&nbsp;my&nbsp;poor&nbsp;English,&nbsp;Thx&nbsp;:)</span><span style="color: #000000; "><br /></span><span style="color: #000000; "><br />PS:&nbsp;maybe&nbsp;a&nbsp;online&nbsp;framework&nbsp;source&nbsp;review&nbsp;website&nbsp;is&nbsp;helpful&nbsp;but&nbsp;I&nbsp;can</span><span style="color: #000000; ">'</span><span style="color: #000000; ">t&nbsp;found&nbsp;one,&nbsp;if&nbsp;you&nbsp;can&nbsp;provide&nbsp;me&nbsp;one,&nbsp;it&nbsp;will&nbsp;be&nbsp;great.&nbsp;:P</span></div><br />完了我自己测试了，发现此方案解决不了。但是引出了另外一问题，就是不用android版本下的webview实现是不一样的，其实看代码就能看出，<br />原先webview有mDefaultScale字段，但是后来应该挪到mZoomManager里去了，但是我发现我手机上webview 实现和作者遇到的问题一样，只有mProvider成员，<br />没有mZoomManager,所以只能寻求源码，千辛万苦，终于找到<br /><div>http://androidxref.com/4.2_r1/xref/frameworks/base/core/java/android/webkit/WebViewClassic.java，<br />mProvider 其实类型就是WebViewClassic(自己看下源码实现）,简要提下，WebProvider只是一个接口，作为WebView的一个成员，<br />创建时用了factory来，完了看下几个工厂类，最后是webviewclassic实例)。<br />&nbsp;对于Jerry Bean 4.2这个版本（我一个手机就是自己刷的rom)，webview的实现又换了个，所以要拿到默认缩放的成员，如下:<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">try</span><span style="color: #000000; ">&nbsp;{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Field&nbsp;defaultScale&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;WebView.</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.getDeclaredField(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">mDefaultScale</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaultScale.setAccessible(</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">float</span><span style="color: #000000; ">&nbsp;sv&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;defaultScale.getFloat(authorizationView);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaultScale.setFloat(authorizationView,&nbsp;xxx);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">catch</span><span style="color: #000000; ">&nbsp;(SecurityException&nbsp;e)&nbsp;{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">catch</span><span style="color: #000000; ">&nbsp;(IllegalArgumentException&nbsp;e)&nbsp;{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">catch</span><span style="color: #000000; ">&nbsp;(IllegalAccessException&nbsp;e)&nbsp;{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">catch</span><span style="color: #000000; ">&nbsp;(NoSuchFieldException&nbsp;e)&nbsp;{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">try</span><span style="color: #000000; ">&nbsp;{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Field&nbsp;zoomManager;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;zoomManager&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;WebView.</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">.getDeclaredField(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">mZoomManager</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;zoomManager.setAccessible(</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;zoomValue&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;zoomManager.get(authorizationView);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Field&nbsp;defaultScale&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;zoomManager.getType().getDeclaredField(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">mDefaultScale</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaultScale.setAccessible(</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">float</span><span style="color: #000000; ">&nbsp;sv&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;defaultScale.getFloat(zoomValue);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaultScale.setFloat(zoomValue,&nbsp;xxx);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">catch</span><span style="color: #000000; ">&nbsp;(SecurityException&nbsp;e1)&nbsp;{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e1.printStackTrace();&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">catch</span><span style="color: #000000; ">&nbsp;(IllegalArgumentException&nbsp;e1)&nbsp;{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">catch</span><span style="color: #000000; ">&nbsp;(IllegalAccessException&nbsp;e1)&nbsp;{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</span><span style="color: #0000FF; ">catch</span><span style="color: #000000; ">&nbsp;(NoSuchFieldException&nbsp;e1)&nbsp;{&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e1.printStackTrace();&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">try</span><span style="color: #000000; ">&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Field&nbsp;mProviderField&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;WebView.</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">.getDeclaredField(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">mProvider</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mProviderField.setAccessible(</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">mProviderField.getClass()</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;webviewclassic&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;mProviderField.get(authorizationView);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Field&nbsp;zoomManager&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;webviewclassic.getClass().getDeclaredField(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">mZoomManager</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;zoomManager.setAccessible(</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Object&nbsp;zoomValue&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;zoomManager.get(webviewclassic);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Field&nbsp;defaultScale&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;zoomManager.getType().getDeclaredField(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">mDefaultScale</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaultScale.setAccessible(</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">float</span><span style="color: #000000; ">&nbsp;sv&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;defaultScale.getFloat(zoomValue);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaultScale.setFloat(zoomValue,&nbsp;xxx);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000FF; ">catch</span><span style="color: #000000; ">(Exception&nbsp;e2)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e2.printStackTrace();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></div><br />虽然可以拿到，并且设置成功，但是在我的手机上还是不能解决input 获取焦点后自动放大，<br />完了想了下，有个实现模式可以参考:当input 获取焦点时，js调用java设置默认放缩率，设置前保存原有值，失去焦点后重新设置原来值，不然跳转到其他页面的时候，你会发现比例不对了。:)。<br /><br />因为放大后双击还是还原回原来样子。所以暂且不来纠结这个东西了。因为不同android版本的如果webview实现不一致的话，这代码就不起作用了 ：）</div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/196429.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-12-18 20:09 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/12/18/196429.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ExecutorService与Executors例子的简单剖析</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/10/30/194106.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Tue, 30 Oct 2012 13:56:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/10/30/194106.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/194106.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/10/30/194106.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/194106.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/194106.html</trackback:ping><description><![CDATA[<div>对于多线程有了一点了解之后，那么来看看java.lang.concurrent包下面的一些东西。在此之前，我们运行一个线程都是显式调用了 Thread的start()方法。我们用concurrent下面的类来实现一下线程的运行，而且这将成为以后常用的方法或者实现思路。 <br /> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 看一个简单的例子： <br /><div id=""><div><div>Java代码 &nbsp;<a id="" title="收藏这段代码"><img src="http://paddy-w.iteye.com/images/spinner.gif"  alt="" /></a></div></div><ol start="1"><li><span>public&nbsp;class&nbsp;CacheThreadPool&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>public&nbsp;static&nbsp;void&nbsp;main(String[]&nbsp;args)&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ExecutorService&nbsp;exec=Executors.newCachedThreadPool();&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>for(int&nbsp;i=0;i&lt;5;i++)&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exec.execute(<span>new&nbsp;LiftOff());&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exec.shutdown();<span>//并不是终止线程的运行，而是禁止在这个Executor中添加新的任务&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>}&nbsp;&nbsp;</li></ol></div> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个例子其实很容易看懂，ExecutorService中有一个execute方法，这个方法的参数是Runnable类型。也就是说，将一个实现了Runnable类型的类的实例作为参数传入execute方法并执行，那么线程就相应的执行了。 <br /> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-size: medium;"><span style="color: darkblue;">一、ExecutorService</span></span> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 先看看ExecutorService，这是一个接口，简单的列一下这个接口： <br /><div id=""><div><div>Java代码 &nbsp;<a title="收藏这段代码"><img src="http://paddy-w.iteye.com/images/icon_star.png" alt="收藏代码" /></a></div></div><ol start="1"><li><span>public&nbsp;interface&nbsp;ExecutorService&nbsp;extends&nbsp;Executor&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>void&nbsp;shutdown();&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;List&lt;Runnable&gt;&nbsp;shutdownNow();&nbsp;&nbsp;</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>boolean&nbsp;isShutdown();&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>boolean&nbsp;isTerminated();&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>boolean&nbsp;awaitTermination(long&nbsp;timeout,&nbsp;TimeUnit&nbsp;unit)&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;T&gt;&nbsp;Future&lt;T&gt;&nbsp;submit(Callable&lt;T&gt;&nbsp;task);&nbsp;&nbsp;</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;T&gt;&nbsp;Future&lt;T&gt;&nbsp;submit(Runnable&nbsp;task,&nbsp;T&nbsp;result);&nbsp;&nbsp;</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Future&lt;?&gt;&nbsp;submit(Runnable&nbsp;task);&nbsp;&nbsp;</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;T&gt;&nbsp;List&lt;Future&lt;T&gt;&gt;&nbsp;invokeAll(Collection&lt;?&nbsp;<span>extends&nbsp;Callable&lt;T&gt;&gt;&nbsp;tasks)&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;T&gt;&nbsp;List&lt;Future&lt;T&gt;&gt;&nbsp;invokeAll(Collection&lt;?&nbsp;<span>extends&nbsp;Callable&lt;T&gt;&gt;&nbsp;tasks,&nbsp;long&nbsp;timeout,&nbsp;TimeUnit&nbsp;unit)&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;T&gt;&nbsp;T&nbsp;invokeAny(Collection&lt;?&nbsp;<span>extends&nbsp;Callable&lt;T&gt;&gt;&nbsp;tasks)&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&lt;T&gt;&nbsp;T&nbsp;invokeAny(Collection&lt;?&nbsp;<span>extends&nbsp;Callable&lt;T&gt;&gt;&nbsp;tasks,&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>long&nbsp;timeout,&nbsp;TimeUnit&nbsp;unit)&nbsp;&nbsp;</span></li><li>}&nbsp;&nbsp;</li></ol></div> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ExecuteService继承了Executor，Executor也是一个接口，里面只有一个方法： <br /><div id=""><div><div>Java代码 &nbsp;<a title="收藏这段代码"><img src="http://paddy-w.iteye.com/images/icon_star.png" alt="收藏代码" /></a></div></div><ol start="1"><li><span>void&nbsp;execute(Runnable&nbsp;command)&nbsp;&nbsp;</span></li></ol></div> <br /> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span style="font-size: medium;"><span style="color: darkblue;">二、Executors</span></span> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Executors是一个类，直接援引JDK文档的说明来说一下这个类的作用： <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <ul>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Factory and utility methods for Executor,  ExecutorService, ScheduledExecutorService, ThreadFactory, and Callable  classes defined in this package. This class supports the following kinds  of methods: <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <li>Methods that create and return an ExecutorService set up with commonly useful configuration settings. </li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <li>Methods that create and return a ScheduledExecutorService set up with commonly useful configuration settings. </li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <li>Methods that create and return a "wrapped"  ExecutorService, that disables reconfiguration by making  implementation-specific methods inaccessible. </li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <li>Methods that create and return a ThreadFactory that sets newly created threads to a known state. </li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <li>Methods that create and return a Callable out of other  closure-like forms, so they can be used in execution methods requiring  Callable. </li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </ul> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在上面的例子中，我们用到了newCachedThreadPool()方法。看一下这个方法： <br /><div id=""><div><div>Java代码 &nbsp;<a title="收藏这段代码"><img src="http://paddy-w.iteye.com/images/icon_star.png" alt="收藏代码" /></a></div></div><ol start="1"><li><span>public&nbsp;static&nbsp;ExecutorService&nbsp;newCachedThreadPool()&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>return&nbsp;new&nbsp;ThreadPoolExecutor(0,&nbsp;Integer.MAX_VALUE,&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;60L,&nbsp;TimeUnit.SECONDS,&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>new&nbsp;SynchronousQueue&lt;Runnable&gt;());&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li></ol></div> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在源码中我们可以知道两点，1、这个方法返回类型是ExecutorService；2、此方法返回值实际是另一个类的实例。看一下这个类的信息： <br /><div id=""><div><div>Java代码 &nbsp;<a title="收藏这段代码"><img src="http://paddy-w.iteye.com/images/icon_star.png" alt="收藏代码" /></a></div></div><ol start="1"><li><span>public&nbsp;class&nbsp;ThreadPoolExecutor&nbsp;extends&nbsp;AbstractExecutorService&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;..........&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>private&nbsp;final&nbsp;BlockingQueue&lt;Runnable&gt;&nbsp;workQueue;//这个变量在下面会提到&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;..........&nbsp;&nbsp;</li><li>}&nbsp;&nbsp;</li></ol></div> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  ThreadPoolExecutor继承了AbstractExecutorService,而AbstractExecutorService又实现 了ExecutorService接口。所以，根据多态，ThreadPoolExecutor可以看作是ExecutorService类型。 <br /> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 线程执行的最关键的一步是执行了executor方法，根据java的动态绑定，实际执行的是ThreadPoolExecutor所实现的executor方法。看看源码： <br /><div id=""><div><div>Java代码 &nbsp;<a title="收藏这段代码"><img src="http://paddy-w.iteye.com/images/icon_star.png" alt="收藏代码" /></a></div></div><ol start="1"><li><span>public&nbsp;class&nbsp;ThreadPoolExecutor&nbsp;extends&nbsp;AbstractExecutorService&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;..........&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>public&nbsp;void&nbsp;execute(Runnable&nbsp;command)&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>if&nbsp;(command&nbsp;==&nbsp;null)&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>throw&nbsp;new&nbsp;NullPointerException();&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>if&nbsp;(poolSize&nbsp;&gt;=&nbsp;corePoolSize&nbsp;||&nbsp;!addIfUnderCorePoolSize(command))&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>if&nbsp;(runState&nbsp;==&nbsp;RUNNING&nbsp;&amp;&amp;&nbsp;workQueue.offer(command))&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>if&nbsp;(runState&nbsp;!=&nbsp;RUNNING&nbsp;||&nbsp;poolSize&nbsp;==&nbsp;0)&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ensureQueuedTaskHandled(command);&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>else&nbsp;if&nbsp;(!addIfUnderMaximumPoolSize(command))&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reject(command);&nbsp;<span>//&nbsp;is&nbsp;shutdown&nbsp;or&nbsp;saturated&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;..........&nbsp;&nbsp;</li><li>}&nbsp;&nbsp;</li></ol></div> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 根据程序正常执行的路线来看，这个方法中比较重要的两个地方分别是： <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、workQueue.offer(command) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; workQueue在上面提到过，是BlockingQueue&lt;Runnable&gt;类型的变量，这条语句就是将Runnable类型的实例加入到队列中。 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、ensureQueuedTaskHandled(command) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个是线程执行的关键语句。看看它的源码： <br /><div id=""><div><div>Java代码 &nbsp;<a title="收藏这段代码"><img src="http://paddy-w.iteye.com/images/icon_star.png" alt="收藏代码" /></a></div></div><ol start="1"><li><span>public&nbsp;class&nbsp;ThreadPoolExecutor&nbsp;extends&nbsp;AbstractExecutorService&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;..........&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>private&nbsp;void&nbsp;ensureQueuedTaskHandled(Runnable&nbsp;command)&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>final&nbsp;ReentrantLock&nbsp;mainLock&nbsp;=&nbsp;this.mainLock;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mainLock.lock();&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>boolean&nbsp;reject&nbsp;=&nbsp;false;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread&nbsp;t&nbsp;=&nbsp;<span>null;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>try&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>int&nbsp;state&nbsp;=&nbsp;runState;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>if&nbsp;(state&nbsp;!=&nbsp;RUNNING&nbsp;&amp;&amp;&nbsp;workQueue.remove(command))&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reject&nbsp;=&nbsp;<span>true;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>else&nbsp;if&nbsp;(state&nbsp;&lt;&nbsp;STOP&nbsp;&amp;&amp;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;poolSize&nbsp;&lt;&nbsp;Math.max(corePoolSize,&nbsp;<span>1)&nbsp;&amp;&amp;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;!workQueue.isEmpty())&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t&nbsp;=&nbsp;addThread(<span>null);&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span>finally&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mainLock.unlock();&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>if&nbsp;(reject)&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;reject(command);&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>else&nbsp;if&nbsp;(t&nbsp;!=&nbsp;null)&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.start();&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;..........&nbsp;&nbsp;</li><li>}&nbsp;&nbsp;</li></ol></div> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在这里我们就可以看到最终执行了t.start()方法来运行线程。在这之前的重点是t=addThread(null)方法，看看addThread方法的源码： <br /><div id=""><div><div>Java代码 &nbsp;<a title="收藏这段代码"><img src="http://paddy-w.iteye.com/images/icon_star.png" alt="收藏代码" /></a></div></div><ol start="1"><li><span>public&nbsp;class&nbsp;ThreadPoolExecutor&nbsp;extends&nbsp;AbstractExecutorService&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;..........&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>private&nbsp;Thread&nbsp;addThread(Runnable&nbsp;firstTask)&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Worker&nbsp;w&nbsp;=&nbsp;<span>new&nbsp;Worker(firstTask);&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread&nbsp;t&nbsp;=&nbsp;threadFactory.newThread(w);&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>if&nbsp;(t&nbsp;!=&nbsp;null)&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;w.thread&nbsp;=&nbsp;t;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;workers.add(w);&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>int&nbsp;nt&nbsp;=&nbsp;++poolSize;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>if&nbsp;(nt&nbsp;&gt;&nbsp;largestPoolSize)&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;largestPoolSize&nbsp;=&nbsp;nt;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>return&nbsp;t;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;..........&nbsp;&nbsp;</li><li>}&nbsp;&nbsp;</li></ol></div> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这里两个重点，很明显： <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1、Worker w = new Worker(firstTask) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2、Thread t = threadFactory.newThread(w) <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 先看Worker是个什么结构： <br /><div id=""><div><div>Java代码 &nbsp;<a title="收藏这段代码"><img src="http://paddy-w.iteye.com/images/icon_star.png" alt="收藏代码" /></a></div></div><ol start="1"><li><span>public&nbsp;class&nbsp;ThreadPoolExecutor&nbsp;extends&nbsp;AbstractExecutorService&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;..........&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>private&nbsp;final&nbsp;class&nbsp;Worker&nbsp;implements&nbsp;Runnable&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;..........&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Worker(Runnable&nbsp;firstTask)&nbsp;{&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>this.firstTask&nbsp;=&nbsp;firstTask;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>private&nbsp;Runnable&nbsp;firstTask;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;..........&nbsp;&nbsp;</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>public&nbsp;void&nbsp;run()&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>try&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Runnable&nbsp;task&nbsp;=&nbsp;firstTask;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;firstTask&nbsp;=&nbsp;<span>null;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>while&nbsp;(task&nbsp;!=&nbsp;null&nbsp;||&nbsp;(task&nbsp;=&nbsp;getTask())&nbsp;!=&nbsp;null)&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;runTask(task);&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;task&nbsp;=&nbsp;<span>null;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span>finally&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;workerDone(<span>this);&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;Runnable&nbsp;getTask()&nbsp;{&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>for&nbsp;(;;)&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>try&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>int&nbsp;state&nbsp;=&nbsp;runState;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>if&nbsp;(state&nbsp;&gt;&nbsp;SHUTDOWN)&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>return&nbsp;null;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Runnable&nbsp;r;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>if&nbsp;(state&nbsp;==&nbsp;SHUTDOWN)&nbsp;&nbsp;//&nbsp;Help&nbsp;drain&nbsp;queue&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r&nbsp;=&nbsp;workQueue.poll();&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>else&nbsp;if&nbsp;(poolSize&nbsp;&gt;&nbsp;corePoolSize&nbsp;||&nbsp;allowCoreThreadTimeOut)&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r&nbsp;=&nbsp;workQueue.poll(keepAliveTime,&nbsp;TimeUnit.NANOSECONDS);&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>else&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r&nbsp;=&nbsp;workQueue.take();&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>if&nbsp;(r&nbsp;!=&nbsp;null)&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>return&nbsp;r;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>if&nbsp;(workerCanExit())&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>if&nbsp;(runState&nbsp;&gt;=&nbsp;SHUTDOWN)&nbsp;//&nbsp;Wake&nbsp;up&nbsp;others&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;interruptIdleWorkers();&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>return&nbsp;null;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>//&nbsp;Else&nbsp;retry&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span>catch&nbsp;(InterruptedException&nbsp;ie)&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>//&nbsp;On&nbsp;interruption,&nbsp;re-check&nbsp;runState&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;..........&nbsp;&nbsp;</li><li>}&nbsp;&nbsp;</li></ol></div> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Worker是一个内部类。根据之前可以知道，传入addThread的参数是null，也就是说Work中firstTask为null。 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在看看newThread是一个什么方法： <br /><div id=""><div><div>Java代码 &nbsp;<a title="收藏这段代码"><img src="http://paddy-w.iteye.com/images/icon_star.png" alt="收藏代码" /></a></div></div><ol start="1"><li><span>public&nbsp;class&nbsp;Executors&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;..........&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>static&nbsp;class&nbsp;DefaultThreadFactory&nbsp;implements&nbsp;ThreadFactory&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;..........&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>public&nbsp;Thread&nbsp;newThread(Runnable&nbsp;r)&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Thread&nbsp;t&nbsp;=&nbsp;<span>new&nbsp;Thread(group,&nbsp;r,&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;namePrefix&nbsp;+&nbsp;threadNumber.getAndIncrement(),&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>0);&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>if&nbsp;(t.isDaemon())&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.setDaemon(<span>false);&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>if&nbsp;(t.getPriority()&nbsp;!=&nbsp;Thread.NORM_PRIORITY)&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t.setPriority(Thread.NORM_PRIORITY);&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>return&nbsp;t;&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;..........&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;..........&nbsp;&nbsp;</li><li>}&nbsp;&nbsp;</li></ol></div> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 通过源码可以得知threadFactory的实际类型是DefaultThreadFactory，而DefaultThreadFactory是Executors的一个嵌套内部类。 <br /> <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  之前我们提到了t.start()这个方法执行了线程。那么现在从头顺一下，看看到底是执行了谁的run方法。首先知 道，t=addThread(null)，而addThread内部执行了下面三步，Worker w = new  Worker(null);Thread t = threadFactory.newThread(w);return t;这里两个t是一致的。 <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  从这里可以看出，t.start()实际上执行的是Worker内部的run方法。run()内部会在if条件里面使用&#8220;短路&#8221;：判断firstTask 是否为null，若不是null则直接执行firstTask的run方法；如果是null，则调用getTask()方法来获取Runnable类型实 例。从哪里获取呢？workQueue！在execute方法中，执行ensureQueuedTaskHandled(command)之前就已经把 Runnable类型实例放入到workQueue中了，所以这里可以从workQueue中获取到。<br /><br />转自:<div>http://paddy-w.iteye.com/blog/1039530</div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/194106.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-10-30 21:56 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/10/30/194106.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>移动环境下push技术开发（01-androidpn环境的配置） ( 转 )</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/09/27/192158.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Thu, 27 Sep 2012 02:54:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/09/27/192158.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/192158.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/09/27/192158.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/192158.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/192158.html</trackback:ping><description><![CDATA[<div><p><span style="font-size: 12px; font-family: verdana,geneva;"><span style="font-size: 14px;"><strong>转自:</strong></span></span><strong> http://www.189works.com/article-58560-1.html</strong></p><strong><br /></strong><p>&nbsp;</p><p><span style="font-size: 12px; font-family: verdana,geneva;"><span style="font-size: 14px;"><strong>一、缘由</strong></span> <br /><br />其实说白了就是研究<a href="http://bbs.189works.com/" target="_blank">android</a>pn这个开源项目，只因我的本科毕业设计的题目就是&#8220;移动环境下push技术开发&#8221;，所以起这个作为本篇博文的题目。其实我本来是想等我的毕业设计答辩结束后，再总结，再分享的，可是最近群里很多人整个环境都不会配，所以我就先写一篇环境的配置吧。<br /><br />当然我起初也是在各位前辈的基础上学习的，关于androidpn网上的资料还是很多的，大家自己看。这里只贴出两个我认为比较好的链接：<br />Android推送通知指南：<a href="http://blog.csdn.net/joshua_yu/article/details/6563587" target="_blank">http://blog.csdn.net/joshua_yu/article/details/6563587</a><br />用androidpn来实现推送（Jclick）：<a href="http://www.iteye.com/topic/1117043?page=13" target="_blank">http://www.iteye.com/topic/1117043?page=13</a><br /><br />刚开始的时候，我就是用的Jclick修改后的tomcat版本，在这个基础上一点一点的修改的，我的</span><span style="font-size: 12px; color: #3366ff;"><a title="更新日志" href="http://www.cnblogs.com/dzchen/archive/2012/04/30/2477104.html" target="_blank"><span style="color: #3366ff;">更新日志</span></a></span><span style="font-size: 12px; font-family: verdana,geneva;">，后来交流的人多了，我就建了一个QQ群（210555217），群共享里面有各种版本（有用JSON的、有用SSH的、以及增加离线消息和回执功能的等等）。我今天就拿小强共享的版本来说明。可以在群共享下载，也可以在本文后面的链接下载。<br /><br /><br /><span style="font-size: 14px;"><strong>二、Windows下androidpn环境的配置</strong></span><br /><br />在配置之前，请关闭或者删除你工作空间里面跟androidpn相关的其他工程。严格按照下面步骤来搞，否则你出现问题，我也不知道怎么处理的。<br /><br /><strong>2.1、客户端配置</strong><br /><br />把 解压后的的&#8220;androidpn-client&#8221;导入Eclipse，导入后整个工程的目录如下，然后打开 &#8220;androidpn.properties&#8221;，修改&#8220;xmppHost&#8221;，如果你是用模拟器测试的话，改成&#8220;10.0.2.2&#8221;，如果是真机测试的话改 成你的电脑的IP。</span></p><p><img src="http://www.189works.com/data/attachment/portal/et2/201205/ET29821020728131.png" alt="" /></p><p><span style="font-size: 12px; font-family: verdana,geneva;"><br /><strong>2.2、服务器端的配置</strong><br /><br />首先在MyEclispe里面配置Tomcat，到apache官网下个纯的tomcat，不要是什么和apache整合的，就单单是tomcat。然后在本地磁盘解压。把tomcat集成到MyEclipse。按照下图操作。</span></p><p><img src="http://www.189works.com/data/attachment/portal/et2/201205/ET29821020728132.png" alt="" /></p><p><span style="font-size: 12px; font-family: verdana,geneva;"><br />然后在Server视图里面启动Tomcat。<br /></span></p><p><img src="http://www.189works.com/data/attachment/portal/et2/201205/ET29821020728133.png" alt="" /></p><p><span style="font-size: 12px; font-family: verdana,geneva;"><br />看启动日志。<br /></span></p><p><img src="http://www.189works.com/data/attachment/portal/et2/201205/ET29821020728134.png" alt="" /><span style="font-size: 12px; font-family: verdana,geneva;"><br /><br />启动成功后，打来浏览器，输入：http://localhost:8080/， 如果出现Tomcat的主页，就说明的tomcat配置成功了。然后关闭Tomcat。<br /><br />把解压后的服务器端代码（Androidpn）导入MyEclipse。导入后的项目结构如下图所示。在数据库里面新建一个名为&#8220;android&#8221;的数据库，再修改jdbc.properties这个文件，关键是红框标记的几处，改成你的MySql对应的值。<br /></span></p><p><img src="http://www.189works.com/data/attachment/portal/et2/201205/ET29821020728135.png" alt="" /></p><p>&nbsp;</p><p><span style="font-size: 12px; font-family: verdana,geneva;"><span style="font-size: 12px; font-family: verdana,geneva;">如果你不是用的MySql，就用相应的数据库jar包替换mysql的jar包，然后再修改jdbc.properties。其他数据库对应的写法如下。</span><br />------SQL Server 2005------<br /># JDBC Configuration<br />jdbcDriverClassName=com.microsoft.jdbc.sqlserver.SQLServerDriver<br />jdbcUrl=jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=android<br />hibernate.dialect=org.hibernate.dialect.SQLServerDialect <br />jdbcUsername=sa<br />jdbcPassword=sql<br /><br />------SQL Server 2008------<br />jdbcDriverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver<br />jdbcUrl=jdbc:sqlserver://localhost:1433;DatabaseName=android;integratedSecurity=false<br />hibernate.dialect=org.hibernate.dialect.SQLServerDialect <br />jdbcUsername=sa<br />jdbcPassword=sql<br /><br />修改好了之后，部署到Tomcat上，部署的过程中注意下图的选择。之后启动Tomcat，然后在浏览器里面输入：http://localhost:8080/Androidpn，正常情况下是可以出现Androidpn的首页。<br /></span></p><p><img src="http://www.189works.com/data/attachment/portal/et2/201205/ET29821020728136.png" alt="" /><span style="font-size: 12px; font-family: verdana,geneva;"><br /></span></p><p>&nbsp;</p><p>&nbsp;</p><p><span style="font-size: 12px; font-family: verdana,geneva;"><span style="font-size: 14px;"><strong>三、测试</strong></span> <br /><br />在模拟器或真机上运行客户端程序，会出现下图的界面。<br /></span></p><p><img src="http://www.189works.com/data/attachment/portal/et2/201205/ET29821020728137.png" alt="" /></p><p>&nbsp;</p><p><span style="font-size: 12px; font-family: verdana,geneva;"><span style="font-size: 12px; font-family: verdana,geneva;">同时MyEclipse的控制台会打印很多log。</span><br /></span></p><p><img src="http://www.189works.com/data/attachment/portal/et2/201205/ET29821020728138.png" alt="" /></p><p><span style="font-size: 12px; font-family: verdana,geneva;"><br />过一会服务器的Web页面的Users列表和Sessions列表里面都会出现你的记录。<br /></span></p><p><img src="http://www.189works.com/data/attachment/portal/et2/201205/ET29821020728139.png" alt="" /></p><p><img src="http://www.189works.com/data/attachment/portal/et2/201205/ET298210207281310.png" alt="" /><span style="font-size: 12px; font-family: verdana,geneva;"><br /><br /></span></p><p><span style="font-size: 12px; font-family: verdana,geneva;"><span style="font-size: 12px; font-family: verdana,geneva;">然后你就可以推送了。</span><br /></span></p><p><img src="http://www.189works.com/data/attachment/portal/et2/201205/ET298210207281311.png" alt="" /></p><p>&nbsp;</p><p><span style="font-size: 12px; font-family: verdana,geneva;">客户端收到信息后的显示界面如下。</span></p><p><img src="http://www.189works.com/data/attachment/portal/et2/201205/ET298210207281312.png" alt="" /></p><p><span style="font-size: 12px; font-family: verdana,geneva;"><br /><br /><span style="font-size: 14px;"><strong>四、Linux下androidpn环境的配置</strong></span><br /><br />其实和上述的步骤一样，只是你把上述的Tomcat根目录下的webapps目录下的&#8220;Androidpn.war&#8221;拷贝到Linux下面的Tomcat的对应目录即可，至于Linux下怎么配置java以及tomcat的环境，请自己网上搜索。<br /><br />项目放好之后，到tomcat的bin目录下，运行：<strong>./startup.sh</strong> 来启动tomcat，启动之后，运行：<strong>netstat -antupl </strong>看下图的端口是否处于监听状态。<br /></span></p><p><img src="http://www.189works.com/data/attachment/portal/et2/201205/ET298210207281313.png" alt="" /><span style="font-size: 12px; font-family: verdana,geneva;"><br /><br />如果是的话，现在你就可以启动客户端了。<br /><br />要看tomcat的log的话，进入tomcat的logs目录运行：<strong>tail -f ./catalina.out</strong><br /><br />好了，如果你按照上述的步骤还是不行的话，加入<span style="font-size: 12px; font-family: verdana,geneva;">QQ群（210555217）</span>提问，或者在<a href="http://phonepush.sinaapp.com/" target="_blank">http://phonepush.sinaapp.com/</a>这个论坛提问。</span></p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/192158.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-09-27 10:54 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/09/27/192158.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>android 4.0 以上平台选择图片报错Attempted to access a cursor after it has been closed. </title><link>http://www.cppblog.com/guojingjia2006/archive/2012/08/31/188901.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Fri, 31 Aug 2012 07:16:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/08/31/188901.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/188901.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/08/31/188901.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/188901.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/188901.html</trackback:ping><description><![CDATA[<div><p><span style="font-size:14px; font-family:'lucida Grande',Verdana">选择图片后 onActivityResult中的代码如下：</span></p> <p><span style="font-family:'lucida Grande',Verdana"></span></p> <div bg_java"=""><div>&nbsp;Uri uri = data.getData();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (uri != null)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mFilePath = new URIUtils().getPathFromUri(uri);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br /></div></div> 解决办法如注释中的所示。 4.0以上平台会自动关闭cursor  <span style="font-family:lucida Grande,Verdana"></span><br /><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all;"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff; font-family: Courier;">protected</span><span style="color: #000000; font-family: Courier;">&nbsp;String&nbsp;getPath(Uri&nbsp;uri)<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;filePath&nbsp;</span><span style="color: #000000; font-family: Courier;">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-family: Courier;">""</span><span style="color: #000000; font-family: Courier;">;<br /><br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String[]&nbsp;projection&nbsp;</span><span style="color: #000000; font-family: Courier;">=</span><span style="color: #000000; font-family: Courier;">&nbsp;{MediaColumns.DATA&nbsp;};<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cursor&nbsp;cursor&nbsp;</span><span style="color: #000000; font-family: Courier;">=</span><span style="color: #000000; font-family: Courier;">&nbsp;managedQuery(uri,<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;projection,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Courier;">null</span><span style="color: #000000; font-family: Courier;">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Courier;">null</span><span style="color: #000000; font-family: Courier;">,<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Courier;">null</span><span style="color: #000000; font-family: Courier;">);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Courier;">if</span><span style="color: #000000; font-family: Courier;">&nbsp;(cursor&nbsp;</span><span style="color: #000000; font-family: Courier;">!=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000ff; font-family: Courier;">null</span><span style="color: #000000; font-family: Courier;">)<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Courier;">int</span><span style="color: #000000; font-family: Courier;">&nbsp;columnIndex&nbsp;</span><span style="color: #000000; font-family: Courier;">=</span><span style="color: #000000; font-family: Courier;">&nbsp;cursor.getColumnIndexOrThrow(MediaColumns.DATA);<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cursor.moveToFirst();<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filePath&nbsp;</span><span style="color: #000000; font-family: Courier;">=</span><span style="color: #000000; font-family: Courier;">&nbsp;cursor.getString(columnIndex);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Courier;">try</span><span style="color: #000000; "><br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; font-family: Courier;">//</span><span style="color: #008000; font-family: Courier;">4.0以上的版本会自动关闭&nbsp;(4.0--14;;&nbsp;4.0.3--15)</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Courier;">if</span><span style="color: #000000; font-family: Courier;">(Integer.parseInt(Build.VERSION.SDK)&nbsp;</span><span style="color: #000000; font-family: Courier;">&lt;</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-family: Courier;">14</span><span style="color: #000000; font-family: Courier;">)<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cursor.close();<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000ff; font-family: Courier;">catch</span><span style="color: #000000; font-family: Courier;">(Exception&nbsp;e)<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Log.error(TAG,&nbsp;</span><span style="color: #000000; font-family: Courier;">"</span><span style="color: #000000; font-family: Courier;">error:</span><span style="color: #000000; font-family: Courier;">"</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; font-family: Courier;">+</span><span style="color: #000000; font-family: Courier;">&nbsp;e);<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff; font-family: Courier;">return</span><span style="color: #000000; font-family: Courier;">&nbsp;filePath;<br /></span><span style="color: #000000; font-family: Courier;">&nbsp;&nbsp;&nbsp;&nbsp;}</span></div><br /> </div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/188901.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-08-31 15:16 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/08/31/188901.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MeasureSpec </title><link>http://www.cppblog.com/guojingjia2006/archive/2012/07/03/181288.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Tue, 03 Jul 2012 11:12:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/07/03/181288.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/181288.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/07/03/181288.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/181288.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/181288.html</trackback:ping><description><![CDATA[<div><div id="sina_keyword_ad_area2"  "=""> 			<div> <div>android的布局分两个阶段，先measure()后requestLayout(),</div> <div> 一个MeasureSpec封装了父布局传给子布局的布局要求。每个MeasureSpec代表了一个宽度或高度的要求。一个MeasureSpec包含一个尺寸和模式。</div> <div>MeasureSpec的三种模式：</div> <div>UNSPECIFIED：父布局没有给子布局任何限制，子布局可以任意大小。</div> <div>EXACTLY：父布局决定子布局的确切大小。不论子布局多大，它都必须限制在这个界限里。</div> <div>AT_MOST：子布局可以根据自己的大小选择任意大小。</div> <div>@Override</div> <div>protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {</div> <div>int measuredHeight = measureHeight(heightMeasureSpec);</div> <div>int measuredWidth = measureWidth(widthMeasureSpec);</div> <div>setMeasuredDimension(measuredHeight, measuredWidth);</div> <div>//final DisplayMetrics metrics = getResources().getDisplayMetrics();</div> <div> //setMeasuredDimension(mBitmap.getScaledWidth(metrics),mBitmap.getScaledHeight(metrics));</div> <div>}</div> <div>private int measureHeight(int measureSpec) {</div> <div>int specMode = MeasureSpec.getMode(measureSpec);</div> <div>int specSize = MeasureSpec.getSize(measureSpec);</div> <div>int result = 500;</div> <div>if (specMode == MeasureSpec.AT_MOST)</div> <div>{</div> <div>result = specSize;</div> <div>}</div> <div>else if (specMode == MeasureSpec.EXACTLY)</div> <div>{</div> <div>result = specSize;</div> <div>}</div> <div>return result;</div> <div>}</div> <div>private int measureWidth(int measureSpec) {</div> <div>int specMode = MeasureSpec.getMode(measureSpec);</div> <div>int specSize = MeasureSpec.getSize(measureSpec);</div> <div>int result = 500;</div> <div>if (specMode == MeasureSpec.AT_MOST)</div> <div>{</div> <div>result = specSize;</div> <div>}</div> <div>else if (specMode == MeasureSpec.EXACTLY)</div> <div>{</div> <div>result = specSize;</div> <div>}</div> <div>return result;</div> <div>}</div> <div>Creation</div> <div>Constructors</div> <div>onFinishInflate() 当View和它的所有子对象从XML中导入之后，调用此方法</div> <div>Layout</div> <div>onMeasure(int, int) View会调用此方法，来确认自己及所有子对象的大小</div> <div>onLayout(boolean, int, int, int, int, int, int) 当View要为所有子对象分配大小和位置时，调用此方法</div> <div>onSizeChanged(int, int, int, int) 当View大小改变时，调用此方法</div> <div>Drawing</div> <div>onDraw(Canvas) 当View要绘制它的内容时，调用此方法</div> <div>Event processing</div> <div>onKeyDown(int, KeyEvent) 当一个新的按键事件发生时，调用此方法</div> <div>onKeyUp(int, KeyEvent) 当一个按键释放事件发生时，调用此方法</div> <div>onMotionEvent(MotionEvent) 当一个动作事件（如触摸）发生时，调用此方法</div> <div>Focus</div> <div>onFocusChanged(boolean, int) 当View获得或失去焦点时，调用此方法</div> <div>Attaching</div> <div>onAttachedToWindow() 当View附加到一个窗体上时，调用此方法</div> <div>onDetachedFromWindow() 当View离开它的窗体时，调用此方法</div> <div>当你为一个 activty 添加一个可见的 view, 并且运行这个activty时,android通常情况下会自动按照下列顺序来触发view的相关事件</div> <div>onAttachedToWindow</div> <div>onMeasure</div> <div>onSizeChanged</div> <div>onLayout</div> <div>onDraw<br /></div> </div>							 		</div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/181288.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-07-03 19:12 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/07/03/181288.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>广播接收器 broadcast sendOrderedBroadcast android </title><link>http://www.cppblog.com/guojingjia2006/archive/2012/06/07/177984.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Thu, 07 Jun 2012 15:09:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/06/07/177984.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/177984.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/06/07/177984.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/177984.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/177984.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 广播接收器： &nbsp; 广播接收者(BroadcastReceiver)用于监听系统事件或应用程序事件，通过调用Context.sendBroadcast()、Context.sendOrderedBroadcast()可以向系统发送广播意图，通过广播一个意图（Intent）可以被多个广播接收者所接收，从而可以在不用修改原始的应用程序的情况下，让你对事件作出反应。 &nbsp;&nbsp;&n...&nbsp;&nbsp;<a href='http://www.cppblog.com/guojingjia2006/archive/2012/06/07/177984.html'>阅读全文</a><img src ="http://www.cppblog.com/guojingjia2006/aggbug/177984.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-06-07 23:09 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/06/07/177984.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android 自动接听来电 </title><link>http://www.cppblog.com/guojingjia2006/archive/2012/06/07/177946.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Thu, 07 Jun 2012 09:20:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/06/07/177946.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/177946.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/06/07/177946.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/177946.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/177946.html</trackback:ping><description><![CDATA[<div><p>网上找到的,HTC One X,三星i9000 cm9 4.0.4测试通过,在此记录一下，大伙需要的话就拿去吧..</p> <p><br /> </p> <p>1. Android 2.3(不包括)以下，通过获取aidl远程服务接口TelephoneyManager来调用它的answerRingingCall方法(ps: 关于此方法具体做法，由于时间关系，我这里就不详细说啦，大家Google一下吧)</p>  <div bg_java"=""><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TelephonyManager&nbsp;tm&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(TelephonyManager)&nbsp;getSystemService(TELEPHONY_SERVICE);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Class&nbsp;c&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;Class.forName(tm.getClass().getName());<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Method&nbsp;m&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;c.getDeclaredMethod(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">getITelephony</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;m.setAccessible(</span><span style="color: #0000FF; ">true</span><span style="color: #000000; ">);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ITelephony&nbsp;telephonyService;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;telephonyService&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(ITelephony)&nbsp;m.invoke(tm);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">&nbsp;Silence&nbsp;the&nbsp;ringer&nbsp;and&nbsp;answer&nbsp;the&nbsp;call!</span><span style="color: #008000; "><br /></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;telephonyService.silenceRinger();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;telephonyService.answerRingingCall();</span></div></div><br /> <br />  <p><br /> </p> <p>2. Android  2.3(包括)以上，如果照样使用TelephoneyManager获取到的answerRingingCall方法的话，就会抛没有 android.permission.MODIFY_PHONE_STATE权限异常，其实你已经配了这个权限的了，但是不好意思，你的App不是系统 软件，没有系统签名，所以还是不能调用，除非，你root了你的手机，把你的app装到系统软件里面去，所以这里使用另外一种方法实现自动接听这个行为 了，详细如下:</p> <p>刚开始我用这段代码的，发现三星机型可以，但HTC(如: G10 , One X)不行，</p> <div bg_java"=""><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">&nbsp;Intent&nbsp;intent&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Intent(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">android.intent.action.MEDIA_BUTTON</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />&nbsp;KeyEvent&nbsp;keyEvent&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;KeyEvent(KeyEvent.ACTION_DOWN,&nbsp;&nbsp;KeyEvent.KEYCODE_HEADSETHOOK);<br />&nbsp;intent.putExtra(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">android.intent.extra.KEY_EVENT</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,keyEvent);<br />&nbsp;sendOrderedBroadcast(intent,</span><span style="color: #000000; ">"</span><span style="color: #000000; ">android.permission.CALL_PRIVILEGED</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />&nbsp;intent&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;&nbsp;Intent(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">android.intent.action.MEDIA_BUTTON</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />&nbsp;keyEvent&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;KeyEvent(KeyEvent.ACTION_UP,&nbsp;KeyEvent.KEYCODE_HEADSETHOOK);<br />&nbsp;intent.putExtra(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">android.intent.extra.KEY_EVENT</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,keyEvent);<br />&nbsp;sendOrderedBroadcast(intent,</span><span style="color: #000000; ">"</span><span style="color: #000000; ">android.permission.CALL_PRIVILEGED</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);</span></div></div><br />  <br /> <br />  <p>后来又google到了这段代码，经过测试，完全好使..</p><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">Intent&nbsp;localIntent1&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Intent(Intent.ACTION_HEADSET_PLUG);<br />localIntent1.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);<br />localIntent1.putExtra(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">state</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);<br />localIntent1.putExtra(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">microphone</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);<br />localIntent1.putExtra(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">name</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Headset</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />CallingActivity.</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.sendOrderedBroadcast(localIntent1,</span><span style="color: #000000; ">"</span><span style="color: #000000; ">android.permission.CALL_PRIVILEGED</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br /><br />Intent&nbsp;localIntent2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Intent(Intent.ACTION_MEDIA_BUTTON);<br />KeyEvent&nbsp;localKeyEvent1&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;KeyEvent(KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_HEADSETHOOK);<br />localIntent2.putExtra(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">android.intent.extra.KEY_EVENT</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,localKeyEvent1);<br />CallingActivity.</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.sendOrderedBroadcast(localIntent2,</span><span style="color: #000000; ">"</span><span style="color: #000000; ">android.permission.CALL_PRIVILEGED</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br /><br />Intent&nbsp;localIntent3&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Intent(Intent.ACTION_MEDIA_BUTTON);<br />KeyEvent&nbsp;localKeyEvent2&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;KeyEvent(KeyEvent.ACTION_UP,KeyEvent.KEYCODE_HEADSETHOOK);<br />localIntent3.putExtra(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">android.intent.extra.KEY_EVENT</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,localKeyEvent2);<br />CallingActivity.</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.sendOrderedBroadcast(localIntent3,</span><span style="color: #000000; ">"</span><span style="color: #000000; ">android.permission.CALL_PRIVILEGED</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br /><br />Intent&nbsp;localIntent4&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;Intent(Intent.ACTION_HEADSET_PLUG);<br />localIntent4.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);<br />localIntent4.putExtra(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">state</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">);<br />localIntent4.putExtra(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">microphone</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">);<br />localIntent4.putExtra(</span><span style="color: #000000; ">"</span><span style="color: #000000; ">name</span><span style="color: #000000; ">"</span><span style="color: #000000; ">,&nbsp;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">Headset</span><span style="color: #000000; ">"</span><span style="color: #000000; ">);<br />CallingActivity.</span><span style="color: #0000FF; ">this</span><span style="color: #000000; ">.sendOrderedBroadcast(localIntent4,</span><span style="color: #000000; ">"</span><span style="color: #000000; ">android.permission.CALL_PRIVILEGED</span><span style="color: #000000; ">"</span><span style="color: #000000;">);</span></div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/177946.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-06-07 17:20 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/06/07/177946.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>android apk 反破解 (转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/05/24/176040.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Thu, 24 May 2012 09:12:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/05/24/176040.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/176040.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/05/24/176040.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/176040.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/176040.html</trackback:ping><description><![CDATA[<div>由于Android安装包APK文件仅仅是一个简单的zip包，导致了APK文件很容易被反编译。这不仅威胁到软件开发公司及程序开发人员的知识产权，而且成为了恶意程序滋生的温床。<br /> <br /> &nbsp;&nbsp;&nbsp;&nbsp;那么如何增加APK被破解的难度，保障APK程序的安全性呢？这段时间里，我总结了一些技术上可行的方法。它们包括如下几篇文章。<br /> <br /> <a href="http://bbs.pediy.com/showthread.php?t=137112" target="_blank">&nbsp;《APK反破解之一：Android&nbsp;Java混淆(ProGuard)》&nbsp;</a><br /> <a href="http://bbs.pediy.com/showthread.php?t=137500" target="_blank">&nbsp;《APK反破解之二：Android&nbsp;APK&nbsp;签名比对》&nbsp;</a><br /> <a href="http://bbs.pediy.com/showthread.php?t=141960" target="_blank">&nbsp;《APK反破解之三：NDK编译.so动态库》&nbsp;</a><br /> <a href="http://bbs.pediy.com/showthread.php?t=142256" target="_blank">&nbsp;《APK反破解之四：Android代码动态加载技术》&nbsp;</a><br /> <br /> &nbsp;&nbsp;&nbsp;&nbsp;为了方便大家查找，特意在这里做个小结，将连接整理在此，方便大家阅读。之所以将这几篇文章的整理称为&#8220;小结&#8221;，是因为这远远算不上&#8220;总结&#8221;。希望大家多多交流，随时留言发表自己的想法，多多补充、指正。谢谢了！<br /> <br /> &nbsp;&nbsp;&nbsp;&nbsp;Android代表了移动互联网时代的兴起，它将广泛运行在各种移动终端之上。有机构数据预测，移动互联网时代的终端数量将是PC时代终端设备数 量的10倍以上。并且移动终端本身的特点决定了它比PC更为私有化。因此它的安全性、隐私保护性将比PC时代的安全和隐私保护更为受到用户、媒体和机构的 关注。<br /> <br /> &nbsp;&nbsp;&nbsp;&nbsp;Android这个可爱的小绿人从出生到现在，满打满算也只有三周岁而已。它的安全领域存在着太多的空白等着我们去开拓和填补。这既是挑战，也是 机遇。希望大家能借看雪论坛Android软件安全板块这个平台，多多交流，相互学习，共同迎接移动互联网软件安全的春天！ 			</div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/176040.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-05-24 17:12 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/05/24/176040.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sqlite 数据库升级</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/05/09/174066.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Wed, 09 May 2012 02:55:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/05/09/174066.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/174066.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/05/09/174066.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/174066.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/174066.html</trackback:ping><description><![CDATA[<div>做Android应用，不可避免的会与SQLite打交道。随着应用的不断升级，原有的数据库结构可能已经不再适应新的功能，这时候，就需要对SQLite数据库的结构进行升级了。<p>　　SQLite提供了ALTER TABLE命令，允许用户重命名或添加新的字段到已有表中，但是不能从表中删除字段。</p><p>　　并且只能在表的末尾添加字段，比如,为 Subscription添加两个字段：　　　　</p><div><pre><span style="color: #008080;">1</span> <span style="color: #0000ff;">ALTER</span> <span style="color: #0000ff;">TABLE</span> Subscription <span style="color: #0000ff;">ADD</span> <span style="color: #0000ff;">COLUMN</span> Activation BLOB;<br /><span style="color: #008080;">2</span> <span style="color: #0000ff;">ALTER</span> <span style="color: #0000ff;">TABLE</span> Subscription <span style="color: #0000ff;">ADD</span> <span style="color: #0000ff;">COLUMN</span> <span style="color: #0000ff;">Key</span> BLOB;</pre></div><p>　　另外，如果遇到复杂的修改操作，比如在修改的同时，需要进行数据的转移，那么可以采取在一个事务中执行如下语句来实现修改表的需求。</p><p>　　1.&nbsp;将表名改为临时表</p><div><pre><span style="color: #0000ff;">ALTER</span> <span style="color: #0000ff;">TABLE</span> Subscription RENAME <span style="color: #0000ff;">TO</span> __temp__Subscription;</pre></div><p>　　2.&nbsp;创建新表</p><div><pre><span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">TABLE</span> Subscription (OrderId <span style="color: #0000ff;">VARCHAR</span>(<span style="color: #800000; font-weight: bold;">32</span>) <span style="color: #0000ff;">PRIMARY</span> <span style="color: #0000ff;">KEY</span> ,UserName <span style="color: #0000ff;">VARCHAR</span>(<span style="color: #800000; font-weight: bold;">32</span>) <span style="color: #808080;">NOT</span> <span style="color: #0000ff;">NULL</span> ,ProductId <span style="color: #0000ff;">VARCHAR</span>(<span style="color: #800000; font-weight: bold;">16</span>) <span style="color: #808080;">NOT</span> <span style="color: #0000ff;">NULL</span>);</pre></div><p>　　3.&nbsp;导入数据　　</p><div><pre><span style="color: #0000ff;">INSERT</span> <span style="color: #0000ff;">INTO</span> Subscription <span style="color: #0000ff;">SELECT</span> OrderId, &#8220;&#8221;, ProductId <span style="color: #0000ff;">FROM</span> __temp__Subscription;</pre></div><p>　　或者　　</p><div><pre><span style="color: #0000ff;">INSERT</span> <span style="color: #0000ff;">INTO</span> Subscription() <span style="color: #0000ff;">SELECT</span> OrderId, &#8220;&#8221;, ProductId <span style="color: #0000ff;">FROM</span> __temp__Subscription;</pre></div><p>　　<span style="background-color: #ccffcc;"><span style="color: #ff0000;">*</span>&nbsp;注意 双引号&#8221;&#8221; 是用来补充原来不存在的数据的</span><br />　　4.&nbsp;删除临时表　　</p><div><pre><span style="color: #0000ff;">DROP</span> <span style="color: #0000ff;">TABLE</span> __temp__Subscription;</pre></div><p>　　通过以上四个步骤，就可以完成旧数据库结构向新数据库结构的迁移，并且其中还可以保证数据不会应为升级而流失。</p><p>　　当然，如果遇到减少字段的情况，也可以通过创建临时表的方式来实现。</p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/174066.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-05-09 10:55 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/05/09/174066.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>收集的网络上大型的开源图像处理软件代码（提供下载链接)</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/05/08/173996.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Tue, 08 May 2012 08:25:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/05/08/173996.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/173996.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/05/08/173996.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/173996.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/173996.html</trackback:ping><description><![CDATA[<div><div id="content_art">                         <span style="color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">要 写好一个图像处理软件，仅靠自己看书是完全不够的，要多方面学习，借鉴前人的经验，要集思广益、多面出击。如今网络发达，图像学的资料其实也到处都是。只 是往往个人能力或精力有限，在短时间内无法找到那些也许藏于角落里的金子。本人研究图像至今也历时7年，在慢慢的摸索和累积中也找到了一些相关资料，共享 给大家学习。</span><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">1、 最著名的<a href="http://www.haogongju.net/tag/%E5%BC%80%E6%BA%90" target="_blank" title="开源">开源</a>图像软件：GIMP。</strong></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 开发语言：C</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;GIMP号称Linux下的Phot<a href="http://www.haogongju.net/tag/OS" target="_blank" title="oS">oS</a>hop，总观其工程，确实达到了PhotoShop早期版本的功能。三大利器:选区、图层、蒙板一应俱全，滤镜也非常丰富，支持插件。缺点就是<a href="http://www.haogongju.net/tag/%E7%95%8C%E9%9D%A2" target="_blank" title="界面">界面</a>不美观，<a href="http://www.haogongju.net/tag/%E7%94%A8%E6%88%B7%E4%BD%93%E9%AA%8C" target="_blank" title="用户体验">用户体验</a>差，执行速度在Windows下慢(Linux下不清楚)。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 官方<a href="http://www.haogongju.net/tag/%E7%BD%91%E5%9D%80" target="_blank" title="网址">网址</a>为：<a href="http://www.gimp.org/" target="_blank" rel="nofollow">http://www.gimp.org/</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 源码下载：因其源码体积过大，请大家直接到其官网下载。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对应的可执行文件可在官方<a href="http://www.haogongju.net/tag/%E7%BD%91%E7%AB%99" target="_blank" title="网站">网站</a>下载。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 界面预览：</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><img alt="" src="http://images.cnblogs.com/cnblogs_com/imageshop/334232/o_GimpPreview.jpg" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-style: initial; border-color: initial; " border="0" height="640" width="1049" /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">2、 <a href="http://www.haogongju.net/tag/%E5%BE%AE%E8%BD%AF" target="_blank" title="微软">微软</a>曾支持过的"开源"图像软件：Paint<a href="http://www.haogongju.net/tag/.NET" target="_blank" title=".NET">.NET</a>。</strong></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 开发语言：C#</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">　　Paint.<a href="http://www.haogongju.net/tag/net" target="_blank" title="NET">NET</a>是Windows 平台上的一个图像和照片处理软件,早期定位于MSPaint的免费替代软件，支持图层、通道、无限制的历史记录、特效和许多实用工具，在3.3版本之前开源，之后由于种种原因放弃开源。其界面看起来有点像Photoshop，执行速度上也不快。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 官方网站：<a href="http://www.getpaint.net/" target="_blank" rel="nofollow">http://www.getpaint.net/</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 源码下载：<a href="http://files.cnblogs.com/Imageshop/Paint.net.rar" target="_blank" rel="nofollow">http://files.cnblogs.com/Imageshop/Paint.net.rar</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 界面预览：</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><img alt="" src="http://images.cnblogs.com/cnblogs_com/imageshop/334232/o_PaintNetPreview.jpg" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-style: initial; border-color: initial; " border="0" height="677" width="966" /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp;3、一个响<a href="http://www.haogongju.net/tag/%E5%BD%93%E5%BD%93" target="_blank" title="当当">当当</a>的图像开源软件：ImageEditor</strong>&nbsp;</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;开发语言：JAVA</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;一个用JAVA开发的图像处理软件，具有图层、选区、滤镜以及其他一些工具。整体来说较上述两个软件稍次一些，但依旧强劲。提供了很多独特的滤镜<a href="http://www.haogongju.net/tag/%E7%AE%97%E6%B3%95" target="_blank" title="算法">算法</a>，工具箱中的透视变形工具很给力，是用JAVA开发图像值得借鉴的好代码。算法的执行速度一般。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;官方网址为：<a href="http://www.jhlabs.com/" target="_blank" rel="nofollow">http://www.jhlabs.com/</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 源码下载：<a href="http://files.cnblogs.com/Imageshop/jhlabs.rar" target="_blank" rel="nofollow">http://files.cnblogs.com/Imageshop/jhlabs.rar</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 源码中包含对应的EXE文件，但需要机器上安装了JAVA运行环境方可正常运行。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 界面预览：</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><img alt="" src="http://images.cnblogs.com/cnblogs_com/imageshop/334232/o_jhlabsPreview.JPG" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-style: initial; border-color: initial; " border="0" /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">4、优秀的图像操作类库: CxImage</strong></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; 开发语言：C++</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;它可以快捷地存取、显示、转换各种图像，自带了较多图像模式转换算法，以及一些滤镜，是<a href="http://www.haogongju.net/tag/VC" target="_blank" title="VC">VC</a>使用者最为常用的图像类库。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; 官方网址：<a href="http://www.codeproject.com/KB/graphics/cximage.aspx" target="_blank" rel="nofollow">http://www.codeproject.com/KB/graphics/cximage.aspx</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; 源码下载：<a href="http://files.cnblogs.com/Imageshop/cximage.rar" target="_blank" rel="nofollow">http://files.cnblogs.com/Imageshop/cximage.rar</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; 界面预览：</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><img alt="" src="http://images.cnblogs.com/cnblogs_com/Imageshop/334232/o_CximagePreview.JPG" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-style: initial; border-color: initial; " border="0" /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">5、国人的开源图像处理软件： Imagestone</strong></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; 开发语言：C++&nbsp;</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;   ImageStone是一套功能强大的C++图像处理库，能读写JPG、GIF、PNG、TIFF、TGA等多种图像文件，有多达100多中预定义的特 效。其算法很多是取自GIMP的代码，如果认为GIMP的代码过于复杂，可以从该软件中很轻松分解出你需要的部分。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;官方网址为：<a href="http://www.codeproject.com/KB/graphics/ImageStone.aspx" target="_blank" rel="nofollow">http://www.codeproject.com/KB/graphics/ImageStone.aspx</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 源码下载：<a href="http://files.cnblogs.com/Imageshop/ImageStone.rar" target="_blank" rel="nofollow">http://files.cnblogs.com/Imageshop/ImageStone.rar</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 界面预览：</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><img alt="" src="http://images.cnblogs.com/cnblogs_com/Imageshop/334232/o_ImageStonePreview.JPG" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-style: initial; border-color: initial; " border="0" height="567" width="962" /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">6、基于AForge.NET的开源软件：iplab</strong></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; 开发语言：C#</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp; 和CxImage似乎是一个作者，包含了很多滤镜，也有一些图像识别上常用的分析方法。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;官方网址为：<a href="http://www.codeproject.com/KB/GDI-plus/Image_Processing_Lab.aspx" target="_blank" rel="nofollow">http://www.codeproject.com/KB/GDI-plus/Image_Processing_Lab.aspx</a>&nbsp;</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;源码下载：<a href="http://www.codeproject.com/KB/GDI-plus/Image_Processing_Lab/iplab_src.zip" target="_blank" rel="nofollow">http://www.codeproject.com/KB/GDI-plus/Image_Processing_Lab/iplab_src.zip</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;界面预览：</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;<img alt="" src="http://images.cnblogs.com/cnblogs_com/imageshop/334232/r_iplab.jpg" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-style: initial; border-color: initial; " border="0" /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">7、一款VB值得爱好者学习的软件：iBmp</strong></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 开发工具：VB6</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 虽然在提供的算法上没有什么太多值得说明的地方，但在图像缩放的坐标计算、偏移、图像<a href="http://www.haogongju.net/tag/%E5%AF%BC%E8%88%AA" target="_blank" title="导航">导航</a>器方面的代码确实值得大家学习。</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 官方网址为：<a href="http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=42376&amp;lngWId=1" target="_blank" rel="nofollow">http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=42376&amp;lngWId=1</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 源码下载：<a href="http://files.cnblogs.com/Imageshop/iBMP.rar" target="_blank" rel="nofollow">http://files.cnblogs.com/Imageshop/iBMP.rar</a></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;界面预览：</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><img alt="" src="http://images.cnblogs.com/cnblogs_com/Imageshop/334232/o_IbmpPreview.JPG" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; border-top-width: 0px; border-right-width: 0px; border-bottom-width: 0px; border-left-width: 0px; border-style: initial; border-color: initial; border-style: initial; border-color: initial; " border="0" /></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;</p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">8、其他的一些开源软件：</strong></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; ">&nbsp;&nbsp;&nbsp; （1） PhotoSprite：<span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-size: 13px; ">一个国产的用C#开发的类似PHOTOSHOP的软件（太抬举他了），用到了很多图形算法，新手可以参考。</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-size: 13px; ">&nbsp;&nbsp;&nbsp;&nbsp; 下载地址：<a href="http://files.cnblogs.com/Imageshop/PhotoSprite.rar" target="_blank" rel="nofollow">http://files.cnblogs.com/Imageshop/PhotoSprite.rar</a></span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-size: 13px; ">&nbsp;&nbsp;&nbsp;&nbsp; （2）FilterExplorer： 一个小的VC写的图像处理代码，有一些比较好的滤镜代码。</span></p><p style="padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #333333; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25px; background-color: #ffffff; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; font-size: 13px; "><span style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">&nbsp;&nbsp;&nbsp;&nbsp; 下载地址：<a href="http://files.cnblogs.com/Imageshop/FilterExplorer.rar" target="_blank" rel="nofollow">http://files.cnblogs.com/Imageshop/FilterExplorer.rar</a></span></span></p>                     </div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/173996.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-05-08 16:25 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/05/08/173996.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ndk</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/05/05/173741.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sat, 05 May 2012 07:02:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/05/05/173741.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/173741.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/05/05/173741.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/173741.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/173741.html</trackback:ping><description><![CDATA[<div>ffmpeg&nbsp; =&gt; http://abitno.me/compile-ffmpeg-android-ndk<br /><div>http://hi.baidu.com/lizhengjun2010/blog/item/08b7fb1b79dc9befe1fe0b09.html</div></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/173741.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-05-05 15:02 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/05/05/173741.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android WebView 文本框获取焦点后自动放大的解决方案</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/04/20/172181.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Fri, 20 Apr 2012 13:34:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/04/20/172181.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/172181.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/04/20/172181.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/172181.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/172181.html</trackback:ping><description><![CDATA[<div><span style="font-size: medium;"><span style="color: #ff0000;">Android WebView 当文本框获取焦点后自动放大，但这种自动放大不是我想要的。</span><span style="color: #999999;">这并不是android的bug，而是他的正常处理</span></span> <p><span style="font-size: medium;">&nbsp; &nbsp; 这是我最近两个星期面临的一个比较棘手的Bug，目前国内外都没有大牛提供很好的解决方式。这里，我今天花了大半天时间来解决这个问题。</span></p> <p>&nbsp;</p> <p>&nbsp; <span style="font-size: medium;">&nbsp; &nbsp;之所以出现这种情况，主要是当文本框获取到焦点后，键盘自动弹出，会执行WebView的</span><span style="direction: ltr; font-size: 10.5pt;"><span style="font-size: medium;">displaySoftKeyboard 方法，这个方法会把缩小的网页恢复到正常情况（也就是说缩小的网页放大），但是我目前的项目都是不允许页面缩放的，所以一旦页面放大后就无法恢复。</span></span><span style="font-size: small;">&nbsp;<span style="direction: ltr;">这里感谢国外的一个朋友的帖子回复</span></span></p> <p><span style="font-size: small;">http://stackoverflow.com/questions/3702805/is-there-a-way-to-disable-the-zoom-feature-on-input-fields-in-webview/7214199#7214199  。</span></p> <p>&nbsp;</p> <p><span style="font-size: large;">不多说，直接上代码，如果想知道原因，看我后续的blog。</span> &lt;!--EndFragment--&gt;</p> &lt;!--EndFragment--&gt; <p>&nbsp;</p> <p><span style="white-space: pre;">	</span><span style="color: #ff0000; font-size: medium;">解决原理：</span></p> <p><span style="color: #ff0000; font-size: medium;"><span style="white-space: pre;">	</span>通过反射，拿到WebView的一个私有属性<span style="direction: ltr;">mDefaultScale，并在WebView失去焦点的时候，修改它的值，已达到网页不放大的效果。</span></span></p> <p>&nbsp;</p> <p><span style="white-space: pre;">	</span></p> <p>&nbsp; &nbsp; <span style="font-size: small;">&nbsp;view.setInitialScale（？？？）； //？？？代表随便多少，小于一百才会有我说的这个bug。</span></p> <p>&nbsp;</p> <p>&nbsp;</p> &lt;!--EndF--&gt; <p><span style="font-size: medium;">&nbsp; &nbsp;</span><span style="direction: ltr;">解决方案如下：</span></p> <p> </p> <div id=""><div><div>Java代码 &nbsp;<a title="收藏这段代码"><img src="http://jiapeng16.iteye.com/images/icon_star.png" alt="收藏代码" /></a></div></div><ol start="1"><li><span>videoNavigation_WV.setOnFocusChangeListener(new&nbsp;View.OnFocusChangeListener()&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>@Override&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;<span>public&nbsp;void&nbsp;onFocusChange(View&nbsp;v,&nbsp;boolean&nbsp;hasFocus)&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>if(hasFocus)&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>try&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Field&nbsp;defaultScale&nbsp;=&nbsp;WebView.<span>class.getDeclaredField("mDefaultScale");&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaultScale.setAccessible(<span>true);&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>//WebViewSettingUtil.getInitScaleValue(VideoNavigationActivity.this,&nbsp;false&nbsp;)/100.0f&nbsp;是我的程序的一个方法，可以用float&nbsp;的scale替代&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;defaultScale.setFloat(videoNavigation_WV&nbsp;,&nbsp;WebViewSettingUtil.getInitScaleValue(VideoNavigationActivity.<span>this,&nbsp;false&nbsp;)/100.0f);&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span>catch&nbsp;(SecurityException&nbsp;e)&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span>catch&nbsp;(IllegalArgumentException&nbsp;e)&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span>catch&nbsp;(IllegalAccessException&nbsp;e)&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;<span>catch&nbsp;(NoSuchFieldException&nbsp;e)&nbsp;{&nbsp;&nbsp;</span></li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</li><li>});&nbsp;&nbsp;</li></ol></div> &nbsp; &lt;!--EndFragmen--&gt; <p>&nbsp; &nbsp; <span style="font-size: medium;">大家如果想利用我这段代码，我这里面的<span style="direction: ltr;">defaultScale.setFloat(WebView,float)， 这个float值是你初始化的时候的scale值。跟你的CSS body值有一定的关系。假如body值 是1920*1080  而你现在是显示在1280*720的屏幕上，那么这个scale  的float值就是0.666667。就是你的现在的缩放页面与正常情况先显示的大小的比（缩放比），大家可以用页面第一次加载的时候通过 getScale()值获取。</span></span></p> <p><span style="font-size: medium;">&nbsp; &nbsp;</span></p> <p><span style="font-size: medium;">&nbsp; &nbsp; 代码还有很多需要优化的地方，比如反射拿属性，其实只要做一次，设置可以做多次，这里只是一个Demo，觉得代码垃圾的话我发个改好的工程给你。</span></p> <p>&nbsp;</p> <p>&nbsp; <span style="background-color: #c0c0c0;"><span style="font-size: small;">&nbsp;有木有做android TV 的 ，加群87154410，欢迎欢迎。 博客刚开始写，希望大家支持。</span></span></p> <p>写都比较简略，大家可以提建议，欢迎留言</p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/172181.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-04-20 21:34 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/04/20/172181.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>android 内存</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/04/19/171954.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Thu, 19 Apr 2012 02:26:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/04/19/171954.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/171954.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/04/19/171954.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/171954.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/171954.html</trackback:ping><description><![CDATA[<div>一、概述 1<br /> 二、Android(Java)中常见的容易引起内存泄漏的不良代码 1<br /> (一) 查询数据库没有关闭游标 2<br /> (二) 构造Adapter时，没有使用缓存的 convertView 3<br /> (三) Bitmap对象不在使用时调用recycle()释放内存 4<br /> (四) 释放对象的引用 4<br /> (五) 其他 5<br /> 三、内存监测工具 DDMS --&gt; Heap 5<br /> 四、内存分析工具 MAT(Memory Analyzer Tool) 7<br /> (一) 生成.hprof文件 7<br /> (二) 使用MAT导入.hprof文件 8<br /> (三) 使用MAT的视图工具分析内存 8<br />  一、概述<br /> &nbsp;&nbsp;Java编程中经常容易被忽视，但本身又十分重要的一个问题就是内存使用的问题。Android应用主要使用Java语言编写，因此这个问题也同样会 在Android开发中出现。本文不对Java编程问题做探讨，而是对于在Android中，特别是应用开发中的此类问题进行整理。<br /> &nbsp;&nbsp;由于作者接触Android时间并不是很长，因此如有叙述不当之处，欢迎指正。<br /> 二、Android(Java)中常见的容易引起内存泄漏的不良代码<br /> &nbsp;&nbsp;Android主要应用在嵌入式设备当中，而嵌入式设备由于一些众所周知的条件限制，通常都不会有很高的配置，特别是内存是比较有限的。如果我们编写 的代码当中有太多的对内存使用不当的地方，难免会使得我们的设备运行缓慢，甚至是死机。为了能够使得Android应用程序安全且快速的运 行，Android的每个应用程序都会使用一个专有的Dalvik虚拟机实例来运行，它是由Zygote服务进程孵化出来的，也就是说每个应用程序都是在 属于自己的进程中运行的。一方面，如果程序在运行过程中出现了内存泄漏的问题，仅仅会使得自己的进程被kill掉，而不会影响其他进程（如果是 system_process等系统进程出问题的话，则会引起系统重启）。另一方面Android为不同类型的进程分配了不同的内存使用上限，如果应用进 程使用的内存超过了这个上限，则会被系统视为内存泄漏，从而被kill掉。Android为应用进程分配的内存上限如下所示：<br /> 位置： /ANDROID_SOURCE/system/core/rootdir/init.rc 部分脚本<br /> # Define the oom_adj values for the classes of processes that can be<br /> # killed by the kernel. These are used in ActivityManagerService.<br /> &nbsp;&nbsp;setprop ro.FOREGROUND_APP_ADJ 0<br /> &nbsp;&nbsp;setprop ro.VISIBLE_APP_ADJ 1<br /> &nbsp;&nbsp;setprop ro.SECONDARY_SERVER_ADJ 2<br /> &nbsp;&nbsp;setprop ro.BACKUP_APP_ADJ 2<br /> &nbsp;&nbsp;setprop ro.HOME_APP_ADJ 4<br /> &nbsp;&nbsp;setprop ro.HIDDEN_APP_MIN_ADJ 7<br /> &nbsp;&nbsp;setprop ro.CONTENT_PROVIDER_ADJ 14<br /> &nbsp;&nbsp;setprop ro.EMPTY_APP_ADJ 15<br /> # Define the memory thresholds at which the above process classes will<br /> # be killed. These numbers are in pages (4k).<br /> &nbsp;&nbsp;setprop ro.FOREGROUND_APP_MEM 1536<br /> &nbsp;&nbsp;setprop ro.VISIBLE_APP_MEM 2048<br /> &nbsp;&nbsp;setprop ro.SECONDARY_SERVER_MEM 4096<br /> &nbsp;&nbsp;setprop ro.BACKUP_APP_MEM 4096<br /> &nbsp;&nbsp;setprop ro.HOME_APP_MEM 4096<br /> &nbsp;&nbsp;setprop ro.HIDDEN_APP_MEM 5120<br /> &nbsp;&nbsp;setprop ro.CONTENT_PROVIDER_MEM 5632<br /> &nbsp;&nbsp;setprop ro.EMPTY_APP_MEM 6144<br /> # Write value must be consistent with the above properties.<br /> # Note that the driver only supports 6 slots, so we have HOME_APP at the<br /> # same memory level as services.<br /> &nbsp;&nbsp;write /sys/module/lowmemorykiller/parameters/adj 0,1,2,7,14,15<br /> &nbsp;&nbsp;write /proc/sys/vm/overcommit_memory 1<br /> &nbsp;&nbsp;write /proc/sys/vm/min_free_order_shift 4<br /> &nbsp;&nbsp;write /sys/module/lowmemorykiller/parameters/minfree 1536,2048,4096,5120,5632,6144<br /> &nbsp;&nbsp;# Set init its forked children's oom_adj.<br /> &nbsp;&nbsp;write /proc/1/oom_adj -16<br /> &nbsp;&nbsp;正因为我们的应用程序能够使用的内存有限，所以在编写代码的时候需要特别注意内存使用问题。如下是一些常见的内存使用不当的情况。<br />  (一) 查询数据库没有关闭游标<br /> 描述：<br /> &nbsp;&nbsp;程序中经常会进行查询数据库的操作，但是经常会有使用完毕Cursor后没有关闭的情况。如果我们的查询结果集比较小，对内存的消耗不容易被发现，只有在常时间大量操作的情况下才会复现内存问题，这样就会给以后的测试和问题排查带来困难和风险。<br />  示例代码：<br /> Cursor cursor = getContentResolver().query(uri ...);<br /> if (cursor.moveToNext()) {<br /> &nbsp;&nbsp;... ...&nbsp;&nbsp;<br /> }<br />  修正示例代码：<br /> Cursor cursor = null;<br /> try {<br /> &nbsp;&nbsp;cursor = getContentResolver().query(uri ...);<br /> &nbsp;&nbsp;if (cursor != null &amp;&amp; cursor.moveToNext()) {<br /> &nbsp;&nbsp;... ...&nbsp;&nbsp;<br /> &nbsp;&nbsp;}<br /> } finally {<br /> &nbsp;&nbsp;if (cursor != null) {<br /> &nbsp;&nbsp;try {&nbsp;&nbsp;<br /> &nbsp;&nbsp;cursor.close();<br /> &nbsp;&nbsp;} catch (Exception e) {<br /> &nbsp;&nbsp;//ignore this<br /> &nbsp;&nbsp;}<br /> &nbsp;&nbsp;}<br /> }&nbsp;&nbsp;<br />  (二) 构造Adapter时，没有使用缓存的 convertView<br /> 描述：<br /> &nbsp;&nbsp;以构造ListView的BaseAdapter为例，在BaseAdapter中提高了方法：<br /> public View getView(int position, View convertView, ViewGroup parent)<br /> 来向ListView提供每一个item所需要的view对象。初始时ListView会从BaseAdapter中根据当前的屏幕布局实例化一定数量的 view对象，同时ListView会将这些view对象缓存起来。当向上滚动ListView时，原先位于最上面的list  item的view对象会被回收，然后被用来构造新出现的最下面的list  item。这个构造过程就是由getView()方法完成的，getView()的第二个形参 View  convertView就是被缓存起来的list item的view对象(初始化时缓存中没有view对象则convertView是null)。<br /> &nbsp;&nbsp;由此可以看出，如果我们不去使用convertView，而是每次都在getView()中重新实例化一个View对象的话，即浪费资源也浪费时间，也会使得内存占用越来越大。ListView回收list item的view对象的过程可以查看:<br /> android.widget.AbsListView.java --&gt; void addScrapView(View scrap) 方法。<br />  示例代码：<br /> public View getView(int position, View convertView, ViewGroup parent) {<br /> &nbsp;&nbsp;View view = new Xxx(...);<br /> &nbsp;&nbsp;... ...<br /> &nbsp;&nbsp;return view;<br /> }<br />  修正示例代码：<br /> public View getView(int position, View convertView, ViewGroup parent) {<br /> &nbsp;&nbsp;View view = null;<br /> &nbsp;&nbsp;if (convertView != null) {<br /> &nbsp;&nbsp;view = convertView;<br /> &nbsp;&nbsp;populate(view, getItem(position));<br /> &nbsp;&nbsp;...<br /> &nbsp;&nbsp;} else {<br /> &nbsp;&nbsp;view = new Xxx(...);<br /> &nbsp;&nbsp;...<br /> &nbsp;&nbsp;}<br /> &nbsp;&nbsp;return view;<br /> }&nbsp;&nbsp;<br />  (三) Bitmap对象不在使用时调用recycle()释放内存<br /> 描述：<br /> &nbsp;&nbsp;有时我们会手工的操作Bitmap对象，如果一个Bitmap对象比较占内存，当它不在被使用的时候，可以调用Bitmap.recycle()方法回收此对象的像素所占用的内存，但这不是必须的，视情况而定。可以看一下代码中的注释：<br /> &nbsp;&nbsp;/**<br /> &nbsp;&nbsp;* Free up the memory associated with this bitmap's pixels, and mark the<br /> &nbsp;&nbsp;* bitmap as "dead", meaning it will throw an exception if getPixels() or<br /> &nbsp;&nbsp;* setPixels() is called, and will draw nothing. This operation cannot be<br /> &nbsp;&nbsp;* reversed, so it should only be called if you are sure there are no<br /> &nbsp;&nbsp;* further uses for the bitmap. This is an advanced call, and normally need<br /> &nbsp;&nbsp;* not be called, since the normal GC process will free up this memory when<br /> &nbsp;&nbsp;* there are no more references to this bitmap.<br /> &nbsp;&nbsp;*/<br /> (四) 释放对象的引用<br /> 描述：<br /> &nbsp;&nbsp;这种情况描述起来比较麻烦，举两个例子进行说明。<br /> 示例A：<br /> 假设有如下操作<br /> public class DemoActivity extends Activity {<br /> &nbsp;&nbsp;... ...<br /> &nbsp;&nbsp;private Handler mHandler = ...<br /> &nbsp;&nbsp;private Object obj;<br /> &nbsp;&nbsp;public void operation() {<br /> &nbsp;&nbsp;obj = initObj();<br /> &nbsp;&nbsp;...<br /> &nbsp;&nbsp;[Mark]<br /> &nbsp;&nbsp;mHandler.post(new Runnable() {<br /> &nbsp;&nbsp;public void run() {<br /> &nbsp;&nbsp;useObj(obj);<br /> &nbsp;&nbsp;}<br /> &nbsp;&nbsp;});<br /> &nbsp;&nbsp;}<br /> }<br /> &nbsp;&nbsp;我们有一个成员变量  obj，在operation()中我们希望能够将处理obj实例的操作post到某个线程的MessageQueue中。在以上的代码中，即便是 mHandler所在的线程使用完了obj所引用的对象，但这个对象仍然不会被垃圾回收掉，因为DemoActivity.obj还保有这个对象的引用。 所以如果在DemoActivity中不再使用这个对象了，可以在[Mark]的位置释放对象的引用，而代码可以修改为：<br /> ... ...<br /> public void operation() {<br /> &nbsp;&nbsp;obj = initObj();<br /> &nbsp;&nbsp;...<br /> &nbsp;&nbsp;final Object o = obj;<br /> &nbsp;&nbsp;obj = null;<br /> &nbsp;&nbsp;mHandler.post(new Runnable() {<br /> &nbsp;&nbsp;public void run() {<br /> &nbsp;&nbsp;useObj(o);<br /> &nbsp;&nbsp;}<br /> &nbsp;&nbsp;}<br /> }<br /> ... ...<br />  示例B:<br /> &nbsp;&nbsp;假设我们希望在锁屏界面(LockScreen)中，监听系统中的电话服务以获取一些信息(如信号强度等)，则可以在LockScreen中定义一个 PhoneStateListener的对象，同时将它注册到TelephonyManager服务中。对于LockScreen对象，当需要显示锁屏界 面的时候就会创建一个LockScreen对象，而当锁屏界面消失的时候LockScreen对象就会被释放掉。<br /> &nbsp;&nbsp;但是如果在释放LockScreen对象的时候忘记取消我们之前注册的PhoneStateListener对象，则会导致LockScreen无法 被垃圾回收。如果不断的使锁屏界面显示和消失，则最终会由于大量的LockScreen对象没有办法被回收而引起OutOfMemory,使得 system_process进程挂掉。<br /> &nbsp;&nbsp;总之当一个生命周期较短的对象A，被一个生命周期较长的对象B保有其引用的情况下，在A的生命周期结束时，要在B中清除掉对A的引用。<br /> (五) 其他<br /> &nbsp;&nbsp;Android应用程序中最典型的需要注意释放资源的情况是在Activity的生命周期中，在onPause()、onStop()、 onDestroy()方法中需要适当的释放资源的情况。由于此情况很基础，在此不详细说明，具体可以查看官方文档对Activity生命周期的介绍，以 明确何时应该释放哪些资源。<br /> 三、内存监测工具 DDMS --&gt; Heap<br /> &nbsp;&nbsp;无论怎么小心，想完全避免bad code是不可能的，此时就需要一些工具来帮助我们检查代码中是否存在会造成内存泄漏的地方。Android  tools中的DDMS就带有一个很不错的内存监测工具Heap(这里我使用eclipse的ADT插件，并以真机为例，在模拟器中的情况类似)。用 Heap监测应用进程使用内存情况的步骤如下：<br /> 1. 启动eclipse后，切换到DDMS透视图，并确认Devices视图、Heap视图都是打开的；<br /> 2. 将手机通过USB链接至电脑，链接时需要确认手机是处于&#8220;USB调试&#8221;模式，而不是作为&#8220;Mass Storage&#8221;；<br /> 3. 链接成功后，在DDMS的Devices视图中将会显示手机设备的序列号，以及设备中正在运行的部分进程信息；<br /> 4. 点击选中想要监测的进程，比如system_process进程；<br /> 5. 点击选中Devices视图界面中最上方一排图标中的&#8220;Update Heap&#8221;图标；<br /> 6. 点击Heap视图中的&#8220;Cause GC&#8221;按钮；<br /> 7. 此时在Heap视图中就会看到当前选中的进程的内存使用量的详细情况。<br />  说明：<br /> a) 点击&#8220;Cause GC&#8221;按钮相当于向虚拟机请求了一次gc操作；<br /> b) 当内存使用信息第一次显示以后，无须再不断的点击&#8220;Cause GC&#8221;，Heap视图界面会定时刷新，在对应用的不断的操作过程中就可以看到内存使用的变化；<br /> c) 内存使用信息的各项参数根据名称即可知道其意思，在此不再赘述。<br /> &nbsp;&nbsp;如何才能知道我们的程序是否有内存泄漏的可能性呢。这里需要注意一个值：Heap视图中部有一个Type叫做data  object，即数据对象，也就是我们的程序中大量存在的类类型的对象。在data object一行中有一列是&#8220;Total  Size&#8221;，其值就是当前进程中所有Java数据对象的内存总量，一般情况下，这个值的大小决定了是否会有内存泄漏。可以这样判断：<br /> a) 不断的操作当前应用，同时注意观察data object的Total Size值；<br /> b) 正常情况下Total  Size值都会稳定在一个有限的范围内，也就是说由于程序中的的代码良好，没有造成对象不被垃圾回收的情况，所以说虽然我们不断的操作会不断的生成很多对 象，而在虚拟机不断的进行GC的过程中，这些对象都被回收了，内存占用量会会落到一个稳定的水平；<br /> c) 反之如果代码中存在没有释放对象引用的情况，则data object的Total Size值在每次GC后不会有明显的回落，随着操作次数的增多Total Size的值会越来越大，<br /> &nbsp;&nbsp;直到到达一个上限后导致进程被kill掉。<br /> d) 此处已system_process进程为例，在我的测试环境中system_process进程所占用的内存的data object的Total Size正常情况下会稳定在2.2~2.8之间，而当其值超过3.55后进程就会被kill。<br /> &nbsp;&nbsp;<br /> &nbsp;&nbsp;总之，使用DDMS的Heap视图工具可以很方便的确认我们的程序是否存在内存泄漏的可能性。<br /> <br /> 四、内存分析工具 MAT(Memory Analyzer Tool)<br /> &nbsp;&nbsp;如果使用DDMS确实发现了我们的程序中存在内存泄漏，那又如何定位到具体出现问题的代码片段，最终找到问题所在呢？如果从头到尾的分析代码逻辑，那 肯定会把人逼疯，特别是在维护别人写的代码的时候。这里介绍一个极好的内存分析工具 -- Memory Analyzer Tool(MAT)。<br /> &nbsp;&nbsp;MAT是一个Eclipse插件，同时也有单独的RCP客户端。官方下载地址、MAT介绍和详细的使用教程请参见：<a href="http://www.eclipse.org/mat" target="_blank">www.eclipse.org/mat</a>，在此不进行说明了。另外在MAT安装后的帮助文档里也有完备的使用教程。在此仅举例说明其使用方法。我自己使用的是MAT的eclipse插件，使用插件要比RCP稍微方便一些。<br /> &nbsp;&nbsp;使用MAT进行内存分析需要几个步骤，包括：生成.hprof文件、打开MAT并导入.hprof文件、使用MAT的视图工具分析内存。以下详细介绍。<br /> (一) 生成.hprof文件<br /> &nbsp;&nbsp;生成.hprof文件的方法有很多，而且Android的不同版本中生成.hprof的方式也稍有差别，我使用的版本的是2.1，各个版本中生成.prof文件的方法请参考：<br /> <a href="http://android.git.kernel.org/?p=platform/dalvik.git" target="_blank">http://android.git.kernel.org/?p=platform/dalvik.git</a>;a=blob_plain;f=docs/heap-profiling.html;hb=HEAD。<br /> 1. 打开eclipse并切换到DDMS透视图，同时确认Devices、Heap和logcat视图已经打开了；<br /> 2. 将手机设备链接到电脑，并确保使用&#8220;USB 调试&#8221;模式链接，而不是&#8220;Mass Storage&#8220;模式；<br /> 3. 链接成功后在Devices视图中就会看到设备的序列号，和设备中正在运行的部分进程；<br /> 4. 点击选中想要分析的应用的进程，在Devices视图上方的一行图标按钮中，同时选中&#8220;Update Heap&#8221;和&#8220;Dump HPROF file&#8221;两个按钮；<br /> 5. 这是DDMS工具将会自动生成当前选中进程的.hprof文件，并将其进行转换后存放在sdcard当中，如果你已经安装了MAT插件，那么此时MAT将会自动被启用，并开始对.hprof文件进行分析；<br /> &nbsp;&nbsp;注意：第4步和第5步能够正常使用前提是我们需要有sdcard，并且当前进程有向sdcard中写入的权限(WRITE_EXTERNAL_STORAGE)，否则.hprof文件不会被生成，在logcat中会显示诸如<br /> &nbsp;&nbsp;ERROR/dalvikvm(8574): hprof: can't open /sdcard/com.xxx.hprof-hptemp: Permission denied.&nbsp;&nbsp;<br /> &nbsp;&nbsp;的信息。<br /> &nbsp; &nbsp; <br /> &nbsp;&nbsp;如果我们没有sdcard，或者当前进程没有向sdcard写入的权限（如system_process），那我们可以这样做：<br /> 6. 在当前程序中，例如framework中某些代码中，可以使用android.os.Debug中的：<br /> &nbsp;&nbsp;public static void dumpHprofData(String fileName) throws IOException<br /> &nbsp;&nbsp;方法，手动的指定.hprof文件的生成位置。例如：<br /> &nbsp;&nbsp;xxxButton.setOnClickListener(new View.OnClickListener() {<br /> &nbsp;&nbsp;public void onClick(View view) {<br /> &nbsp;&nbsp;android.os.Debug.dumpHprofData("/data/temp/myapp.hprof");<br /> &nbsp;&nbsp;... ...<br /> &nbsp;&nbsp;}<br /> &nbsp;&nbsp;}<br /> &nbsp;&nbsp;上述代码意图是希望在xxxButton被点击的时候开始抓取内存使用信息，并保存在我们指定的位置：/data/temp /myapp.hprof，这样就没有权限的限制了，而且也无须用sdcard。但要保证/data/temp目录是存在的。这个路径可以自己定义，当然 也可以写成sdcard当中的某个路径。<br />  <br /> (二) 使用MAT导入.hprof文件<br /> 1. 如果是eclipse自动生成的.hprof文件，可以使用MAT插件直接打开（可能是比较新的ADT才支持）；<br /> 2. 如果eclipse自动生成的.hprof文件不能被MAT直接打开，或者是使用android.os.Debug.dumpHprofData()方法手动生成的.hprof文件，则需要将.hprof文件进行转换，转换的方法：<br /> &nbsp;&nbsp;例如我将.hprof文件拷贝到PC上的/ANDROID_SDK/tools目录下，并输入命令hprof-conv xxx.hprof  yyy.hprof，其中xxx.hprof为原始文件，yyy.hprof为转换过后的文件。转换过后的文件自动放在/ANDROID_SDK /tools目录下。OK，到此为止，.hprof文件处理完毕，可以用来分析内存泄露情况了。<br /> 3. 在Eclipse中点击Windows-&gt;Open Perspective-&gt;Other-&gt;Memory  Analyzer，或者打Memory Analyzer Tool的RCP。在MAT中点击File-&gt;Open  File，浏览并导入刚刚转换而得到的.hprof文件。<br /> (三) 使用MAT的视图工具分析内存<br /> &nbsp;&nbsp;导入.hprof文件以后，MAT会自动解析并生成报告，点击Dominator  Tree，并按Package分组，选择自己所定义的Package类点右键，在弹出菜单中选择List objects-&gt;With  incoming references。这时会列出所有可疑类，右键点击某一项，并选择Path to GC Roots -&gt; exclude  weak/soft references，会进一步筛选出跟程序相关的所有有内存泄露的类。据此，可以追踪到代码中的某一个产生泄露的类。<br /> &nbsp;&nbsp;MAT的界面如下图所示。<br />  <br /> <br /> &nbsp;&nbsp;<br /> &nbsp;&nbsp;具体的分析方法在此不做说明了，因为在MAT的官方网站和客户端的帮助文档中有十分详尽的介绍。<br /> &nbsp;&nbsp;了解MAT中各个视图的作用很重要，例如<a href="http://www.eclipse.org/mat/about/screenshots.php" target="_blank">www.eclipse.org/mat/about/screenshots.php</a>中介绍的。<br /> &nbsp; &nbsp;<br /> &nbsp;&nbsp;总之使用MAT分析内存查找内存泄漏的根本思路，就是找到哪个类的对象的引用没有被释放，找到没有被释放的原因，也就可以很容易定位代码中的哪些片段的逻辑有问题了。</div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/171954.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-04-19 10:26 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/04/19/171954.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android远程图片获取和本地缓存</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/04/16/171602.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Mon, 16 Apr 2012 03:43:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/04/16/171602.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/171602.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/04/16/171602.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/171602.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/171602.html</trackback:ping><description><![CDATA[<div><p>另外一个问题就是加载速度，如果应用中图片加载速度很慢的话，那么用户同样会等到崩溃。</p> <p>那么如何处理好图片资源的获取和管理呢?</p> <p>异步下载</p> <p>本地缓存</p> <p>异步下载</p> <p>大家都知道，在android应用中UI线程5秒没响应的话就会抛出无响应异常，对于远程获取大的资源来说，这种异常还是很容易就会抛出来的，那么怎么避免这种问题的产生。在android中提供两种方法来做这件事情：</p> <p>启动一个新的线程来获取资源，完成后通过Handler机制发送消息，并在UI线程中处理消息，从而达到在异步线程中获取图片，然后通过Handler Message来更新UI线程的过程。</p> <p>使用android中提供的AsyncTask来完成。</p>  <center><img alt="" src="http://www.61ic.com/Mobile/UploadFiles_9667/201109/20110907085025291.png" height="219" width="469" /></center> <p>具体的做法这里就不介绍了，查下API就可以了，或者是google、baidu下。这里主要来说本地缓存。</p> <p>本地缓存</p> <p>对于图片资源来说，你不可能让应用每次获取的时候都重新到远程去下载(ListView)，这样会浪费资源，但是你又不能让所有图片资源都放到内存 中去(虽然这样加载会比较快)，因为图片资源往往会占用很大的内存空间，容易导致OOM。那么如果下载下来的图片保存到SDCard中，下次直接从 SDCard上去获取呢?这也是一种做法，我看了下，还是有不少应用采用这种方式的。采用LRU等一些算法可以保证sdcard被占用的空间只有一小部 分，这样既保证了图片的加载、节省了流量、又使SDCard的空间只占用了一小部分。另外一种做法是资源直接保存在内存中，然后设置过期时间和LRU规 则。</p> <p>sdcard保存：</p>  <center><img alt="" src="http://www.61ic.com/Mobile/UploadFiles_9667/201109/20110907085025219.png" height="286" width="367" /></center> <p>在sdcard上开辟一定的空间，需要先判断sdcard上剩余空间是否足够，如果足够的话就可以开辟一些空间，比如10M</p> <p>当需要获取图片时，就先从sdcard上的目录中去找，如果找到的话，使用该图片，并更新图片最后被使用的时间。如果找不到，通过URL去download</p> <p>去服务器端下载图片，如果下载成功了，放入到sdcard上，并使用，如果失败了，应该有重试机制。比如3次。</p> <p>下载成功后保存到sdcard上，需要先判断10M空间是否已经用完，如果没有用完就保存，如果空间不足就根据LRU规则删除一些最近没有被用户的资源。</p> <p>关键代码：</p> <p>保存图片到SD卡上</p><pre><ol><li><span>private void saveBmpToSd(Bitmap bm, Stringurl) { </span></li><li>        if (<span>bm == null) { </span></li><li>            Log.w(TAG, " trying to savenull bitmap"); </li><li>            return; </li><li>        } </li><li>         //判断sdcard上的空间 </li><li>        if (FREE_SD_SPACE_NEEDED_TO_CACHE <span><strong>&gt;</strong>freeSpaceOnSd()) { </span></li><li>            Log.w(TAG, "Low free space onsd, do not cache"); </li><li>            return; </li><li>        } </li><li>        String <span>filename =convertUrlToFileName(url); </span></li><li>        String <span>dir = getDirectory(filename); </span></li><li>        File <span>file = new File(dir +"/" + filename); </span></li><li>        try { </li><li>            file.createNewFile(); </li><li>            OutputStream <span>outStream = newFileOutputStream(file); </span></li><li>           bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream); </li><li>            outStream.flush(); </li><li>            outStream.close(); </li><li>            Log.i(TAG, "Image saved tosd"); </li><li>        } catch (FileNotFoundException e) { </li><li>            Log.w(TAG,"FileNotFoundException"); </li><li>        } catch (IOException e) { </li><li>            Log.w(TAG,"IOException"); </li><li>        } </li><li>    } </li></ol></pre> <p>计算sdcard上的空间：</p><pre><ol><li><span>/** </span></li><li> * 计算sdcard上的剩余空间 </li><li> * @return </li><li> */ </li><li>private int freeSpaceOnSd() { </li><li>    StatFs <span>stat = newStatFs(Environment.getExternalStorageDirectory() .getPath()); </span></li><li>    double <span>sdFreeMB = ((double)stat.getAvailableBlocks() * (double) stat.getBlockSize()) / MB; </span></li><li>    return (int) sdFreeMB; </li><li>} </li></ol></pre> <p>修改文件的最后修改时间</p><pre><ol><li><span>/** </span></li><li> * 修改文件的最后修改时间 </li><li> * @param dir </li><li> * @param fileName </li><li> */ </li><li>private void updateFileTime(String dir,String fileName) { </li><li>    File <span>file = new File(dir,fileName);        </span></li><li>    long <span>newModifiedTime =System.currentTimeMillis(); </span></li><li>    file.setLastModified(newModifiedTime); </li><li>} </li></ol></pre> <p>本地缓存优化</p><pre><ol><li><span>/** </span></li><li> *计算存储目录下的文件大小，当文件总大小大于规定的CACHE_SIZE或者sdcard剩余空间小于FREE_SD_SPACE_NEEDED_TO_CACHE的规定 </li><li> * 那么删除40%最近没有被使用的文件 </li><li> * @param dirPath </li><li> * @param filename </li><li> */ </li><li>private void removeCache(String dirPath) { </li><li>    File <span>dir = new File(dirPath); </span></li><li>    File[] <span>files = dir.listFiles(); </span></li><li>    if (<span>files == null) { </span></li><li>        return; </li><li>    } </li><li>    int <span>dirSize = 0; </span></li><li>    for (int <span>i = 0; i <strong>&lt;</strong> <strong>files.length</strong>;i++) { </span></li><li>        if(files[i].getName().contains(WHOLESALE_CONV)) { </li><li>            dirSize += files[i].length(); </li><li>        } </li><li>    } </li><li>    if (dirSize <span><strong>&gt;</strong> CACHE_SIZE * MB ||FREE_SD_SPACE_NEEDED_TO_CACHE <strong>&gt;</strong> freeSpaceOnSd()) { </span></li><li>        int <span>removeFactor = (int) ((0.4 *files.length) + 1); </span></li><li> </li><li>        Arrays.sort(files, newFileLastModifSort()); </li><li> </li><li>        Log.i(TAG, "Clear some expiredcache files "); </li><li> </li><li>        for (int <span>i = 0; i <strong>&lt;removeFactor</strong>; i++) { </span></li><li> </li><li>            if(files[i].getName().contains(WHOLESALE_CONV)) { </li><li> </li><li>                files[i].delete();              </li><li> </li><li>            } </li><li> </li><li>        } </li><li> </li><li>    } </li><li> </li><li>} </li><li>/** </li><li> * 删除过期文件 </li><li> * @param dirPath </li><li> * @param filename </li><li> */ </li><li>private void removeExpiredCache(StringdirPath, String filename) { </li><li> </li><li>    File <span>file = new File(dirPath,filename); </span></li><li> </li><li>    if (System.currentTimeMillis() -file.lastModified() <span><strong>&gt;</strong> mTimeDiff) { </span></li><li> </li><li>        Log.i(TAG, "Clear some expiredcache files "); </li><li> </li><li>        file.delete(); </li><li> </li><li>    } </li><li> </li><li>} </li></ol></pre> <p>文件使用时间排序</p><pre><ol><li><span>/** </span></li><li> * TODO 根据文件的最后修改时间进行排序 * </li><li> */ </li><li>classFileLastModifSort implements Comparator<strong><span>&lt;File&gt;</span></strong>{ </li><li>    public int compare(File arg0, File arg1) { </li><li>        if (arg0.lastModified() <span><strong>&gt;</strong>arg1.lastModified()) { </span></li><li>            return 1; </li><li>        } else if (arg0.lastModified() ==arg1.lastModified()) { </li><li>            return 0; </li><li>        } else { </li><li>            return -1; </li><li>        } </li><li>    } </li><li>} </li></ol></pre> <p>内存保存：</p> <p>在内存中保存的话，只能保存一定的量，而不能一直往里面放，需要设置数据的过期时间、LRU等算法。这里有一个方法是把常用的数据放到一个缓存中 (A)，不常用的放到另外一个缓存中(B)。当要获取数据时先从A中去获取，如果A中不存在那么再去B中获取。B中的数据主要是A中LRU出来的数据，这 里的内存回收主要针对B内存，从而保持A中的数据可以有效的被命中。</p>  <center><img alt="" src="http://www.61ic.com/Mobile/UploadFiles_9667/201109/20110907085025923.png" height="402" width="375" /></center> <p>先定义A缓存：</p><pre><ol><li><span>private final HashMap<strong>&lt;String</strong>, Bitmap<strong>&gt;</strong>mHardBitmapCache = new LinkedHashMap<strong>&lt;String</strong>, Bitmap<strong>&gt;</strong>(HARD_CACHE_CAPACITY/ 2, 0.75f, true) { </span></li><li>        @Override </li><li>        protected booleanremoveEldestEntry(LinkedHashMap.Entry<strong><span>&lt;String</span></strong>, Bitmap<strong>&gt;</strong> eldest) { </li><li>            if (size() <span><strong>&gt;</strong>HARD_CACHE_CAPACITY) { </span></li><li>               //当map的size大于30时，把最近不常用的key放到mSoftBitmapCache中，从而保证mHardBitmapCache的效率 </li><li>               mSoftBitmapCache.put(eldest.getKey(), newSoftReference<strong><span>&lt;Bitmap&gt;</span></strong>(eldest.getValue())); </li><li>                return true; </li><li>            } else </li><li>                return false; </li><li>        } </li><li>    }; </li></ol></pre> <p>再定于B缓存：</p><pre><ol><li><span>/** </span></li><li>    *当mHardBitmapCache的key大于30的时候，会根据LRU算法把最近没有被使用的key放入到这个缓存中。 </li><li>    *Bitmap使用了SoftReference，当内存空间不足时，此cache中的bitmap会被垃圾回收掉 </li><li>    */ </li><li>   private final staticConcurrentHashMap<strong><span>&lt;String</span></strong>, SoftReference<strong>&lt;Bitmap&gt;&gt;</strong> mSoftBitmapCache =new ConcurrentHashMap<strong>&lt;String</strong>,SoftReference<strong>&lt;Bitmap&gt;&gt;</strong>(HARD_CACHE_CAPACITY / 2); </li></ol></pre> <p>从缓存中获取数据：</p><pre><ol><li><span>/** </span></li><li>     * 从缓存中获取图片 </li><li>     */ </li><li>    private Bitmap getBitmapFromCache(Stringurl) { </li><li>        // 先从mHardBitmapCache缓存中获取 </li><li>        synchronized (mHardBitmapCache) { </li><li>            final Bitmap <span>bitmap =mHardBitmapCache.get(url); </span></li><li>            if (bitmap != null) { </li><li>                //如果找到的话，把元素移到linkedhashmap的最前面，从而保证在LRU算法中是最后被删除 </li><li>                mHardBitmapCache.remove(url); </li><li>                mHardBitmapCache.put(url,bitmap); </li><li>                return bitmap; </li><li>            } </li><li>        } </li><li>        //如果mHardBitmapCache中找不到，到mSoftBitmapCache中找 </li><li>        SoftReference<strong><span>&lt;Bitmap&gt;</span></strong>bitmapReference = mSoftBitmapCache.get(url); </li><li>        if (bitmapReference != null) { </li><li>            final Bitmap <span>bitmap =bitmapReference.get(); </span></li><li>            if (bitmap != null) { </li><li>                return bitmap; </li><li>            } else { </li><li>                mSoftBitmapCache.remove(url); </li><li>            } </li><li>        } </li><li>        return null; </li><li>    } </li></ol></pre> <p>如果缓存中不存在，那么就只能去服务器端去下载：</p><pre><ol><li><span>/** </span></li><li>     * 异步下载图片 </li><li>     */ </li><li>    class ImageDownloaderTask extendsAsyncTask<strong><span>&lt;String</span></strong>, Void, Bitmap<strong>&gt;</strong> { </li><li>        private static final int <span>IO_BUFFER_SIZE= 4 * 1024; </span></li><li>        private String url; </li><li>        private finalWeakReference<strong><span>&lt;ImageView&gt;</span></strong> imageViewReference; </li><li>        public ImageDownloaderTask(ImageViewimageView) { </li><li>            <span>imageViewReference = newWeakReference<strong>&lt;ImageView&gt;</strong>(imageView); </span></li><li>        } </li><li> </li><li>       @Override </li><li>        protected BitmapdoInBackground(String... params) { </li><li>            final AndroidHttpClient <span>client =AndroidHttpClient.newInstance("Android"); </span></li><li>            <span>url = params[0]; </span></li><li>            final HttpGet <span>getRequest = newHttpGet(url); </span></li><li>            try { </li><li>                HttpResponse <span>response =client.execute(getRequest); </span></li><li>                final int <span>statusCode =response.getStatusLine().getStatusCode(); </span></li><li>                if (statusCode !=HttpStatus.SC_OK) { </li><li>                    Log.w(TAG, "从" +url + "中下载图片时出错!,错误码:" + statusCode); </li><li>                    return null; </li><li>                } </li><li>                final HttpEntity <span>entity =response.getEntity(); </span></li><li>                if (entity != null) { </li><li>                    InputStream <span>inputStream =null; </span></li><li>                    OutputStream <span>outputStream =null; </span></li><li>                    try { </li><li>                        <span>inputStream =entity.getContent(); </span></li><li>                        finalByteArrayOutputStream <span>dataStream = new ByteArrayOutputStream(); </span></li><li>                        <span>outputStream = newBufferedOutputStream(dataStream, IO_BUFFER_SIZE); </span></li><li>                        copy(inputStream,outputStream); </li><li>                        outputStream.flush(); </li><li>                        final byte[] <span>data =dataStream.toByteArray(); </span></li><li>                        final Bitmap <span>bitmap =BitmapFactory.decodeByteArray(data, 0, data.length); </span></li><li>                        return bitmap; </li><li>                    } finally { </li><li>                        if (inputStream !=null) { </li><li>                           inputStream.close(); </li><li>                        } </li><li>                        if (outputStream !=null) { </li><li>                           outputStream.close(); </li><li>                        } </li><li>                       entity.consumeContent(); </li><li>                    } </li><li>                } </li><li>            } catch (IOException e) { </li><li>                getRequest.abort(); </li><li>                Log.w(TAG, "I/O errorwhile retrieving bitmap from " + url, e); </li><li>            } catch (IllegalStateException e) { </li><li>                getRequest.abort(); </li><li>                Log.w(TAG, "Incorrect URL:" + url); </li><li>            } catch (Exception e) { </li><li>                getRequest.abort(); </li><li>                Log.w(TAG, "Error whileretrieving bitmap from " + url, e); </li><li>            } finally { </li><li>                if (client != null) { </li><li>                    client.close(); </li><li>                } </li><li>            } </li><li>            return null; </li><li>        } </li></ol></pre> <p>这是两种做法，还有一些应用在下载的时候使用了线程池和消息队列MQ，对于图片下载的效率要更好一些。有兴趣的同学可以看下。</p> <p>总结</p> <p>对于远程图片等相对比较大的资源一定要在异步线程中去获取本地做缓存</p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/171602.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-04-16 11:43 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/04/16/171602.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java5泛型的用法，T.class的获取和为擦拭法站台 (转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/04/14/171398.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sat, 14 Apr 2012 13:47:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/04/14/171398.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/171398.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/04/14/171398.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/171398.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/171398.html</trackback:ping><description><![CDATA[<div>&nbsp; Java  5的泛型语法已经有太多书讲了，这里不再打字贴书。GP一定有用，不然Java和C#不会约好了似的同时开始支持GP。但大家也清楚，GP和Ruby式的 动态OO语言属于不同的意识形态，如果是一人一票，我想大部分的平民程序员更热衷动态OO语言的平白自然。但如果不准备跳槽到支持JSR223的动态语 言，那还是看看GP吧。<br /><br />&nbsp;&nbsp; <strong>胡乱总结泛型的四点作用：<br /></strong>&nbsp;&nbsp; 第一是泛化，可以拿个T代表任意类型。 但GP是被C++严苛的静态性逼出来的，落到Java、C#这样的花语平原里----所有对象除几个原始类型外都派生于Object，再加上Java的反射功能，Java的Collection库没有范型一样过得好好的。<br /><br />&nbsp;&nbsp;&nbsp;第二是泛型 +&nbsp;反射，原本因为Java的泛型拿不到T.class而觉得泛型没用，最近才刚刚学到通过反射的API来获取T的Class，后述。<br /><br />&nbsp;&nbsp; 第三是收敛，就是增加了类型安全，减少了强制类型转换的代码。这点倒是Java Collection历来的弱项。<br /><br />&nbsp;&nbsp;   第四是可以在编译期搞很多东西，比如MetaProgramming。但除非能完全封闭于框架内部，框架的使用者和扩展者都不用学习这些东西的用法，否则 那就是自绝于人民的票房毒药。C++的MetaProgramming好厉害吧，但对比一下Python拿Meta  Programming生造一个Class出来的简便语法，就明白什么才是真正的叫好又叫座。<br /><br />&nbsp;&nbsp;&nbsp;所以，作为一个架构设计师，应该使用上述的第2，3项用法，在框架类里配合使用反射和泛型，使得框架的能力更强； 同时采用收敛特性，本着对人民负责的精神，用泛型使框架更加类型安全，更少强制类型转换。<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp; <strong>擦拭法避免了Java的流血分裂&nbsp;：</strong><br />&nbsp;&nbsp;&nbsp; 大家经常骂Java GP的擦拭法实现，但我觉得多亏于它的中庸特性---如果你用就是范型，不用就是普通Object，避免了Java阵营又要经历一场to be or not to be的分裂。&nbsp;<br />&nbsp;&nbsp; &nbsp;最大的例子莫过Java 5的Collection 框架，&nbsp;比如有些同学坚持认为自己不会白痴到类型出错，而且难以忍受每个定义的地方都要带一个泛型定义List〈Book〉，不用强制类型转换所省下的代码还不够N处定义花的(对了，java里面还没有tyepdef.....)，因此对范型十分不感冒，这时就要齐齐感谢这个搽拭法让你依然可以对一个泛型框架保持非泛型的用法了...<br /><br />&nbsp;&nbsp;<strong> 通过反射获得 T.class：</strong><br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; 不知为何书上不怎么讲这个，是差沙告诉我才知道的，最经典的应用见Hibernate wiki的<a href="http://www.hibernate.org/328.html">Generic Data Access Objects</a>， 代码如下：&nbsp;  <div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #0000ff">abstract</span>&nbsp;<span style="color: #0000ff">public</span>&nbsp;<span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;BaseHibernateEntityDao</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span>&nbsp;<span style="color: #0000ff">extends</span><span style="color: #000000">&nbsp;HibernateDaoSupport&nbsp;{<br />&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;Class&lt;T&gt;&nbsp;entityClass;<br />&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;BaseHibernateEntityDao()&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;entityClass&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">(Class&lt;T&gt;) ((ParameterizedType) getClass()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .getGenericSuperclass()).getActualTypeArguments()[0];<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;T&nbsp;get(Serializable&nbsp;id)&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;o&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;(T)&nbsp;getHibernateTemplate().get(entityClass,&nbsp;id);<br />}<br />}</span></div><br />&nbsp; 精华就是这句了：<br /><div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #000000">Class</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span><span style="color: #000000">&nbsp;entityClass&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;(Class</span><span style="color: #000000">&lt;</span><span style="color: #000000">T</span><span style="color: #000000">&gt;</span><span style="color: #000000">)&nbsp;((ParameterizedType)&nbsp;getClass().getGenericSuperclass()).getActualTypeArguments()[</span><span style="color: #000000">0</span><span style="color: #000000">];&nbsp;</span></div><br />&nbsp; 泛型之后，所有BaseHibernateEntityDao的子类只要定义了泛型，就无需再重载getEnttityClass()，get()函数和find()函数，销益挺明显的，所以<a href="http://www.springside.org.cn/">SpringSide</a>的Dao基类毫不犹豫就泛型了。<br /><br />&nbsp; 不过擦拭法的大棒仍在，所以子类的泛型语法可不能乱写，最正确的用法只有：<br />&nbsp;&nbsp;&nbsp;  <span style="color: #0000ff">public</span>&nbsp;<span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;BookDao&nbsp;</span><span style="color: #0000ff">extends</span><span style="color: #000000">&nbsp;BaseHibernateEntityDao</span><span style="color: #000000">&lt;</span><span style="color: #000000">Book</span><span style="color: #000000">&gt;</span></div><br />转自:<div>http://www.blogjava.net/calvin/archive/2009/12/10/43830.html</div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/171398.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-04-14 21:47 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/04/14/171398.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android NotificationManager 和Notification的使用总结</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/04/05/170101.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Wed, 04 Apr 2012 18:34:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/04/05/170101.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/170101.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/04/05/170101.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/170101.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/170101.html</trackback:ping><description><![CDATA[<div><div> 		<br /> 	</div> 	 <div><a href="http://www.cnblogs.com/stay/articles/1898963.html#" command_help=""  help"="">?</a></div><table border="0" cellpadding="0" cellspacing="0"><tbody><tr><td><div number1="" index0=""  alt2"="">1</div><div number2="" index1=""  alt1"="">2</div><div number3="" index2=""  alt2"="">3</div><div number4="" index3=""  alt1"="">4</div><div number5="" index4=""  alt2"="">5</div><div number6="" index5=""  alt1"="">6</div><div number7="" index6=""  alt2"="">7</div><div number8="" index7=""  alt1"="">8</div><div number9="" index8=""  alt2"="">9</div><div number10="" index9=""  alt1"="">10</div><div number11="" index10=""  alt2"="">11</div><div number12="" index11=""  alt1"="">12</div><div number13="" index12=""  alt2"="">13</div><div number14="" index13=""  alt1"="">14</div><div number15="" index14=""  alt2"="">15</div><div number16="" index15=""  alt1"="">16</div><div number17="" index16=""  alt2"="">17</div><div number18="" index17=""  alt1"="">18</div><div number19="" index18=""  alt2"="">19</div><div number20="" index19=""  alt1"="">20</div><div number21="" index20=""  alt2"="">21</div><div number22="" index21=""  alt1"="">22</div><div number23="" index22=""  alt2"="">23</div><div number24="" index23=""  alt1"="">24</div><div number25="" index24=""  alt2"="">25</div><div number26="" index25=""  alt1"="">26</div><div number27="" index26=""  alt2"="">27</div><div number28="" index27=""  alt1"="">28</div><div number29="" index28=""  alt2"="">29</div><div number30="" index29=""  alt1"="">30</div><div number31="" index30=""  alt2"="">31</div><div number32="" index31=""  alt1"="">32</div><div number33="" index32=""  alt2"="">33</div><div number34="" index33=""  alt1"="">34</div><div number35="" index34=""  alt2"="">35</div><div number36="" index35=""  alt1"="">36</div><div number37="" index36=""  alt2"="">37</div><div number38="" index37=""  alt1"="">38</div><div number39="" index38=""  alt2"="">39</div><div number40="" index39=""  alt1"="">40</div><div number41="" index40=""  alt2"="">41</div><div number42="" index41=""  alt1"="">42</div><div number43="" index42=""  alt2"="">43</div><div number44="" index43=""  alt1"="">44</div><div number45="" index44=""  alt2"="">45</div><div number46="" index45=""  alt1"="">46</div><div number47="" index46=""  alt2"="">47</div><div number48="" index47=""  alt1"="">48</div><div number49="" index48=""  alt2"="">49</div><div number50="" index49=""  alt1"="">50</div><div number51="" index50=""  alt2"="">51</div><div number52="" index51=""  alt1"="">52</div><div number53="" index52=""  alt2"="">53</div><div number54="" index53=""  alt1"="">54</div><div number55="" index54=""  alt2"="">55</div><div number56="" index55=""  alt1"="">56</div><div number57="" index56=""  alt2"="">57</div><div number58="" index57=""  alt1"="">58</div><div number59="" index58=""  alt2"="">59</div><div number60="" index59=""  alt1"="">60</div><div number61="" index60=""  alt2"="">61</div><div number62="" index61=""  alt1"="">62</div><div number63="" index62=""  alt2"="">63</div><div number64="" index63=""  alt1"="">64</div><div number65="" index64=""  alt2"="">65</div><div number66="" index65=""  alt1"="">66</div><div number67="" index66=""  alt2"="">67</div><div number68="" index67=""  alt1"="">68</div><div number69="" index68=""  alt2"="">69</div><div number70="" index69=""  alt1"="">70</div><div number71="" index70=""  alt2"="">71</div><div number72="" index71=""  alt1"="">72</div><div number73="" index72=""  alt2"="">73</div><div number74="" index73=""  alt1"="">74</div><div number75="" index74=""  alt2"="">75</div><div number76="" index75=""  alt1"="">76</div><div number77="" index76=""  alt2"="">77</div><div number78="" index77=""  alt1"="">78</div><div number79="" index78=""  alt2"="">79</div><div number80="" index79=""  alt1"="">80</div><div number81="" index80=""  alt2"="">81</div><div number82="" index81=""  alt1"="">82</div><div number83="" index82=""  alt2"="">83</div><div number84="" index83=""  alt1"="">84</div><div number85="" index84=""  alt2"="">85</div><div number86="" index85=""  alt1"="">86</div><div number87="" index86=""  alt2"="">87</div><div number88="" index87=""  alt1"="">88</div><div number89="" index88=""  alt2"="">89</div><div number90="" index89=""  alt1"="">90</div><div number91="" index90=""  alt2"="">91</div><div number92="" index91=""  alt1"="">92</div><div number93="" index92=""  alt2"="">93</div><div number94="" index93=""  alt1"="">94</div><div number95="" index94=""  alt2"="">95</div><div number96="" index95=""  alt1"="">96</div><div number97="" index96=""  alt2"="">97</div><div number98="" index97=""  alt1"="">98</div><div number99="" index98=""  alt2"="">99</div><div number100="" index99=""  alt1"="">100</div><div number101="" index100=""  alt2"="">101</div><div number102="" index101=""  alt1"="">102</div><div number103="" index102=""  alt2"="">103</div></td><td><div><div number1="" index0=""  alt2"=""><code plain"="">NotificationManager 和Notification的使用总结（转）</code></div><div number2="" index1=""  alt1"=""><code plain"="">文章分类:移动开发</code></div><div number3="" index2=""  alt2"=""><code plain"="">这 几天一直在修改twigee的源代码，其中一个要加入的功能是常驻Notification栏，以前写的时候只能出现  在&#8220;通知&#8221;这一组中，想把它放在&#8220;正在运行&#8221;组中却不知道怎么放，查了下官方文档，找到了方法，在notification的flags字段中加一下  &#8220;FLAG_ONGOING_EVENT&#8221;就可以了。同时我也把Notification的使用方法给总结了一下。详见下文：</code></div><div number4="" index3=""  alt1"=""><code plain"="">(</code><code value"="">1</code><code plain"="">)、使用系统定义的Notification</code></div><div number5="" index4=""  alt2"=""><code plain"="">以下是使用示例代码：</code></div><div number6="" index5=""  alt1"=""><code comments"="">//创建一个NotificationManager的引用</code></div><div number7="" index6=""  alt2"=""><code plain"="">String ns = Context.NOTIFICATION_SERVICE;</code></div><div number8="" index7=""  alt1"=""><code plain"="">NotificationManager mNotificationManager = (NotificationManager)getSystemService(ns);</code></div><div number9="" index8=""  alt2"=""><code comments"="">// 定义Notification的各种属性</code></div><div number10="" index9=""  alt1"=""><code keyword"="">int</code> <code plain"="">icon = R.drawable.icon; </code><code comments"="">//通知图标</code></div><div number11="" index10=""  alt2"=""><code plain"="">CharSequence tickerText = </code><code string"="">"Hello"</code><code plain"="">; </code><code comments"="">//状态栏显示的通知文本提示</code></div><div number12="" index11=""  alt1"=""><code keyword"="">long</code> <code plain"="">when = System.currentTimeMillis(); </code><code comments"="">//通知产生的时间，会在通知信息里显示</code></div><div number13="" index12=""  alt2"=""><code comments"="">//用上面的属性初始化 Nofification</code></div><div number14="" index13=""  alt1"=""><code plain"="">Notification notification = </code><code keyword"="">new</code> <code plain"="">Notification(icon,tickerText,when);</code></div><div number15="" index14=""  alt2"=""><code comments"="">/*</code></div><div number16="" index15=""  alt1"=""><code comments"="">* 添加声音</code></div><div number17="" index16=""  alt2"=""><code comments"="">* notification.defaults |=Notification.DEFAULT_SOUND;</code></div><div number18="" index17=""  alt1"=""><code comments"="">* 或者使用以下几种方式</code></div><div number19="" index18=""  alt2"=""><code comments"="">* notification.sound = Uri.parse("<a>file:///sdcard/notification/ringer.mp3</a>");</code></div><div number20="" index19=""  alt1"=""><code comments"="">* notification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6");</code></div><div number21="" index20=""  alt2"=""><code comments"="">* 如果想要让声音持续重复直到用户对通知做出反应，则可以在notification的flags字段增加"FLAG_INSISTENT"</code></div><div number22="" index21=""  alt1"=""><code comments"="">* 如果notification的defaults字段包括了"DEFAULT_SOUND"属性，则这个属性将覆盖sound字段中定义的声音</code></div><div number23="" index22=""  alt2"=""><code comments"="">*/</code></div><div number24="" index23=""  alt1"=""><code comments"="">/*</code></div><div number25="" index24=""  alt2"=""><code comments"="">* 添加振动</code></div><div number26="" index25=""  alt1"=""><code comments"="">* notification.defaults |= Notification.DEFAULT_VIBRATE;</code></div><div number27="" index26=""  alt2"=""><code comments"="">* 或者可以定义自己的振动模式：</code></div><div number28="" index27=""  alt1"=""><code comments"="">* long[] vibrate = {0,100,200,300}; //0毫秒后开始振动，振动100毫秒后停止，再过200毫秒后再次振动300毫秒</code></div><div number29="" index28=""  alt2"=""><code comments"="">* notification.vibrate = vibrate;</code></div><div number30="" index29=""  alt1"=""><code comments"="">* long数组可以定义成想要的任何长度</code></div><div number31="" index30=""  alt2"=""><code comments"="">* 如果notification的defaults字段包括了"DEFAULT_VIBRATE",则这个属性将覆盖vibrate字段中定义的振动</code></div><div number32="" index31=""  alt1"=""><code comments"="">*/</code></div><div number33="" index32=""  alt2"=""><code comments"="">/*</code></div><div number34="" index33=""  alt1"=""><code comments"="">* 添加LED灯提醒</code></div><div number35="" index34=""  alt2"=""><code comments"="">* notification.defaults |= Notification.DEFAULT_LIGHTS;</code></div><div number36="" index35=""  alt1"=""><code comments"="">* 或者可以自己的LED提醒模式:</code></div><div number37="" index36=""  alt2"=""><code comments"="">* notification.ledARGB = 0xff00ff00;</code></div><div number38="" index37=""  alt1"=""><code comments"="">* notification.ledOnMS = 300; //亮的时间</code></div><div number39="" index38=""  alt2"=""><code comments"="">* notification.ledOffMS = 1000; //灭的时间</code></div><div number40="" index39=""  alt1"=""><code comments"="">* notification.flags |= Notification.FLAG_SHOW_LIGHTS;</code></div><div number41="" index40=""  alt2"=""><code comments"="">*/</code></div><div number42="" index41=""  alt1"=""><code comments"="">/*</code></div><div number43="" index42=""  alt2"=""><code comments"="">* 更多的特征属性</code></div><div number44="" index43=""  alt1"=""><code comments"="">* notification.flags |= FLAG_AUTO_CANCEL; //在通知栏上点击此通知后自动清除此通知</code></div><div number45="" index44=""  alt2"=""><code comments"="">* notification.flags |= FLAG_INSISTENT; //重复发出声音，直到用户响应此通知</code></div><div number46="" index45=""  alt1"=""><code comments"="">* notification.flags |= FLAG_ONGOING_EVENT; //将此通知放到通知栏的"Ongoing"即"正在运行"组中</code></div><div number47="" index46=""  alt2"=""><code comments"="">* notification.flags |= FLAG_NO_CLEAR; //表明在点击了通知栏中的"清除通知"后，此通知不清除，</code></div><div number48="" index47=""  alt1"=""><code comments"="">* //经常与FLAG_ONGOING_EVENT一起使用</code></div><div number49="" index48=""  alt2"=""><code comments"="">* notification.number = 1; //number字段表示此通知代表的当前事件数量，它将覆盖在状态栏图标的顶部</code></div><div number50="" index49=""  alt1"=""><code comments"="">* //如果要使用此字段，必须从1开始</code></div><div number51="" index50=""  alt2"=""><code comments"="">* notification.iconLevel = ; //</code></div><div number52="" index51=""  alt1"=""><code comments"="">*/</code></div><div number53="" index52=""  alt2"=""><code comments"="">//设置通知的事件消息</code></div><div number54="" index53=""  alt1"=""><code plain"="">Context context = getApplicationContext(); </code><code comments"="">//上下文</code></div><div number55="" index54=""  alt2"=""><code plain"="">CharSequence contentTitle = </code><code string"="">"My Notification"</code><code plain"="">; </code><code comments"="">//通知栏标题</code></div><div number56="" index55=""  alt1"=""><code plain"="">CharSequence contentText = </code><code string"="">"Hello World!"</code><code plain"="">; </code><code comments"="">//通知栏内容</code></div><div number57="" index56=""  alt2"=""><code plain"="">Intent notificationIntent = </code><code keyword"="">new</code> <code plain"="">Intent(</code><code keyword"="">this</code><code plain"="">,Main.</code><code keyword"="">class</code><code plain"="">); </code><code comments"="">//点击该通知后要跳转的Activity</code></div><div number58="" index57=""  alt1"=""><code plain"="">PendingIntent contentIntent = PendingIntent.getActivity(</code><code keyword"="">this</code><code plain"="">,</code><code value"="">0</code><code plain"="">,notificationIntent,</code><code value"="">0</code><code plain"="">);</code></div><div number59="" index58=""  alt2"=""><code plain"="">notification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);</code></div><div number60="" index59=""  alt1"=""><code comments"="">//把Notification传递给 NotificationManager</code></div><div number61="" index60=""  alt2"=""><code plain"="">mNotificationManager.notify(</code><code value"="">0</code><code plain"="">,notification);</code></div><div number62="" index61=""  alt1"=""><code plain"="">如果想要更新一个通知，只需要在设置好notification之后，再次调用 setLatestEventInfo(),然后重新发送一次通知即可，即再次调用notify()。</code></div><div number63="" index62=""  alt2"=""><code plain"="">(</code><code value"="">2</code><code plain"="">)、使用自定义的 Notification</code></div><div number64="" index63=""  alt1"=""><code plain"="">要 创建一个自定义的Notification，可以使用RemoteViews。要定义自己的扩展消息，首先  要初始化一个RemoteViews对象，然后将它传递给Notification的contentView字段，再把PendingIntent传递给  contentIntent字段。以下示例代码是完整步骤：</code></div><div number65="" index64=""  alt2"=""><code comments"="">//1、创建一个自 定义的消息布局 view.xml</code></div><div number66="" index65=""  alt1"=""><code plain"="">&lt;?xml version=</code><code string"="">"1.0"</code> <code plain"="">encoding=</code><code string"="">"utf-8"</code><code plain"="">?&gt;</code></div><div number67="" index66=""  alt2"=""><code plain"="">&lt;LinearLayout xmlns:android=</code><code string"="">"<a href="http://schemas.android.com/apk/res/android">http://schemas.android.com/apk/res/android</a>"</code></div><div number68="" index67=""  alt1"=""><code plain"="">android:layout_width=</code><code string"="">"fill_parent"</code> <code plain"="">android:layout_height=</code><code string"="">"fill_parent"</code><code plain"="">&gt;</code></div><div number69="" index68=""  alt2"=""><code plain"="">&lt;ImageView android:id=</code><code string"="">"@+id/image"</code> <code plain"="">android:layout_width=</code><code string"="">"wrap_content"</code></div><div number70="" index69=""  alt1"=""><code plain"="">android:layout_height=</code><code string"="">"fill_parent"</code> <code plain"="">android:layout_marginRight=</code><code string"="">"10dp"</code> <code plain"="">/&gt;</code></div><div number71="" index70=""  alt2"=""><code plain"="">&lt;TextView android:id=</code><code string"="">"@+id/text"</code> <code plain"="">android:layout_width=</code><code string"="">"wrap_content"</code></div><div number72="" index71=""  alt1"=""><code plain"="">android:layout_height=</code><code string"="">"fill_parent"</code> <code plain"="">android:textColor=</code><code string"="">"#000"</code> <code plain"="">/&gt;</code></div><div number73="" index72=""  alt2"=""><code plain"="">&lt;/LinearLayout&gt;</code></div><div number74="" index73=""  alt1"=""><code comments"="">//2、 在程序代码中使用RemoteViews的方法来定义image和text。然后把RemoteViews对象传到contentView字段</code></div><div number75="" index74=""  alt2"=""><code plain"="">RemoteViews contentView = </code><code keyword"="">new</code> <code plain"="">RemoteViews(getPackageName(),R.layout.view);</code></div><div number76="" index75=""  alt1"=""><code plain"="">contentView.setImageViewResource(R.id.image,R.drawable.icon);</code></div><div number77="" index76=""  alt2"=""><code plain"="">contentView.setTextViewText(R.id.text,&#8221;Hello,</code><code keyword"="">this</code> <code plain"="">message is in a custom expanded view&#8221;);</code></div><div number78="" index77=""  alt1"=""><code plain"="">notification.contentView = contentView;</code></div><div number79="" index78=""  alt2"=""><code comments"="">//3、 为Notification的contentIntent字段定义一个Intent(注意，使用自定义View不需要 setLatestEventInfo()方法)</code></div><div number80="" index79=""  alt1"=""><code plain"="">Intent notificationIntent = </code><code keyword"="">new</code> <code plain"="">Intent(</code><code keyword"="">this</code><code plain"="">,Main.</code><code keyword"="">class</code><code plain"="">);</code></div><div number81="" index80=""  alt2"=""><code plain"="">PendingIntent contentIntent = PendingIntent.getActivity(</code><code keyword"="">this</code><code plain"="">,</code><code value"="">0</code><code plain"="">,notificationIntent,</code><code value"="">0</code><code plain"="">);</code></div><div number82="" index81=""  alt1"=""><code plain"="">notification.contentIntent = contentIntent;</code></div><div number83="" index82=""  alt2"=""><code comments"="">//4、发送通知</code></div><div number84="" index83=""  alt1"=""><code plain"="">mNotificationManager.notify(</code><code value"="">2</code><code plain"="">,notification);</code></div><div number85="" index84=""  alt2"=""><code comments"="">// 以下是全部示例代码</code></div><div number86="" index85=""  alt1"=""><code comments"="">//创建一个 NotificationManager的引用</code></div><div number87="" index86=""  alt2"=""><code plain"="">String ns = Context.NOTIFICATION_SERVICE;</code></div><div number88="" index87=""  alt1"=""><code plain"="">NotificationManager mNotificationManager = (NotificationManager)getSystemService(ns);</code></div><div number89="" index88=""  alt2"=""><code comments"="">// 定义Notification的各种属性</code></div><div number90="" index89=""  alt1"=""><code keyword"="">int</code> <code plain"="">icon = R.drawable.icon; </code><code comments"="">//通知图标</code></div><div number91="" index90=""  alt2"=""><code plain"="">CharSequence tickerText = </code><code string"="">"Hello"</code><code plain"="">; </code><code comments"="">//状态栏显示的通知文本提示</code></div><div number92="" index91=""  alt1"=""><code keyword"="">long</code> <code plain"="">when = System.currentTimeMillis(); </code><code comments"="">//通知产生的时间，会在通知信息里显示</code></div><div number93="" index92=""  alt2"=""><code comments"="">//用上面的属性初始化 Nofification</code></div><div number94="" index93=""  alt1"=""><code plain"="">Notification notification = </code><code keyword"="">new</code> <code plain"="">Notification(icon,tickerText,when);</code></div><div number95="" index94=""  alt2"=""><code plain"="">RemoteViews contentView = </code><code keyword"="">new</code> <code plain"="">RemoteViews(getPackageName(),R.layout.view);</code></div><div number96="" index95=""  alt1"=""><code plain"="">contentView.setImageViewResource(R.id.image, R.drawable.iconempty);</code></div><div number97="" index96=""  alt2"=""><code plain"="">contentView.setTextViewText(R.id.text, </code><code string"="">"Hello,this is JC"</code><code plain"="">);</code></div><div number98="" index97=""  alt1"=""><code plain"="">notification.contentView = contentView;</code></div><div number99="" index98=""  alt2"=""><code plain"="">Intent notificationIntent = </code><code keyword"="">new</code> <code plain"="">Intent(</code><code keyword"="">this</code><code plain"="">,Main.</code><code keyword"="">class</code><code plain"="">);</code></div><div number100="" index99=""  alt1"=""><code plain"="">PendingIntent contentIntent = PendingIntent.getActivity(</code><code keyword"="">this</code><code plain"="">,</code><code value"="">0</code><code plain"="">,notificationIntent,</code><code value"="">0</code><code plain"="">);</code></div><div number101="" index100=""  alt2"=""><code plain"="">notification.contentIntent = contentIntent;</code></div><div number102="" index101=""  alt1"=""><code comments"="">//把Notification传递给NotificationManager</code></div><div number103="" index102=""  alt2"=""><code plain"="">mNotificationManager.notify(</code><code value"="">0</code><code plain"="">,notification);</code></div></div></td></tr></tbody></table></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/170101.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-04-05 02:34 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/04/05/170101.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用TextView/EditText应该注意的地方</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/03/28/169336.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Wed, 28 Mar 2012 12:54:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/03/28/169336.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/169336.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/03/28/169336.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/169336.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/169336.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 关于android软键盘enter键的替换与事件监听 软件盘的界面替换只有一个属性android:imeOptions，这个属性的可以取的值有 normal，actionUnspecified，actionNone，actionGo，actionSearch，actionSend，actionNext，actionDone， 例如当值为actionNext时enter键外观变成一个向下箭头，而值为...&nbsp;&nbsp;<a href='http://www.cppblog.com/guojingjia2006/archive/2012/03/28/169336.html'>阅读全文</a><img src ="http://www.cppblog.com/guojingjia2006/aggbug/169336.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-03-28 20:54 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/03/28/169336.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>android中onMeasure初看,深入理解布局之一!(转)</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/03/27/169214.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Tue, 27 Mar 2012 15:59:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/03/27/169214.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/169214.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/03/27/169214.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/169214.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/169214.html</trackback:ping><description><![CDATA[<div><p>今天学习android自定义组件:docs/guide/topics/ui/custom-components.html</p>  <p>其中有两个对布局界面影响很的方法,onDraw(),和onMeasure().</p>  <p>onDraw()比较好理解.onMeasure()就比较难理解一些,也更复杂些 ,引用文档中的说法就是:</p>    <blockquote>   onMeasure() is a little more involved.  </blockquote> 其实还有另一个方面的原因就是我对这个单词measure不是很知道,然后果了下词典,就放了下心,确实是测量的意思.    <p>实现onMeasure()方法基本需要完成下面三个方面的事情(最终结果是你自己写相应代码得出测量值并调用view的一个方法进行设置,告诉给你的view安排位置大小的父容器你要多大的空间.):</p>  <p>1.传递进来的参数,widthMeasureSpec,和heightMeasureSpec是你对你应该得出来的测量值的限制.</p>  <p>&nbsp;</p>  <blockquote>   The overidden onMeasure() method is called with width and height  measure specifications(widthMeasureSpec and heightMeasureSpec  parameters,both are integer codes representing dimensions) which should  be treated as requirements for the restrictions on the width and height  measurements you should produce.  </blockquote>  <br /> 2. 你在onMeasure计算出来设置的width和height将被用来渲染组件.应当尽量在传递进来的width和height 声明之间.    <p>虽然你也可以选择你设置的尺寸超过传递进来的声明.但是这样的话,父容器可以选择,如clipping,scrolling,或者抛出异常,或者(也许是用新的声明参数)再次调用onMeasure()<br /> </p>  <blockquote>   Your component's onMeasure() method should calculate a measurement  width and height which will be required to render the component.it  should try to stay within the specified passed in.although it can choose  to exceed them(in this case,the parent can choose what to do,including  clipping,scrolling,throwing an excption,or asking the onMeasure to try  again,perhaps with different measurement specifications).  </blockquote>  <br /> 3.一但width和height计算好了,就应该调用View.setMeasuredDimension(int width,int height)方法,否则将导致抛出异常.      <blockquote>   Once the width and height are calculated,the setMeasureDimension(int  width,int height) method must be called with the calculated  measurements.Failure to do this will result in an exceptiion being  thrown  </blockquote> &nbsp; &nbsp;    <p>在Android提提供的一个自定义View示例中(在API demos 中的 view/LabelView)可以看到一个重写onMeasure()方法的</p>  <p>实例,也比较好理解.</p>    <div "="" id="highlighter_129876"><div><div alt1"=""><table><tbody><tr><td><code>01</code></td><td><code>/**</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>02</code></td><td><code>&nbsp;</code><code>* @see android.view.View#measure(int, int)</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>03</code></td><td><code>&nbsp;</code><code>*/</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>04</code></td><td><code>@Override</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>05</code></td><td><code>protected</code> <code>void</code> <code>onMeasure(</code><code>int</code> <code>widthMeasureSpec, </code><code>int</code> <code>heightMeasureSpec) {</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>06</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>setMeasuredDimension(measureWidth(widthMeasureSpec),</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>07</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>measureHeight(heightMeasureSpec));</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>08</code></td><td><code>}</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>09</code></td><td>&nbsp;</td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>10</code></td><td><code>/**</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>11</code></td><td><code>&nbsp;</code><code>* Determines the width of this view</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>12</code></td><td><code>&nbsp;</code><code>* @param measureSpec A measureSpec packed into an int</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>13</code></td><td><code>&nbsp;</code><code>* @return The width of the view, honoring constraints from measureSpec</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>14</code></td><td><code>&nbsp;</code><code>*/</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>15</code></td><td><code>private</code> <code>int</code> <code>measureWidth(</code><code>int</code> <code>measureSpec) {</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>16</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>int</code> <code>result = </code><code>0</code><code>;</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>17</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>int</code> <code>specMode = MeasureSpec.getMode(measureSpec);</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>18</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>int</code> <code>specSize = MeasureSpec.getSize(measureSpec);</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>19</code></td><td>&nbsp;</td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>20</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>if</code> <code>(specMode == MeasureSpec.EXACTLY) {</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>21</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>// We were told how big to be</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>22</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>result = specSize;</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>23</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>} </code><code>else</code> <code>{</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>24</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>// Measure the text</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>25</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>result = (</code><code>int</code><code>) mTextPaint.measureText(mText) + getPaddingLeft()</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>26</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>+ getPaddingRight();</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>27</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>if</code> <code>(specMode == MeasureSpec.AT_MOST) {</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>28</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>// Respect AT_MOST value if that was what is called for by measureSpec</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>29</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>result = Math.min(result, specSize);</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>30</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>}</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>31</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>}</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>32</code></td><td>&nbsp;</td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>33</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>return</code> <code>result;</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>34</code></td><td><code>}</code></td></tr></tbody></table></div></div></div>  <p> </p>    <p>&nbsp;</p>  <p>直接看measureWidth()</p>  <p>首先看到的是参数,分别代表宽度和高度的MeasureSpec</p>  <p>android2.2文档中对于MeasureSpec中的说明是:</p>  <p>一个MeasureSpec封装了从父容器传递给子容器的布局需求.</p>  <p>每一个MeasureSpec代表了一个宽度,或者高度的说明.</p>  <p>一个MeasureSpec是一个大小跟模式的组合值.一共有三种模式.</p>    <blockquote>   A MeasureSpec encapsulates the layout requirements passed from parent  to child Each MeasureSpec represents a requirement for either the width  or the height.A MeasureSpec is compsized of a size and a mode.There are  three possible modes:  </blockquote>  <br /> &nbsp;(1)UPSPECIFIED :父容器对于子容器没有任何限制,子容器想要多大就多大.      <blockquote>   UNSPECIFIED The parent has not imposed any constraint on the child.It can be whatever size it wants  </blockquote>  <br /> &nbsp;(2) EXACTLY    <p>&nbsp;父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间.</p>    <blockquote>   EXACTLY The parent has determined and exact size for the child.The  child is going to be given those bounds regardless of how big it wants  to be.  </blockquote>  <br /> (3) AT_MOST    <p>&nbsp;子容器可以是声明大小内的任意大小.</p>    <blockquote>   AT_MOST The child can be as large as it wants up to the specified size  </blockquote>  <br /> MeasureSpec是View类下的静态公开类,MeasureSpec中的值作为一个整型是为了减少对象的分配开支.此类用于    <p>将size和mode打包或者解包为一个整型.</p>    <blockquote>   MeasureSpecs are implemented as ints to reduce object allocation.This  class is provided to pack and unpack the size,mode tuple into the int  </blockquote>  <br /> 我比较好奇的是怎么样将两个值打包到一个int中,又如何解包.    <p>MeasureSpec类代码如下 :(注释已经被我删除了,因为在上面说明了.)</p>    <div "="" id="highlighter_954075"><div><div alt1"=""><table><tbody><tr><td><code>01</code></td><td><code>public</code> <code>static</code> <code>class</code> <code>MeasureSpec {</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>02</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>private</code> <code>static</code> <code>final</code> <code>int</code> <code>MODE_SHIFT = </code><code>30</code><code>;</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>03</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>private</code> <code>static</code> <code>final</code> <code>int</code> <code>MODE_MASK&nbsp; = </code><code>0x3</code> <code>&lt;&lt; MODE_SHIFT;</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>04</code></td><td>&nbsp;</td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>05</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>public</code> <code>static</code> <code>final</code> <code>int</code> <code>UNSPECIFIED = </code><code>0</code> <code>&lt;&lt; MODE_SHIFT;</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>06</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>public</code> <code>static</code> <code>final</code> <code>int</code> <code>EXACTLY&nbsp;&nbsp;&nbsp;&nbsp; = </code><code>1</code> <code>&lt;&lt; MODE_SHIFT;</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>07</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>public</code> <code>static</code> <code>final</code> <code>int</code> <code>AT_MOST&nbsp;&nbsp;&nbsp;&nbsp; = </code><code>2</code> <code>&lt;&lt; MODE_SHIFT;</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>08</code></td><td>&nbsp;</td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>09</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>public</code> <code>static</code> <code>int</code> <code>makeMeasureSpec(</code><code>int</code> <code>size, </code><code>int</code> <code>mode) {</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>10</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>return</code> <code>size + mode;</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>11</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>}</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>12</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>public</code> <code>static</code> <code>int</code> <code>getMode(</code><code>int</code> <code>measureSpec) {</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>13</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>return</code> <code>(measureSpec &amp; MODE_MASK);</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>14</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>}</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>15</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>public</code> <code>static</code> <code>int</code> <code>getSize(</code><code>int</code> <code>measureSpec) {</code></td></tr></tbody></table></div><div alt2"=""><table><tbody><tr><td><code>16</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code>return</code> <code>(measureSpec &amp; ~MODE_MASK);</code></td></tr></tbody></table></div><div alt1"=""><table><tbody><tr><td><code>17</code></td><td><code>&nbsp;&nbsp;&nbsp;&nbsp;</code><code>}&nbsp; }</code></td></tr></tbody></table></div></div></div>  <p> </p>    <p>我无聊的将他们的十进制值打印出来了:</p>  <p>mode_shift=30,mode_mask=-1073741824,UNSPECIFIED=0,EXACTLY=1073741824,AT_MOST=-2147483648</p>  <p>然后觉得也应该将他们的二进制值打印出来,如下:</p>    <p>mode_shift=11110, // 30</p>  <p>mode_mask=11000000000000000000000000000000,</p>  <p>UNSPECIFIED=0,&nbsp;</p>  <p>EXACTLY=1000000000000000000000000000000,&nbsp;</p>  <p>AT_MOST=10000000000000000000000000000000</p>  <p>&nbsp;</p>  <div "="" id="highlighter_775868"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td><code>MODE_MASK&nbsp; = </code><code>0x3</code> <code>&lt;&lt; MODE_SHIFT </code><code>//也就是说MODE_MASK是由11左移30位得到的.因为Java用补码表示数值.最后得到的值最高位是1所以就是负数了</code></td></tr></tbody></table></div></div></div>  <div "="" id="highlighter_694660"><div><div alt1"=""><table><tbody><tr><td><code>1</code></td><td>&nbsp;</td></tr></tbody></table></div></div></div>对于上面的数值我们应该这样想,不要把0x3看成3而要看成二进制的11,    <p>而把MODE_SHIFF就看成30.那为什么是二进制 的11呢?</p>  <p>呢,因为只有三各模式,如果有四种模式就是111了因为111三个位才可以有四种组合对吧.</p>  <p>我们这样来看,</p>    <p>UNSPECIFIED=00000000000000000000000000000000,&nbsp;</p>  <p>&nbsp; &nbsp; &nbsp; EXACTLY=01000000000000000000000000000000,&nbsp;</p>  <p>&nbsp; &nbsp; AT_MOST=10000000000000000000000000000000</p>  <p>也就是说,0,1,2</p>  <p>对应 &nbsp; 00,01,10</p>  <p>当跟11想与时 &nbsp;00 &amp;11 还是得到 00,11&amp;01 -&gt; 01,10&amp;</p>  <p>我觉得到了这个份上相信,看我博客的也都理解了.</p>    <p>&nbsp;return (measureSpec &amp; ~MODE_MASK);应该是&nbsp;return (measureSpec &amp; (~MODE_MASK));</p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/169214.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-03-27 23:59 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/03/27/169214.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>android 焦点</title><link>http://www.cppblog.com/guojingjia2006/archive/2012/03/24/168797.html</link><dc:creator>小果子</dc:creator><author>小果子</author><pubDate>Sat, 24 Mar 2012 07:33:00 GMT</pubDate><guid>http://www.cppblog.com/guojingjia2006/archive/2012/03/24/168797.html</guid><wfw:comment>http://www.cppblog.com/guojingjia2006/comments/168797.html</wfw:comment><comments>http://www.cppblog.com/guojingjia2006/archive/2012/03/24/168797.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/guojingjia2006/comments/commentRss/168797.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/guojingjia2006/services/trackbacks/168797.html</trackback:ping><description><![CDATA[<div><p>Android应用启动时，焦点直接在EditText上，输入法直接打开，影响界面美观。</p><p>导致进入画面入就打开输入法，影响界面美观。</p><p>默认焦点的顺序是：从上倒下 从左到右第一个可以输入的控件作为焦点 可以使用：</p><p>btSearch.setFocusable(true);</p><p>btSearch.requestFocus();</p><p>btSearch.setFocusableInTouchMode(true);</p><p>也可以：</p><p>在EditText前面放置一个看不到的LinearLayout，让他率先获取焦点：&nbsp;</p><p>&lt;LinearLayout android:focusable="true" android:focusableInTouchMode="true" android:layout_width="0px" android:layout_height="0px"/&gt;</p></div><img src ="http://www.cppblog.com/guojingjia2006/aggbug/168797.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/guojingjia2006/" target="_blank">小果子</a> 2012-03-24 15:33 <a href="http://www.cppblog.com/guojingjia2006/archive/2012/03/24/168797.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>