﻿<?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>IT博客-游子的博客</title><link>http://www.cnitblog.com/liaoqingshan/</link><description>慈母手中线，游子身上衣，
临行密密缝，意恐迟迟归，
谁言寸草心，报得三春晖。


数据读取中，请稍候......</description><language>zh-cn</language><lastBuildDate>Tue, 21 Apr 2026 04:55:06 GMT</lastBuildDate><pubDate>Tue, 21 Apr 2026 04:55:06 GMT</pubDate><ttl>60</ttl><item><title>移动端跨平台开发的深度解析--转载</title><link>http://www.cnitblog.com/liaoqingshan/archive/2020/03/04/92088.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Wed, 04 Mar 2020 15:21:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2020/03/04/92088.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/92088.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2020/03/04/92088.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/92088.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/92088.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 跨平台一直是老生常谈的话题，cordova、ionic、react-native、weex、kotlin-native、flutter等跨平台框架的百花齐放，颇有一股推倒原生开发者的势头。（事实上更多是共存发展）看完本篇，相信你会对于当下跨平台移动开发的现状、实现原理、框架的选择等有更深入的理解。&nbsp;&nbsp;<a href='http://www.cnitblog.com/liaoqingshan/archive/2020/03/04/92088.html'>阅读全文</a><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/92088.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2020-03-04 23:21 <a href="http://www.cnitblog.com/liaoqingshan/archive/2020/03/04/92088.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一晃又三年</title><link>http://www.cnitblog.com/liaoqingshan/archive/2019/05/20/91440.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Mon, 20 May 2019 08:29:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2019/05/20/91440.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/91440.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2019/05/20/91440.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/91440.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/91440.html</trackback:ping><description><![CDATA[不看不知道，一看吓一跳。原来我5年前就搞android了，可是现在仍是个菜鸟，哈哈。<img src ="http://www.cnitblog.com/liaoqingshan/aggbug/91440.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2019-05-20 16:29 <a href="http://www.cnitblog.com/liaoqingshan/archive/2019/05/20/91440.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>多年未见</title><link>http://www.cnitblog.com/liaoqingshan/archive/2016/05/13/90433.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Fri, 13 May 2016 09:49:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2016/05/13/90433.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/90433.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2016/05/13/90433.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/90433.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/90433.html</trackback:ping><description><![CDATA[ 你还好吗？<img src ="http://www.cnitblog.com/liaoqingshan/aggbug/90433.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2016-05-13 17:49 <a href="http://www.cnitblog.com/liaoqingshan/archive/2016/05/13/90433.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XML自动缩进</title><link>http://www.cnitblog.com/liaoqingshan/archive/2015/07/24/90157.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Fri, 24 Jul 2015 02:56:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2015/07/24/90157.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/90157.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2015/07/24/90157.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/90157.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/90157.html</trackback:ping><description><![CDATA[用_di_IXMLDocument生成的xml文件，一个空格也没有，上网找了半天，整整半天，终于找到方法了。<br />&nbsp;_di_IXMLDocument doc;<br /><br />&nbsp;doc = NewXMLDocument();<br />&nbsp;doc-&gt;Encoding = "GB2312";<br />&nbsp;doc-&gt;Active = true;<br />&nbsp;doc-&gt;Version = "1.0";<br />&nbsp;//doc-&gt;SetNodeIndentStr("******\n");<br />&nbsp;doc-&gt;Options = doc-&gt;Options &lt;&lt; doNodeAutoIndent;<br />......<br />&nbsp;doc-&gt;SaveToFile( stS );<br /><br />其中，最关键的行是doc-&gt;Options = doc-&gt;Options &lt;&lt; doNodeAutoIndent，没有这行，SetNodeIndentStr的是无效的。<br />网上大多数是delphi的代码，C++ BUILDER的太少了。<br />这样生成的xml有回车，换行，tab.<br /><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/90157.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2015-07-24 10:56 <a href="http://www.cnitblog.com/liaoqingshan/archive/2015/07/24/90157.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android Activity和Intent机制学习笔记----转载</title><link>http://www.cnitblog.com/liaoqingshan/archive/2015/02/08/89987.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Sun, 08 Feb 2015 05:44:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2015/02/08/89987.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/89987.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2015/02/08/89987.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/89987.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/89987.html</trackback:ping><description><![CDATA[<p align="justify" style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;"><strong>Activity</strong></p><p align="justify" style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;">Android中，Activity是所有程序的根本，所有程序的流程都运行在Activity之中，Activity具有自己的生命周期（见<a href="http://www.cnblogs.com/feisky/archive/2010/01/01/1637427.html" style="color: #1d58d1;">http://www.cnblogs.com/feisky/archive/2010/01/01/1637427.html</a>，由系统控制生命周期，程序无法改变，但可以用<strong>onSaveInstanceState</strong>保存其状态）。</p><p align="justify" style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;">对于Activity，关键是其<strong>生命周期</strong>的把握（如下图），其次就是状态的保存和恢复（onSaveInstanceState onRestoreInstanceState），以及Activity之间的跳转和数据传输（<strong>intent</strong>）。</p><p align="justify" style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;"><img alt="activity_lifecycle" src="http://images.cnblogs.com/cnblogs_com/feisky/WindowsLiveWriter/6aad9ec8a679_D53B/activity_lifecycle_thumb.png" width="286" height="373" style="border: 0px;" /></p><p align="justify" style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;">Activity中常用的函数有<strong>SetContentView()&nbsp;&nbsp; findViewById()&nbsp;&nbsp;&nbsp; finish()&nbsp;&nbsp; startActivity()，</strong>其生命周期涉及的函数有：</p><p align="justify" style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;"><strong><code>void onCreate(Bundle&nbsp;<em>savedInstanceState</em>)</code><br /><code>void onStart()</code><br /><code>void onRestart()</code><br /><code>void onResume()</code><br /><code>void onPause()</code><br /><code>void onStop()</code><br /><code>void onDestroy()</code></strong></p><p align="justify" style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;"><code><strong>注意的是，Activity的使用需要在Manifest文件中添加相应的&lt;Activity&gt;，并设置其属性和intent-filter。</strong></code></p><p style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;"><strong>Intent</strong></p><p align="justify" style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;">Android中提供了Intent机制来协助应用间的交互与通讯，Intent负责对应用中一次操作的动作、动作涉及数据、附加数据进行描述，Android则根据此Intent的描述，负责找到对应的组件，将 Intent传递给调用的组件，并完成组件的调用。Intent不仅可用于应用程序之间，也可用于应用程序内部的Activity/Service之间的交互。因此，Intent在这里起着一个媒体中介的作用，专门提供组件互相调用的相关信息，实现调用者与被调用者之间的解耦。在SDK中给出了Intent作用的表现形式为：</p><ul style="margin-left: 45px; padding-left: 0px; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;"><li style="list-style: inherit !important;">通过<code><code><a href="http://androidappdocs.appspot.com/reference/android/content/Context.html#startActivity(android.content.Intent)" style="color: #1d58d1;">Context.startActivity()</a></code></code>&nbsp;or<code><code><a href="http://androidappdocs.appspot.com/reference/android/app/Activity.html#startActivityForResult(android.content.Intent, int)" style="color: #1d58d1;">Activity.startActivityForResult()</a></code></code>&nbsp;启动一个Activity；</li><li style="list-style: inherit !important;">通过&nbsp;<code><code><a href="http://androidappdocs.appspot.com/reference/android/content/Context.html#startService(android.content.Intent)" style="color: #1d58d1;">Context.startService()</a></code></code>&nbsp;启动一个服务，或者通过<code><code><a href="http://androidappdocs.appspot.com/reference/android/content/Context.html#bindService(android.content.Intent, android.content.ServiceConnection, int)" style="color: #1d58d1;">Context.bindService()</a></code></code>&nbsp;和后台服务交互；</li><li style="list-style: inherit !important;">通过广播方法(比如&nbsp;<code><code><a href="http://androidappdocs.appspot.com/reference/android/content/Context.html#sendBroadcast(android.content.Intent)" style="color: #1d58d1;">Context.sendBroadcast()</a></code></code>,<code><code><a href="http://androidappdocs.appspot.com/reference/android/content/Context.html#sendOrderedBroadcast(android.content.Intent, java.lang.String)" style="color: #1d58d1;">Context.sendOrderedBroadcast()</a></code></code>,&nbsp;&nbsp;<code><code><a href="http://androidappdocs.appspot.com/reference/android/content/Context.html#sendStickyBroadcast(android.content.Intent)" style="color: #1d58d1;">Context.sendStickyBroadcast()</a></code></code>) 发给broadcast receivers。</li></ul><p style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;"><strong>Intent属性的设置</strong>，包括以下几点：（以下为XML中定义，当然也可以通过Intent类的方法来获取和设置）</p><p align="justify" style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;">（1）Action，也就是要执行的动作</p><p align="justify" style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;">SDk中定义了一些标准的动作，包括</p><span style="border-collapse: separate; font-stretch: normal; font-family: simsun; border-spacing: 0px;"><span style="line-height: 16px; font-family: arial, sans-serif; color: #333333; font-size: 13px;"><table style="border: 0px solid silver; border-collapse: collapse; word-break: break-word; padding: 0px; margin: 1em 0px 0px 1em; empty-cells: show; font-size: 1em;"><tbody style="padding: 0px; border-width: 0px; margin: 0px;"><tr style="padding: 0px; border-width: 0px; margin: 0px;"><th style="border: 1px solid #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top; background-color: #dee8f1;">onstant</th><th style="border: 1px solid #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top; background-color: #dee8f1;">Target component</th><th style="border: 1px solid #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top; background-color: #dee8f1;">Action</th></tr><tr style="padding: 0px; border-width: 0px; margin: 0px;"><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;"><code style="line-height: 1em; color: #007000;">ACTION_CALL</code></td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">activity</td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">Initiate a phone call.</td></tr><tr style="padding: 0px; border-width: 0px; margin: 0px;"><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;"><code style="line-height: 1em; color: #007000;">ACTION_EDIT</code></td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">activity</td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">Display data for the user to edit.</td></tr><tr style="padding: 0px; border-width: 0px; margin: 0px;"><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;"><code style="line-height: 1em; color: #007000;">ACTION_MAIN</code></td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">activity</td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">Start up as the initial activity of a task, with no data input and no returned output.</td></tr><tr style="padding: 0px; border-width: 0px; margin: 0px;"><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;"><code style="line-height: 1em; color: #007000;">ACTION_SYNC</code></td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">activity</td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">Synchronize data on a server with data on the mobile device.</td></tr><tr style="padding: 0px; border-width: 0px; margin: 0px;"><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;"><code style="line-height: 1em; color: #007000;">ACTION_BATTERY_LOW</code></td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">broadcast receiver</td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">A warning that the battery is low.</td></tr><tr style="padding: 0px; border-width: 0px; margin: 0px;"><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;"><code style="line-height: 1em; color: #007000;">ACTION_HEADSET_PLUG</code></td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">broadcast receiver</td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">A headset has been plugged into the device, or unplugged from it.</td></tr><tr style="padding: 0px; border-width: 0px; margin: 0px;"><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;"><code style="line-height: 1em; color: #007000;">ACTION_SCREEN_ON</code></td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">broadcast receiver</td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">The screen has been turned on.</td></tr><tr style="padding: 0px; border-width: 0px; margin: 0px;"><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;"><code style="line-height: 1em; color: #007000;">ACTION_TIMEZONE_CHANGED</code></td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">broadcast receiver</td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">The setting for the time zone has changed.</td></tr></tbody></table></span></span><p align="justify" style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;">&nbsp;</p><p align="justify" style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;">当然，也可以自定义动作（自定义的动作在使用时，需要加上包名作为前缀，如"<code>com.example.project.SHOW_COLOR</code>&#8221;），并可定义相应的Activity来处理我们的自定义动作。</p><p align="justify" style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;">（2）Data，也就是执行动作要操作的数据</p><p align="justify" style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;">Android中采用指向数据的一个URI来表示，如在联系人应用中，一个指向某联系人的URI可能为：content://contacts/1。对于不同的动作，其URI数据的类型是不同的（可以设置type属性指定特定类型数据），如ACTION_EDIT指定Data为文件URI，打电话为tel:URI，访问网络为http:URI，而由content provider提供的数据则为<code>content:</code>&nbsp;URIs。</p><p align="justify" style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;">（3）type（数据类型），显式指定Intent的数据类型（MIME）。一般Intent的数据类型能够根据数据本身进行判定，但是通过设置这个属性，可以强制采用显式指定的类型而不再进行推导。</p><p style="margin: 10px auto; font-family: Verdana, 'Lucida Grande', Arial, Helvetica, sans-serif; font-size: 12px; line-height: 18px;">（4）category（类别），被执行动作的附加信息。例如 LAUNCHER_CATEGORY 表示Intent 的接受者应该在Launcher中作为顶级应用出现；而ALTERNATIVE_CATEGORY表示当前的Intent是一系列的可选动作中的一个，这些动作可以在同一块数据上执行。还有其他的为</p><span style="widows: 2; border-collapse: separate; font-stretch: normal; font-family: simsun; orphans: 2; border-spacing: 0px;"><span style="line-height: 16px; font-family: arial, sans-serif; color: #333333; font-size: 13px;"><table style="border: 0px solid silver; border-collapse: collapse; word-break: break-word; padding: 0px; margin: 1em 0px 0px 1em; empty-cells: show; font-size: 1em;"><tbody style="padding: 0px; border-width: 0px; margin: 0px;"><tr style="padding: 0px; border-width: 0px; margin: 0px;"><th style="border: 1px solid #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top; background-color: #dee8f1;">Constant</th><th style="border: 1px solid #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top; background-color: #dee8f1;">Meaning</th></tr><tr style="padding: 0px; border-width: 0px; margin: 0px;"><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;"><code style="line-height: 1em; color: #007000;">CATEGORY_BROWSABLE</code></td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">The target activity can be safely invoked by the browser to display data referenced by a link &#8212; for example, an image or an e-mail message.</td></tr><tr style="padding: 0px; border-width: 0px; margin: 0px;"><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;"><code style="line-height: 1em; color: #007000;">CATEGORY_GADGET</code></td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">The activity can be embedded inside of another activity that hosts gadgets.</td></tr><tr style="padding: 0px; border-width: 0px; margin: 0px;"><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;"><code style="line-height: 1em; color: #007000;">CATEGORY_HOME</code></td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">The activity displays the home screen, the first screen the user sees when the device is turned on or when the HOME key is pressed.</td></tr><tr style="padding: 0px; border-width: 0px; margin: 0px;"><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;"><code style="line-height: 1em; color: #007000;">CATEGORY_LAUNCHER</code></td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">The activity can be the initial activity of a task and is listed in the top-level application launcher.</td></tr><tr style="padding: 0px; border-width: 0px; margin: 0px;"><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;"><code style="line-height: 1em; color: #007000;">CATEGORY_PREFERENCE</code></td><td style="font-size: 12px; border-style: solid; border-color: #cccccc; border-collapse: collapse; padding: 6px 12px; margin: 0px; vertical-align: top;">The target activity is a preference panel.</td></tr></tbody></table><p style="margin: 10px auto;">&nbsp;</p><p style="margin: 10px auto;">（5）component（组件），指定Intent的的目标组件的类名称。通常 Android会根据Intent 中包含的其它属性的信息，比如action、data/type、category进行查找，最终找到一个与之匹配的目标组件。但是，如果 component这个属性有指定的话，将直接使用它指定的组件，而不再执行上述查找过程。指定了这个属性以后，Intent的其它所有属性都是可选的。</p><p style="margin: 10px auto;">（6）extras（附加信息），是其它所有附加信息的集合。使用extras可以为组件提供扩展信息，比如，如果要执行&#8220;发送电子邮件&#8221;这个动作，可以将电子邮件的标题、正文等保存在extras里，传给电子邮件发送组件。</p><p style="margin: 10px auto;">理解Intent的关键之一是理解清楚Intent的两种基本用法：一种是<strong>显式的Intent</strong>，即在构造Intent对象时就指定接收者；另一种是<strong>隐式的Intent</strong>，即Intent的发送者在构造Intent对象时，并不知道也不关心接收者是谁，有利于降低发送者和接收者之间的耦合。</p><p style="margin: 10px auto;">对于显式Intent，Android不需要去做解析，因为目标组件已经很明确，Android需要解析的是那些隐式Intent，通过解析，将 Intent映射给可以处理此Intent的Activity、IntentReceiver或Service。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p><p style="margin: 10px auto;">Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Intent，最终找到匹配的Intent。在这个解析过程中，Android是通过Intent的action、type、category这三个属性来进行判断的，判断方法如下：</p><ul style="margin-left: 45px; padding-left: 0px;"><li style="list-style: inherit !important;">如果Intent指明定了action，则目标组件的IntentFilter的action列表中就必须包含有这个action，否则不能匹配；</li><li style="list-style: inherit !important;">如果Intent没有提供type，系统将从data中得到数据类型。和action一样，目标组件的数据类型列表中必须包含Intent的数据类型，否则不能匹配。</li><li style="list-style: inherit !important;">如果Intent中的数据不是content: 类型的URI，而且Intent也没有明确指定它的type，将根据Intent中数据的scheme （比如 http: 或者<a href="http://www.androidcn.net/wiki/index.php/Reference/android/content/mailto" style="color: #1d58d1;"><u>mailto</u></a>:） 进行匹配。同上，Intent 的scheme必须出现在目标组件的scheme列表中。</li><li style="list-style: inherit !important;">如果Intent指定了一个或多个category，这些类别必须<strong>全部</strong>出现在组建的类别列表中。比如Intent中包含了两个类别：LAUNCHER_CATEGORY 和 ALTERNATIVE_CATEGORY，解析得到的目标组件必须至少包含这两个类别。</li></ul><p style="margin: 10px auto;"><strong>Intent-Filter的定义</strong></p><p style="margin: 10px auto;">一些属性设置的例子：</p><pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 22px; white-space: pre-wrap; word-wrap: break-word; font-size: 1em;">&lt;action android:name="com.example.project.SHOW_CURRENT" /&gt;</pre><pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 22px; white-space: pre-wrap; word-wrap: break-word; font-size: 1em;">&lt;category android:name="android.intent.category.DEFAULT" /&gt;</pre><pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 22px; white-space: pre-wrap; word-wrap: break-word; font-size: 1em;">&lt;data android:mimeType="video/mpeg" android:scheme="http" . . . /&gt; </pre><pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 22px; white-space: pre-wrap; word-wrap: break-word; font-size: 1em;">&lt;data android:mimeType="image/*" /&gt;</pre><pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 22px; white-space: pre-wrap; word-wrap: break-word; font-size: 1em;">&lt;data android:scheme="http" android:type="video/*" /&gt;</pre><p style="margin: 10px auto;">完整的实例</p><span style="border-collapse: separate; font-stretch: normal; font-size: medium; line-height: normal; font-family: simsun; color: #000000; border-spacing: 0px;"><span style="font-family: arial, sans-serif; color: #333333; font-size: 13px;"><pre style="margin-top: 0px; margin-left: 1em; white-space: pre-wrap; word-wrap: break-word; font-size: 1em; border: 1px solid #cccccc; padding: 10px; overflow: auto; color: #007000; background-color: #fafafa;"><span style="color: #000088;">&lt;activity</span> <span style="color: #660066;">android:name</span><span style="color: #666600;">=</span><span style="color: #008800;">"NotesList"</span> <span style="color: #660066;">android:label</span><span style="color: #666600;">=</span><span style="color: #008800;">"@string/title_notes_list"</span><span style="color: #000088;">&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000088;">&lt;intent-filter&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000088;">&lt;action</span> <span style="color: #660066;">android:name</span><span style="color: #666600;">=</span><span style="color: #008800;">"android.intent.action.MAIN"</span> <span style="color: #000088;">/&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000088;">&lt;category</span> <span style="color: #660066;">android:name</span><span style="color: #666600;">=</span><span style="color: #008800;">"android.intent.category.LAUNCHER"</span> <span style="color: #000088;">/&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000088;">&lt;/intent-filter&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000088;">&lt;intent-filter&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000088;">&lt;action</span> <span style="color: #660066;">android:name</span><span style="color: #666600;">=</span><span style="color: #008800;">"android.intent.action.VIEW"</span> <span style="color: #000088;">/&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000088;">&lt;action</span> <span style="color: #660066;">android:name</span><span style="color: #666600;">=</span><span style="color: #008800;">"android.intent.action.EDIT"</span> <span style="color: #000088;">/&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000088;">&lt;action</span> <span style="color: #660066;">android:name</span><span style="color: #666600;">=</span><span style="color: #008800;">"android.intent.action.PICK"</span> <span style="color: #000088;">/&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000088;">&lt;category</span> <span style="color: #660066;">android:name</span><span style="color: #666600;">=</span><span style="color: #008800;">"android.intent.category.DEFAULT"</span> <span style="color: #000088;">/&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000088;">&lt;data</span> <span style="color: #660066;">android:mimeType</span><span style="color: #666600;">=</span><span style="color: #008800;">"vnd.android.cursor.dir/vnd.google.note"</span> <span style="color: #000088;">/&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000088;">&lt;/intent-filter&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000088;">&lt;intent-filter&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000088;">&lt;action</span> <span style="color: #660066;">android:name</span><span style="color: #666600;">=</span><span style="color: #008800;">"android.intent.action.GET_CONTENT"</span> <span style="color: #000088;">/&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000088;">&lt;category</span> <span style="color: #660066;">android:name</span><span style="color: #666600;">=</span><span style="color: #008800;">"android.intent.category.DEFAULT"</span> <span style="color: #000088;">/&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000088;">&lt;data</span> <span style="color: #660066;">android:mimeType</span><span style="color: #666600;">=</span><span style="color: #008800;">"vnd.android.cursor.item/vnd.google.note"</span> <span style="color: #000088;">/&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000088;">&lt;/intent-filter&gt;</span><span style="color: #000000;"><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="color: #000088;">&lt;/activity&gt;</span></pre><p style="margin: 10px auto;"><strong>Intent用法实例</strong></p><p style="margin: 10px auto;"><strong>1.无参数Activity跳转</strong></p><pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 22px; white-space: pre-wrap; word-wrap: break-word; font-size: 1em;">Intent it = <span style="color: #0000ff;">new</span> Intent(Activity.Main.<span style="color: #0000ff;">this</span>, Activity2.<span style="color: #0000ff;">class</span>); <br />startActivity(it);   </pre><p style="margin: 10px auto;">&nbsp;</p><p style="margin: 10px auto;"><strong>2.向下一个Activity传递数据（使用Bundle和Intent.putExtras）</strong></p><pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 22px; white-space: pre-wrap; word-wrap: break-word; font-size: 1em;">Intent it = <span style="color: #0000ff;">new</span> Intent(Activity.Main.<span style="color: #0000ff;">this</span>, Activity2.<span style="color: #0000ff;">class</span>); <br />Bundle bundle=<span style="color: #0000ff;">new</span> Bundle(); <br />bundle.putString("<span style="color: #8b0000;">name</span>", "<span style="color: #8b0000;">This is from MainActivity!</span>"); <br />it.putExtras(bundle);       <span style="color: #008000;">// it.putExtra(&#8220;test&#8221;, "shuju&#8221;);</span> <br />startActivity(it);            <span style="color: #008000;">// startActivityForResult(it,REQUEST_CODE);</span></pre><p style="margin: 10px auto;">&nbsp;</p><p style="margin: 10px auto;">对于数据的获取可以采用：</p><pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 22px; white-space: pre-wrap; word-wrap: break-word; font-size: 1em;">Bundle bundle=getIntent().getExtras(); <br />String name=bundle.getString("<span style="color: #8b0000;">name</span>");</pre><p style="margin: 10px auto;"><strong></strong>&nbsp;</p><p style="margin: 10px auto;"><strong>3.向上一个Activity返回结果（使用setResult，针对startActivityForResult(it,REQUEST_CODE)启动的Activity）</strong></p><pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 22px; white-space: pre-wrap; word-wrap: break-word; font-size: 1em;">Intent intent=getIntent();         <br />Bundle bundle2=<span style="color: #0000ff;">new</span> Bundle();         <br />bundle2.putString("<span style="color: #8b0000;">name</span>", "<span style="color: #8b0000;">This is from ShowMsg!</span>");         <br />intent.putExtras(bundle2);         <br />setResult(RESULT_OK, intent);</pre><p style="margin: 10px auto;"></p><p style="margin: 10px auto;"><strong>4.回调上一个Activity的结果处理函数（onActivityResult）</strong></p><pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 22px; white-space: pre-wrap; word-wrap: break-word; font-size: 1em;"><span style="font-family: arial, sans-serif; background-color: #ffffff;">@Override</span></pre><pre style="margin-top: 0px; margin-bottom: 0px; margin-left: 22px; white-space: pre-wrap; word-wrap: break-word; background-color: #ffffff;">    <span style="color: #0000ff;">protected</span> <span style="color: #0000ff;">void</span> onActivityResult(<span style="color: #0000ff;">int</span> requestCode, <span style="color: #0000ff;">int</span> resultCode, Intent data) {
        <span style="color: #008000;">// TODO Auto-generated method stub</span>
        <span style="color: #0000ff;">super</span>.onActivityResult(requestCode, resultCode, data);
        <span style="color: #0000ff;">if</span> (requestCode==REQUEST_CODE){
            <span style="color: #0000ff;">if</span>(resultCode==RESULT_CANCELED)
                  setTitle("<span style="color: #8b0000;">cancle</span>");
            <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (resultCode==RESULT_OK) {
                 String temp=<span style="color: #0000ff;">null</span>;
                 Bundle bundle=data.getExtras();
                 <span style="color: #0000ff;">if</span>(bundle!=<span style="color: #0000ff;">null</span>)   temp=bundle.getString("<span style="color: #8b0000;">name</span>");
                 setTitle(temp);
            }
        }
    }</pre><p style="margin: 10px auto;"><strong>下面是转载来的其他的一些Intent用法实例（转自javaeye）</strong></p><p style="margin: 10px auto;"><strong>显示网页<br /></strong>&nbsp;&nbsp; 1. Uri uri = Uri.parse("http://google.com");&nbsp;&nbsp;<br />&nbsp;&nbsp; 2. Intent it = new Intent(Intent.ACTION_VIEW, uri);&nbsp;&nbsp;<br />&nbsp;&nbsp; 3. startActivity(it);</p><p style="margin: 10px auto;"><strong>显示地图</strong><br />&nbsp;&nbsp; 1. Uri uri = Uri.parse("geo:38.899533,-77.036476");&nbsp;&nbsp;<br />&nbsp;&nbsp; 2. Intent it = new Intent(Intent.ACTION_VIEW, uri);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp; 3. startActivity(it);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp; 4. //其他 geo URI 範例&nbsp;&nbsp;<br />&nbsp;&nbsp; 5. //geo:latitude,longitude&nbsp;&nbsp;<br />&nbsp;&nbsp; 6. //geo:latitude,longitude?z=zoom&nbsp;&nbsp;<br />&nbsp;&nbsp; 7. //geo:0,0?q=my+street+address&nbsp;&nbsp;<br />&nbsp;&nbsp; 8. //geo:0,0?q=business+near+city&nbsp;&nbsp;<br />&nbsp;&nbsp; 9. //google.streetview:cbll=lat,lng&amp;cbp=1,yaw,,pitch,zoom&amp;mz=mapZoom</p><p style="margin: 10px auto;"><strong>路径规划</strong><br />&nbsp;&nbsp; 1. Uri uri = Uri.parse("http://maps.google.com/maps?f=d&amp;saddr=startLat%20startLng&amp;daddr=endLat%20endLng&amp;hl=en");&nbsp;&nbsp;<br />&nbsp;&nbsp; 2. Intent it = new Intent(Intent.ACTION_VIEW, uri);&nbsp;&nbsp;<br />&nbsp;&nbsp; 3. startActivity(it);&nbsp;&nbsp;<br />&nbsp;&nbsp; 4. //where startLat, startLng, endLat, endLng are a long with 6 decimals like: 50.123456&nbsp;</p><p style="margin: 10px auto;"><strong>打电话</strong><br />&nbsp;&nbsp; 1. //<strong>叫出拨号程序</strong>&nbsp;<br />&nbsp;&nbsp; 2. Uri uri = Uri.parse("tel:0800000123");&nbsp;&nbsp;<br />&nbsp;&nbsp; 3. Intent it = new Intent(Intent.ACTION_DIAL, uri);&nbsp;&nbsp;<br />&nbsp;&nbsp; 4. startActivity(it);&nbsp;&nbsp;<br />&nbsp;&nbsp; 1.&nbsp;<strong>//直接打电话出去</strong>&nbsp;&nbsp;<br />&nbsp;&nbsp; 2. Uri uri = Uri.parse("tel:0800000123");&nbsp;&nbsp;<br />&nbsp;&nbsp; 3. Intent it = new Intent(Intent.ACTION_CALL, uri);&nbsp;&nbsp;<br />&nbsp;&nbsp; 4. startActivity(it);&nbsp;&nbsp;<br />&nbsp;&nbsp; 5. //用這個，要在 AndroidManifest.xml 中，加上&nbsp;&nbsp;<br />&nbsp;&nbsp; 6. //&lt;uses-permission id="android.permission.CALL_PHONE" /&gt;&nbsp;</p><p style="margin: 10px auto;"><strong>传送SMS/MMS</strong><br />&nbsp;&nbsp; 1.&nbsp;<strong>//调用短信程序</strong>&nbsp;<br />&nbsp;&nbsp; 2. Intent it = new Intent(Intent.ACTION_VIEW, uri);&nbsp;&nbsp;<br />&nbsp;&nbsp; 3. it.putExtra("sms_body", "The SMS text");&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp; 4. it.setType("vnd.android-dir/mms-sms");&nbsp;&nbsp;<br />&nbsp;&nbsp; 5. startActivity(it);&nbsp;<br />&nbsp;&nbsp; 1.<strong>&nbsp;//传送消息</strong>&nbsp;<br />&nbsp;&nbsp; 2. Uri uri = Uri.parse("smsto://0800000123");&nbsp;&nbsp;<br />&nbsp;&nbsp; 3. Intent it = new Intent(Intent.ACTION_SENDTO, uri);&nbsp;&nbsp;<br />&nbsp;&nbsp; 4. it.putExtra("sms_body", "The SMS text");&nbsp;&nbsp;<br />&nbsp;&nbsp; 5. startActivity(it);&nbsp;<br />&nbsp;&nbsp; 1.&nbsp;<strong>//传送 MMS</strong>&nbsp;&nbsp;<br />&nbsp;&nbsp; 2. Uri uri = Uri.parse("content://media/external/images/media/23");&nbsp;&nbsp;<br />&nbsp;&nbsp; 3. Intent it = new Intent(Intent.ACTION_SEND);&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp; 4. it.putExtra("sms_body", "some text");&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp; 5. it.putExtra(Intent.EXTRA_STREAM, uri);&nbsp;&nbsp;<br />&nbsp;&nbsp; 6. it.setType("image/png");&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp; 7. startActivity(it);&nbsp;</p><p style="margin: 10px auto;"><strong>传送 Email</strong><br />&nbsp;&nbsp; 1. Uri uri = Uri.parse("mailto:xxx@abc.com");&nbsp;&nbsp;<br />&nbsp;&nbsp; 2. Intent it = new Intent(Intent.ACTION_SENDTO, uri);&nbsp;&nbsp;<br />&nbsp;&nbsp; 3. startActivity(it);&nbsp;</p><p style="margin: 10px auto;"><br />&nbsp;&nbsp; 1. Intent it = new Intent(Intent.ACTION_SEND);&nbsp;&nbsp;<br />&nbsp;&nbsp; 2. it.putExtra(Intent.EXTRA_EMAIL, "me@abc.com");&nbsp;&nbsp;<br />&nbsp;&nbsp; 3. it.putExtra(Intent.EXTRA_TEXT, "The email body text");&nbsp;&nbsp;<br />&nbsp;&nbsp; 4. it.setType("text/plain");&nbsp;&nbsp;<br />&nbsp;&nbsp; 5. startActivity(Intent.createChooser(it, "Choose Email Client"));&nbsp;</p><p style="margin: 10px auto;"><br />&nbsp;&nbsp; 1. Intent it=new Intent(Intent.ACTION_SEND);&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp; 2. String[] tos={"me@abc.com"};&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp; 3. String[] ccs={"you@abc.com"};&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp; 4. it.putExtra(Intent.EXTRA_EMAIL, tos);&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp; 5. it.putExtra(Intent.EXTRA_CC, ccs);&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp; 6. it.putExtra(Intent.EXTRA_TEXT, "The email body text");&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp; 7. it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp; 8. it.setType("message/rfc822");&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp; 9. startActivity(Intent.createChooser(it, "Choose Email Client"));</p><p style="margin: 10px auto;"><br />&nbsp;&nbsp; 1. //传送附件<br />&nbsp;&nbsp; 2. Intent it = new Intent(Intent.ACTION_SEND);&nbsp;&nbsp;<br />&nbsp;&nbsp; 3. it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text");&nbsp;&nbsp;<br />&nbsp;&nbsp; 4. it.putExtra(Intent.EXTRA_STREAM, "file:///sdcard/mysong.mp3");&nbsp;&nbsp;<br />&nbsp;&nbsp; 5. sendIntent.setType("audio/mp3");&nbsp;&nbsp;<br />&nbsp;&nbsp; 6. startActivity(Intent.createChooser(it, "Choose Email Client"));</p><p style="margin: 10px auto;"><strong>播放多媒体</strong><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Uri uri = Uri.parse("file:///sdcard/song.mp3");&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Intent it = new Intent(Intent.ACTION_VIEW, uri);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; it.setType("audio/mp3");&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startActivity(it);&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Uri uri = Uri.withAppendedPath(MediaStore.Audio.Media.INTERNAL_CONTENT_URI, "1");&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Intent it = new Intent(Intent.ACTION_VIEW, uri);&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startActivity(it);</p><p style="margin: 10px auto;"><strong>Market 相关<br /></strong>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //寻找某个应用&nbsp;<br />2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Uri uri = Uri.parse("market://search?q=pname:pkg_name");&nbsp;<br />3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Intent it = new Intent(Intent.ACTION_VIEW, uri);&nbsp;&nbsp;<br />4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startActivity(it);&nbsp;&nbsp;<br />5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //where pkg_name is the full package path for an application&nbsp;<br />1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //显示某个应用的相关信息&nbsp;<br />2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Uri uri = Uri.parse("market://details?id=app_id");&nbsp;&nbsp;<br />3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Intent it = new Intent(Intent.ACTION_VIEW, uri);&nbsp;<br />4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startActivity(it);&nbsp;&nbsp;<br />5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //where app_id is the application ID, find the ID&nbsp;&nbsp;&nbsp;<br />6.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //by clicking on your application on Market home&nbsp;&nbsp;&nbsp;<br />7.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //page, and notice the ID from the address bar</p><p style="margin: 10px auto;"><strong>Uninstall 应用程序</strong><br />1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Uri uri = Uri.fromParts("package", strPackageName, null);&nbsp;<br />2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Intent it = new Intent(Intent.ACTION_DELETE, uri);&nbsp;&nbsp;&nbsp;<br />3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startActivity(it);&nbsp;</p></span></span></span></span><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/89987.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2015-02-08 13:44 <a href="http://www.cnitblog.com/liaoqingshan/archive/2015/02/08/89987.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android后台Service服务----转载</title><link>http://www.cnitblog.com/liaoqingshan/archive/2015/01/26/89968.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Mon, 26 Jan 2015 03:41:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2015/01/26/89968.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/89968.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2015/01/26/89968.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/89968.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/89968.html</trackback:ping><description><![CDATA[<p>最近在编写一个基于Android 2.1 的手机应用程序，其中的一个功能是利用Google 的地图API接口实现足迹追踪，整个程序设计大概分为三个部分，UI设计、GoogleMapAPI接口调用以及后台Service所做的数据的采集和传输以及和服务器的通讯。</p>
<p><span style="white-space: pre"></span>Android的UI设计和JAVA、MFC、C#.NET有些不同，毕竟是手持设备，硬件资源的限制要求它用尽量轻便的代码框架去完成功能，Android的用户界面是用XML来进行布局和管理的，支持直接拖拽，但是效果并不是很好。它的主活动界面是在main.xml中编写的，在这里可以定义一些按钮啊、文本框什么的。GoogleMapAPI的用法网上有很多教程，首先要去申请一个KEY，然后才能去调用API得到想要的数据，我们这里要获得GPS的实时数据，所以要用到 LocationListeninger 和 LocationManager 两个类，绘制地图可以调用Mapview类，里面有很多操作地图的方法，类似放大缩小、拖拽描点等都可以调用函数直接实现。</p>
<p><span style="white-space: pre"></span>主要来说一下后台服务的编写吧，在Android中Service是用来进行后台数据处理的东西，类似于Linux下的后台进程，就是当前活动创建的Service在这个活动窗口退出后Service还是继续运行的，我们要对用户的行动进行跟踪，就要长时间采集GPS发送过来的地理位置信息，这样的东西写成一个Service再合适不过了。自己编写的Service要继承系统的Service类，然后Override其中的方法。</p>
<div class="dp-highlighter bg_java" sizcache="29" sizset="50">
<div class="bar" sizcache="29" sizset="50">
<div class="tools" sizcache="29" sizset="50"><strong>[java]</strong> <a title="view plain" class="ViewSource" href="http://blog.csdn.net/cloudcraft/article/details/7682633#"><u><font color="#0066cc">view plain</font></u></a><a title="copy" class="CopyToClipboard" href="http://blog.csdn.net/cloudcraft/article/details/7682633#"><u><font color="#0066cc">copy</font></u></a><a title="print" class="PrintSource" href="http://blog.csdn.net/cloudcraft/article/details/7682633#"><u><font color="#0066cc">print</font></u></a><a title="?" class="About" href="http://blog.csdn.net/cloudcraft/article/details/7682633#"><u><font color="#0066cc">?</font></u></a></div></div>
<ol class="dp-j"><li class="alt"><span class="keyword">package</span><span>&nbsp;server.track;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;</span></li><li class="alt"><span></span><span class="keyword">import</span><span>&nbsp;java.util.Calendar;&nbsp;&nbsp;</span></span></li><li><span></span><span class="keyword">import</span><span>&nbsp;android.app.Service;&nbsp;&nbsp;</span></span></li><li class="alt"><span></span><span class="keyword">import</span><span>&nbsp;android.content.Context;&nbsp;&nbsp;</span></span></li><li><span></span><span class="keyword">import</span><span>&nbsp;android.content.Intent;&nbsp;&nbsp;</span></span></li><li class="alt"><span></span><span class="keyword">import</span><span>&nbsp;android.location.Location;&nbsp;&nbsp;</span></span></li><li><span></span><span class="keyword">import</span><span>&nbsp;android.location.LocationListener;&nbsp;&nbsp;</span></span></li><li class="alt"><span></span><span class="keyword">import</span><span>&nbsp;android.location.LocationManager;&nbsp;&nbsp;</span></span></li><li><span></span><span class="keyword">import</span><span>&nbsp;android.os.Bundle;&nbsp;&nbsp;</span></span></li><li class="alt"><span></span><span class="keyword">import</span><span>&nbsp;android.os.IBinder;&nbsp;&nbsp;</span></span></li><li><span></span><span class="keyword">import</span><span>&nbsp;android.util.Log;&nbsp;&nbsp;</span></span></li><li class="alt"><span></span><span class="keyword">import</span><span>&nbsp;android.widget.Toast;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;</span></li><li class="alt"><span></span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;Track&nbsp;</span><span class="keyword">extends</span><span>&nbsp;Service&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">static</span><span>&nbsp;</span><span class="keyword">final</span><span>&nbsp;String&nbsp;TAG&nbsp;=&nbsp;</span><span class="string">"Track"</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;LocationManager&nbsp;lm;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;LocationListener&nbsp;locationListener;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">final</span><span>&nbsp;SDRW&nbsp;filerecord&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;SDRW();&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;String&nbsp;record&nbsp;;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;String&nbsp;length;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">private</span><span>&nbsp;</span><span class="keyword">int</span><span>&nbsp;headposition;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="annotation">@Override</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;IBinder&nbsp;onBind(Intent&nbsp;arg0)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span></span><span class="comment">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Log.d(TAG,&nbsp;"onBind."); </span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">return</span><span>&nbsp;</span><span class="keyword">null</span><span>;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;onStart(Intent&nbsp;intent,&nbsp;</span><span class="keyword">int</span><span>&nbsp;startId)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Log.d(TAG,&nbsp;</span><span class="string">"onStart."</span><span>);&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Toast.makeText(getApplicationContext(),&nbsp;</span><span class="string">"启动服务"</span><span>,Toast.LENGTH_SHORT).show();&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">super</span><span>.onStart(intent,&nbsp;startId);&nbsp;&nbsp;</span></span></li><li><span></span><span class="comment">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;startDb(); </span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span></span><span class="comment">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Bundle&nbsp;extras&nbsp;=&nbsp;intent.getExtras(); </span><span>&nbsp;&nbsp;</span></span></li><li><span></span><span class="comment">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(extras&nbsp;!=&nbsp;null)&nbsp;{ </span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span></span><span class="comment">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;track_id&nbsp;=&nbsp;extras.getInt(LocateDbAdapter.TRACKID); </span><span>&nbsp;&nbsp;</span></span></li><li><span></span><span class="comment">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} </span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span></span><span class="comment">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Log.d(TAG,&nbsp;"track_id&nbsp;="&nbsp;+&nbsp;track_id); </span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;---use&nbsp;the&nbsp;LocationManager&nbsp;class&nbsp;to&nbsp;obtain&nbsp;GPS&nbsp;locations--- </span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Calendar&nbsp;calendar&nbsp;=&nbsp;Calendar.getInstance();&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;headposition&nbsp;=&nbsp;</span><span class="number">5</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;record&nbsp;=&nbsp;</span><span class="string">"head:&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;&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;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n"</span><span>;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filerecord.write(record);&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;record&nbsp;=&nbsp;</span><span class="string">"user:"</span><span>+</span><span class="string">"Yastand\r\n"</span><span>+</span><span class="string">"date:"</span><span>+calendar.get(Calendar.YEAR)&nbsp;+&nbsp;</span><span class="string">"-"</span><span>&nbsp;+calendar.get(Calendar.MONTH)&nbsp;+&nbsp;</span><span class="string">"-"</span><span>&nbsp;+&nbsp;&nbsp;calendar.get(Calendar.DAY_OF_MONTH)&nbsp;+&nbsp;</span><span class="string">"&nbsp;"</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;calendar.get(Calendar.HOUR_OF_DAY)&nbsp;+&nbsp;</span><span class="string">":"</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;calendar.get(Calendar.MINUTE)&nbsp;+&nbsp;</span><span class="string">":"</span><span>&nbsp;&nbsp;+&nbsp;calendar.get(Calendar.SECOND)+</span><span class="string">"\r\n"</span><span>;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filerecord.write(record);&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;length&nbsp;=&nbsp;String.valueOf(record.length())+</span><span class="string">"&nbsp;"</span><span>;&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filerecord.writehead(length,headposition);&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;headposition&nbsp;+=&nbsp;length.length();&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lm&nbsp;=&nbsp;(LocationManager)&nbsp;getSystemService(Context.LOCATION_SERVICE);&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;locationListener&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;MyLocationListener();&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lm.requestLocationUpdates(LocationManager.GPS_PROVIDER,&nbsp;</span><span class="number">0</span><span>,&nbsp;</span><span class="number">0</span><span>,locationListener);&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;onDestroy()&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Toast.makeText(</span><span class="keyword">this</span><span>,&nbsp;</span><span class="string">"service&nbsp;done"</span><span>,&nbsp;Toast.LENGTH_SHORT).show();&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">super</span><span>.onDestroy();&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lm.removeUpdates(locationListener);&nbsp;&nbsp;</span></li><li class="alt"><span></span><span class="comment">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stopService(new&nbsp;Intent("Context.LOCATION_SERVICE")); </span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stopSelf();&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">protected</span><span>&nbsp;</span><span class="keyword">class</span><span>&nbsp;MyLocationListener&nbsp;</span><span class="keyword">implements</span><span>&nbsp;LocationListener&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="annotation">@Override</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;onLocationChanged(Location&nbsp;loc)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Log.d(TAG,&nbsp;</span><span class="string">"MyLocationListener::onLocationChanged.."</span><span>);&nbsp;&nbsp;</span></span></li><li><span></span><span class="comment">/*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(loc&nbsp;!=&nbsp;null)&nbsp;{</span>&nbsp;</span></li><li class="alt"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;//////////</span>&nbsp;</li><li><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(mlcDbHelper&nbsp;==&nbsp;null){</span>&nbsp;</li><li class="alt"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mlcDbHelper.open();</span>&nbsp;</li><li><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span>&nbsp;</li><li class="alt"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mlcDbHelper.createLocate(track_id,&nbsp;&nbsp;loc.getLongitude(),loc.getLatitude(),&nbsp;loc.getAltitude());</span>&nbsp;</li><li><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span>&nbsp;</li><li class="alt"><span class="comment">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;record&nbsp;=&nbsp;</span><span class="string">"GPS:"</span><span>+</span><span class="string">"&nbsp;lon:"</span><span>+String.valueOf(loc.getLongitude())+</span><span class="string">"&nbsp;lat:"</span><span>+String.valueOf(loc.getLatitude())+</span><span class="string">"&nbsp;alt:"</span><span>+String.valueOf(loc.getAltitude())+</span><span class="string">"\r\n"</span><span>;&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">if</span><span>&nbsp;(loc&nbsp;!=&nbsp;</span><span class="keyword">null</span><span>)&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;&nbsp;filepoint.write(edit1.getText().toString());&nbsp; </span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;filerecord.write(record);&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="annotation">@Override</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;onProviderDisabled(String&nbsp;provider)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Toast.makeText(&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getBaseContext(),&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="string">"ProviderDisabled."</span><span>,&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Toast.LENGTH_SHORT).show();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="annotation">@Override</span><span>&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;onProviderEnabled(String&nbsp;provider)&nbsp;{&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Toast.makeText(&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;getBaseContext(),&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="string">"ProviderEnabled,provider:"</span><span>+provider,&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Toast.LENGTH_SHORT).show();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="annotation">@Override</span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;onStatusChanged(String&nbsp;provider,&nbsp;</span><span class="keyword">int</span><span>&nbsp;status,&nbsp;Bundle&nbsp;extras)&nbsp;{&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="comment">//&nbsp;TODO&nbsp;Auto-generated&nbsp;method&nbsp;stub </span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></li><li><span>}&nbsp;&nbsp;</span></li></ol></div><pre class="java" style="display: none" name="code">package server.track;

import java.util.Calendar;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;

public class Track extends Service {
	private static final String TAG = "Track";

	private LocationManager lm;
	private LocationListener locationListener;
	final SDRW filerecord = new SDRW();
	private String record ;
	private String length;
	private int headposition;
	@Override
	public IBinder onBind(Intent arg0) {
//		Log.d(TAG, "onBind.");
		return null;
	}
	
	public void onStart(Intent intent, int startId) {  
		Log.d(TAG, "onStart.");
		Toast.makeText(getApplicationContext(), "启动服务",Toast.LENGTH_SHORT).show();
        super.onStart(intent, startId);
//        startDb();
//		Bundle extras = intent.getExtras();
//		if (extras != null) {
//			track_id = extras.getInt(LocateDbAdapter.TRACKID);
//		}
//		Log.d(TAG, "track_id =" + track_id);
		// ---use the LocationManager class to obtain GPS locations---
		Calendar calendar = Calendar.getInstance();
		headposition = 5;
		record = "head:                                                                                 \r\n";
		filerecord.write(record);
		record = "user:"+"Yastand\r\n"+"date:"+calendar.get(Calendar.YEAR) + "-" +calendar.get(Calendar.MONTH) + "-" +  calendar.get(Calendar.DAY_OF_MONTH) + " "
		+ calendar.get(Calendar.HOUR_OF_DAY) + ":"
		+ calendar.get(Calendar.MINUTE) + ":"  + calendar.get(Calendar.SECOND)+"\r\n";
		filerecord.write(record);
		length = String.valueOf(record.length())+" ";
		filerecord.writehead(length,headposition);
		headposition += length.length();
		lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		locationListener = new MyLocationListener();
		lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,locationListener);
    }
	
	

    public void onDestroy() {
    	Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
    	super.onDestroy();
    	lm.removeUpdates(locationListener);
//        stopService(new Intent("Context.LOCATION_SERVICE"));
    	stopSelf();
    }

    protected class MyLocationListener implements LocationListener {

		@Override
		public void onLocationChanged(Location loc) {
			Log.d(TAG, "MyLocationListener::onLocationChanged..");
/*			if (loc != null) {
				// //////////
				if(mlcDbHelper == null){
					mlcDbHelper.open();
				}
				mlcDbHelper.createLocate(track_id,  loc.getLongitude(),loc.getLatitude(), loc.getAltitude());
			}
			*/
			record = "GPS:"+" lon:"+String.valueOf(loc.getLongitude())+" lat:"+String.valueOf(loc.getLatitude())+" alt:"+String.valueOf(loc.getAltitude())+"\r\n";
			if (loc != null)
			{
			//	filepoint.write(edit1.getText().toString()); 
				filerecord.write(record);
			}
		}


		@Override
		public void onProviderDisabled(String provider) {
			Toast.makeText(
					getBaseContext(),
					"ProviderDisabled.",
					Toast.LENGTH_SHORT).show();		}

		@Override
		public void onProviderEnabled(String provider) {
			Toast.makeText(
					getBaseContext(),
					"ProviderEnabled,provider:"+provider,
					Toast.LENGTH_SHORT).show();		}

		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
			// TODO Auto-generated method stub
		}
	}

	
}
</pre>要开启这个Service可以用 
<div class="dp-highlighter bg_java" sizcache="29" sizset="54">
<div class="bar" sizcache="29" sizset="54">
<div class="tools" sizcache="29" sizset="54"><strong>[java]</strong> <a title="view plain" class="ViewSource" href="http://blog.csdn.net/cloudcraft/article/details/7682633#"><u><font color="#0066cc">view plain</font></u></a><a title="copy" class="CopyToClipboard" href="http://blog.csdn.net/cloudcraft/article/details/7682633#"><u><font color="#0066cc">copy</font></u></a><a title="print" class="PrintSource" href="http://blog.csdn.net/cloudcraft/article/details/7682633#"><u><font color="#0066cc">print</font></u></a><a title="?" class="About" href="http://blog.csdn.net/cloudcraft/article/details/7682633#"><u><font color="#0066cc">?</font></u></a></div></div>
<ol class="dp-j"><li class="alt"><span>Intent&nbsp;i&nbsp;=&nbsp;</span><span class="keyword">new</span><span>&nbsp;Intent(</span><span class="string">"server.track.START_TRACK_SERVICE"</span><span>);&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;startService(i);&nbsp;&nbsp;</span></li></ol></div><pre class="java" style="display: none" name="code">Intent i = new Intent("server.track.START_TRACK_SERVICE");
                startService(i);</pre>执行这句话后，Service类首先去找Create函数，再运行Onstart函数，一个Service就成功的运行了，但是退出当前程序这个操作对这个后台运行的Service并没有什么影响，那么怎样结束这个Service呢？可以这样 
<div class="dp-highlighter bg_java" sizcache="29" sizset="58">
<div class="bar" sizcache="29" sizset="58">
<div class="tools" sizcache="29" sizset="58"><strong>[java]</strong> <a title="view plain" class="ViewSource" href="http://blog.csdn.net/cloudcraft/article/details/7682633#"><u><font color="#0066cc">view plain</font></u></a><a title="copy" class="CopyToClipboard" href="http://blog.csdn.net/cloudcraft/article/details/7682633#"><u><font color="#0066cc">copy</font></u></a><a title="print" class="PrintSource" href="http://blog.csdn.net/cloudcraft/article/details/7682633#"><u><font color="#0066cc">print</font></u></a><a title="?" class="About" href="http://blog.csdn.net/cloudcraft/article/details/7682633#"><u><font color="#0066cc">?</font></u></a></div></div>
<ol class="dp-j"><li class="alt"><span>stopService(</span><span class="keyword">new</span><span>&nbsp;Intent(</span><span class="string">"server.track.START_TRACK_SERVICE"</span><span>));&nbsp;&nbsp;</span></li></ol></div><pre class="java" style="display: none" name="code">stopService(new Intent("server.track.START_TRACK_SERVICE"));</pre>执行这句话，系统就会调用Service实例的onDestroy()函数，到这里本以为万事大吉了，结果发现调用stopService之后GPS发送回来的数据还是源源不断的写入到文件中，原来在onDestroy()函数中必须显示的把Service实例中调用的线程都结束之后才能停止，在我们的Service中调用的LocationLinstener是这问题的关键，必须在onDestroy()中结束它运行的线程 
<div class="dp-highlighter bg_java" sizcache="29" sizset="62">
<div class="bar" sizcache="29" sizset="62">
<div class="tools" sizcache="29" sizset="62"><strong>[java]</strong> <a title="view plain" class="ViewSource" href="http://blog.csdn.net/cloudcraft/article/details/7682633#"><u><font color="#0066cc">view plain</font></u></a><a title="copy" class="CopyToClipboard" href="http://blog.csdn.net/cloudcraft/article/details/7682633#"><u><font color="#0066cc">copy</font></u></a><a title="print" class="PrintSource" href="http://blog.csdn.net/cloudcraft/article/details/7682633#"><u><font color="#0066cc">print</font></u></a><a title="?" class="About" href="http://blog.csdn.net/cloudcraft/article/details/7682633#"><u><font color="#0066cc">?</font></u></a></div></div>
<ol class="dp-j"><li class="alt"><span>&nbsp;</span><span class="keyword">public</span><span>&nbsp;</span><span class="keyword">void</span><span>&nbsp;onDestroy()&nbsp;{&nbsp;&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Toast.makeText(</span><span class="keyword">this</span><span>,&nbsp;</span><span class="string">"service&nbsp;done"</span><span>,&nbsp;Toast.LENGTH_SHORT).show();&nbsp;&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span class="keyword">super</span><span>.onDestroy();&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lm.removeUpdates(locationListener);&nbsp;&nbsp;</span></li><li class="alt"><span></span><span class="comment">//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stopService(new&nbsp;Intent("Context.LOCATION_SERVICE")); </span><span>&nbsp;&nbsp;</span></span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stopSelf();&nbsp;&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;</span></li></ol></div><pre class="java" style="display: none" name="code"> public void onDestroy() {
    	Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
    	super.onDestroy();
    	lm.removeUpdates(locationListener);
//        stopService(new Intent("Context.LOCATION_SERVICE"));
    	stopSelf();
    }</pre>ok了，调用这个函数之后后台运行的Service就自己终止了。 <br /><br /><br />
<h1>Android SERVICE后台服务进程的自启动和保持</h1>&nbsp;
<div class="content bgF8F8F8 f14">
<div id="content">Service组件在android开发中经常遇到，其经常作为后台服务，需要始终保持运行，负责处理一些必要（见不得人）的任务。而一些安全软件，如360等，会有结束进程的功能，如果不做Service的保持，就会被其杀掉。
<p>如何保持Service的运行状态是现在要说明的，核心就是利用ANDROID的系统广播，这一不会被其他软件影响的常驻程序触发自己的程序检查Service的运行状态，如果被杀掉，就再起来。</p>
<p>我利用的系统广播是Intent.ACTION_TIME_TICK，这个广播每分钟发送一次，我们可以每分钟检查一次Service的运行状态，如果已经被结束了，就重新启动Service。</p>
<p>下边就是具体的代码和注意事项了：</p>
<p>1、 Intent.ACTION_TIME_TICK的使用</p>
<p>我们知道广播的注册有静态注册和动态注册，但此系统广播只能通过动态注册的方式使用。即你不能通过在manifest.xml里注册的方式接收到这个广播，只能在代码里通过registerReceiver()方法注册。</p>
<p>在ThisApp extends Application 里注册广播：</p><pre><ol class="dp-j"><li class="alt"><span>IntentFilter&nbsp;filter&nbsp;=&nbsp;newIntentFilter(Intent.ACTION_TIME_TICK);&nbsp;</span></li><li><span>MyBroadcastReceiver&nbsp;receiver&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;MyBroadcastReceiver();&nbsp;</span></span></li><li class="alt"><span>registerReceiver(receiver,&nbsp;filter);&nbsp;</span></li></ol></pre>
<p>在广播接收器MyBroadcastReceiver extends BroadcastReceiver的onReceive里</p><pre><ol class="dp-j"><li class="alt"><span class="keyword">if</span><span>&nbsp;(intent.getAction().equals(Intent.ACTION_TIME_TICK))&nbsp;{&nbsp;</span></li><li><span>&nbsp;&nbsp;</span></li><li class="alt"><span class="comment">//检查Service状态</span><span>&nbsp;</span></li><li><span>&nbsp;&nbsp;</span></li><li class="alt"><span>}&nbsp;</span></li></ol></pre>
<p>2、Service的检查与启动</p><pre><ol class="dp-j"><li class="alt"><span class="keyword">boolean</span><span>&nbsp;isServiceRunning&nbsp;=&nbsp;</span><span class="keyword">false</span><span>;&nbsp;</span></li><li><span>ActivityManager&nbsp;manager&nbsp;=&nbsp;(ActivityManager)ThisApp.getContext().getSystemService(Context.ACTIVITY_SERVICE);&nbsp;</span></li><li class="alt"><span class="keyword">for</span><span>&nbsp;(RunningServiceInfo&nbsp;service&nbsp;:manager.getRunningServices(Integer.MAX_VALUE))&nbsp;{&nbsp;</span></li><li><span class="keyword">if</span><span>(</span><span class="string">"so.xxxx.WidgetUpdateService"</span><span>.equals(service.service.getClassName()))&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">//Service的类名</span><span>&nbsp;</span></span></li><li><span>{&nbsp;</span></li><li class="alt"><span>isServiceRunning&nbsp;=&nbsp;<span class="keyword">true</span><span>;&nbsp;</span></span></li><li><span>}&nbsp;</span></li><li class="alt"><span>&nbsp;&nbsp;</span></li><li><span>&nbsp;}&nbsp;</span></li><li class="alt"><span class="keyword">if</span><span>&nbsp;(!isServiceRunning)&nbsp;{&nbsp;</span></li><li><span>Intent&nbsp;i&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;Intent(context,&nbsp;WidgetUpdateService.</span><span class="keyword">class</span><span>);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;context.startService(i);&nbsp;</span></li><li><span>}&nbsp;</span></li></ol></pre>
<p>另一个话题，Service的开机启动。</p>
<p>实现和上边的类似，也是通过监控开机的系统广播来启动Service。但其实你做了上边的检查也就不会做开机启动了，因为过一两分钟就会通过上边的程序启动Service了。代码如下：</p><pre><ol class="dp-j"><li class="alt"><span class="keyword">if</span><span>&nbsp;(intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED))&nbsp;{&nbsp;</span></li><li><span>Intent&nbsp;i&nbsp;=&nbsp;<span class="keyword">new</span><span>&nbsp;Intent(context,&nbsp;LogService.</span><span class="keyword">class</span><span>);&nbsp;</span></span></li><li class="alt"><span>&nbsp;&nbsp;&nbsp;&nbsp;context.startService(i);&nbsp;</span></li><li><span>&nbsp;&nbsp;&nbsp;&nbsp;</span></li></ol></pre></div></div><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/89968.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2015-01-26 11:41 <a href="http://www.cnitblog.com/liaoqingshan/archive/2015/01/26/89968.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android studio 安装的若干问题----转载</title><link>http://www.cnitblog.com/liaoqingshan/archive/2015/01/13/89941.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Tue, 13 Jan 2015 15:29:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2015/01/13/89941.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/89941.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2015/01/13/89941.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/89941.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/89941.html</trackback:ping><description><![CDATA[<div id="cnblogs_post_body">
<h4>1、在国内如何更新android sdk？</h4>
<p>由于众所周知的某些原因，我们无法直接连接android sdk的更新服务更新sdk，所以可以通过国内的ftp站点把常用的sdk组件如android platform-tools、samples、build-tools、system image等直接下载添加到官网的sdk中再使用。</p>
<p>最近在用的一个ftp站点：&nbsp;http://mirrors.neusoft.edu.cn/android/repository/</p>
<p>当然也可以使用vpn后直接更新，不过也是比较慢。</p>
<h4>2、解决Fetching android sdk component information加载问题</h4>
<div>
<p>安装完成后，如果直接启动，Android Studio会去获取 android sdk 组件信息，这个过程相当慢，还经常加载失败，导致Android Studio启动不起开。解决办法就是不去获取android sdk 组件信息。方法如下：</p>
<p>1）进入刚安装的Android Studio目录下的bin目录。找到idea.properties文件，用文本编辑器打开。</p>
<p>2）在idea.properties文件末尾添加一行：disable.android.first.run=true，然后保存文件。</p>
<p>3）关闭Android Studio后重新启动，便可进入界面。</p></div>
<p>其实是如果不做这个修改， android studio每次启动都会去检查更新。</p>
<h4>3、Gradle DSL method not found: &nbsp;runProguard()</h4>
<p>在升级gradle后或更新 导入某些non-Android studio project会发现如下报错</p>
<p>Gradle DSL method not found: 'runProguard()'</p>
<p>查阅官方文档之后（http://tools.android.com/tech-docs/new-build-system）之后发现，在新版本的gradle中，runProguard这个方法已经废弃了，并且改为新的方法了：minifyEnabled. 因此，正确的解决方法不是修改gradle的版本号，而是将项目中每个Module对应的build.gradle文件中的runProguard方法名改为minifyEnabled。</p></div><br /><br />转自 <a href="http://www.cnblogs.com/onlyinweb/p/4216445.html">http://www.cnblogs.com/onlyinweb/p/4216445.html</a><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/89941.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2015-01-13 23:29 <a href="http://www.cnitblog.com/liaoqingshan/archive/2015/01/13/89941.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>sql语句中的十进制转十六进制</title><link>http://www.cnitblog.com/liaoqingshan/archive/2014/06/23/89616.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Mon, 23 Jun 2014 09:58:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2014/06/23/89616.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/89616.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2014/06/23/89616.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/89616.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/89616.html</trackback:ping><description><![CDATA[<span style="text-transform: none; background-color: rgb(255,237,196); text-indent: 0px; display: inline !important; font: 13px 宋体, 'MS Sans Serif', sans-serif; white-space: normal; float: none; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; -webkit-text-stroke-width: 0px">由0xa--&gt;10<br />select&nbsp;CONVERT(VARCHAR(50),&nbsp;CONVERT(bigint,0xa))&nbsp;as&nbsp;converted<br /><br />由10--&gt;0x0a<br />select convert(varbinary(1), 10)<br /><br />特别的方式：<br />select REPLACE('其它字符10', '10', 'a')<br />这可以直接把10替换成a。<br /><br /><br /></span><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/89616.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2014-06-23 17:58 <a href="http://www.cnitblog.com/liaoqingshan/archive/2014/06/23/89616.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux环境下段错误的产生原因及调试方法小结（转载）</title><link>http://www.cnitblog.com/liaoqingshan/archive/2014/05/14/89547.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Wed, 14 May 2014 09:59:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2014/05/14/89547.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/89547.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2014/05/14/89547.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/89547.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/89547.html</trackback:ping><description><![CDATA[<h2>&nbsp;</h2>
<div class="postbody">
<div id="cnblogs_post_body">
<p>最近在Linux环境下做C语言项目，由于是在一个原有项目基础之上进行二次开发，而且项目工程庞大复杂，出现了不少问题，其中遇到最多、花费时间最长的问题就是著名的&#8220;段错误&#8221;（Segmentation Fault）。借此机会系统学习了一下，这里对Linux环境下的段错误做个小结，方便以后同类问题的排查与解决。</p>
<h1>1. 段错误是什么</h1>
<p>一句话来说，段错误是指访问的内存超出了系统给这个程序所设定的内存空间，例如访问了不存在的内存地址、访问了系统保护的内存地址、访问了只读的内存地址等等情况。这里贴一个对于&#8220;段错误&#8221;的准确定义（参考Answers.com）：</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre>A segmentation fault (often shortened to segfault) is a particular error condition that can occur during the operation of computer software. In short, a segmentation fault occurs <span style="color: #0000ff">when</span> a program attempts to access a memory location that it is <span style="color: #0000ff">not</span> allowed to access, or attempts to access a memory location in a way that is <span style="color: #0000ff">not</span> allowed (e.g., attempts to write to a read-only location, or to overwrite part of the operating system). Systems based <span style="color: #0000ff">on</span> processors like the Motorola 68000 tend to refer to these events as Address or Bus errors.<br /><br />Segmentation is one approach to memory management and protection in the operating system. It has been superseded by paging <span style="color: #0000ff">for</span> most purposes, but much of the terminology of segmentation is still used, "segmentation fault" being an example. Some operating systems still have segmentation at some logical level although paging is used as the main memory management policy.<br /><br /><span style="color: #0000ff">On</span> Unix-like operating systems, a process that accesses invalid memory receives the SIGSEGV signal. <span style="color: #0000ff">On</span> Microsoft Windows, a process that accesses invalid memory receives the STATUS_ACCESS_VIOLATION exception.</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<h1>2. 段错误产生的原因</h1>
<h2>2.1 访问不存在的内存地址</h2>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre>#include&lt;stdio.h&gt;<br />#include&lt;stdlib.h&gt;<br /><span style="color: #0000ff">void</span> main()<br />{<br />        <span style="color: #0000ff">int</span> *ptr = NULL;<br />        *ptr = <span style="color: #800080">0</span>;<br />}</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<h2>2.2 访问系统保护的内存地址</h2>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre>#include&lt;stdio.h&gt;<br />#include&lt;stdlib.h&gt;<br /><span style="color: #0000ff">void</span> main()<br />{<br />        <span style="color: #0000ff">int</span> *ptr = (<span style="color: #0000ff">int</span> *)<span style="color: #800080">0</span>;<br />        *ptr = <span style="color: #800080">100</span>;<br />}</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<h2>2.3 访问只读的内存地址</h2>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre>#include&lt;stdio.h&gt;<br />#include&lt;stdlib.h&gt;<br />#include&lt;<span style="color: #0000ff">string</span>.h&gt;<br /><span style="color: #0000ff">void</span> main()<br />{<br />        <span style="color: #0000ff">char</span> *ptr = <span style="color: #800000">"</span><span style="color: #800000">test</span><span style="color: #800000">"</span>;<br />        strcpy(ptr, <span style="color: #800000">"</span><span style="color: #800000">TEST</span><span style="color: #800000">"</span>);<br />}</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<h2>2.4 栈溢出</h2>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre>#include&lt;stdio.h&gt;<br />#include&lt;stdlib.h&gt;<br /><span style="color: #0000ff">void</span> main()<br />{<br />        main();<br />}</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<p>等等其他原因。</p>
<h1>3. 段错误信息的获取</h1>
<p>程序发生段错误时，提示信息很少，下面有几种查看段错误的发生信息的途径。</p>
<h2>3.1 dmesg</h2>
<p>dmesg可以在应用程序crash掉时，显示内核中保存的相关信息。如下所示，通过dmesg命令可以查看发生段错误的程序名称、引起段错误发生的内存地址、指令指针地址、堆栈指针地址、错误代码、错误原因等。以程序2.3为例：</p>
<div class="cnblogs_code"><pre>panfeng@ubuntu:~/segfault$ dmesg<br />[ 2329.479037] segfault3[2700]: segfault at 80484e0 ip 00d2906a sp bfbbec3c error 7 in libc-2.10.1.so[cb4000+13e000]</pre></div>
<h2>3.2 -g</h2>
<p>使用gcc编译程序的源码时，加上-g参数，这样可以使得生成的二进制文件中加入可以用于gdb调试的有用信息。以程序2.3为例：</p>
<div class="cnblogs_code"><pre>panfeng@ubuntu:~/segfault$ gcc -g -o segfault3 segfault3.c</pre></div>
<h2>3.3 nm</h2>
<p>使用nm命令列出二进制文件中的符号表，包括符号地址、符号类型、符号名等，这样可以帮助定位在哪里发生了段错误。以程序2.3为例：</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre>panfeng@ubuntu:~/segfault$ nm segfault3<br />08049f20 d _DYNAMIC<br />08049ff4 d _GLOBAL_OFFSET_TABLE_<br />080484dc R _IO_stdin_used<br />         w _Jv_RegisterClasses<br />08049f10 d __CTOR_END__<br />08049f0c d __CTOR_LIST__<br />08049f18 D __DTOR_END__<br />08049f14 d __DTOR_LIST__<br />080484ec r __FRAME_END__<br />08049f1c d __JCR_END__<br />08049f1c d __JCR_LIST__<br />0804a014 A __bss_start<br />0804a00c D __data_start<br />08048490 t __do_global_ctors_aux<br />08048360 t __do_global_dtors_aux<br />0804a010 D __dso_handle<br />         w __gmon_start__<br />0804848a T __i686.get_pc_thunk.bx<br />08049f0c d __init_array_end<br />08049f0c d __init_array_start<br />08048420 T __libc_csu_fini<br />08048430 T __libc_csu_init<br />         U __libc_start_main@@GLIBC_2.0<br />0804a014 A _edata<br />0804a01c A _end<br />080484bc T _fini<br />080484d8 R _fp_hw<br />080482bc T _init<br />08048330 T _start<br />0804a014 b completed.6990<br />0804a00c W data_start<br />0804a018 b dtor_idx.6992<br />080483c0 t frame_dummy<br />080483e4 T main<br />         U memcpy@@GLIBC_2.0</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<h2>3.4 ldd</h2>
<p>使用ldd命令查看二进制程序的共享链接库依赖，包括库的名称、起始地址，这样可以确定段错误到底是发生在了自己的程序中还是依赖的共享库中。以程序2.3为例：</p>
<div class="cnblogs_code"><pre>panfeng@ubuntu:~/segfault$ ldd ./segfault3<br />    linux-gate.so.1 =&gt;  (0x00e08000)<br />    libc.so.6 =&gt; /lib/tls/i686/cmov/libc.so.6 (0x00675000)<br />    /lib/ld-linux.so.2 (0x00482000)</pre></div>
<h1>4. 段错误的调试方法</h1>
<h2>4.1 使用printf输出信息</h2>
<p>这个是看似最简单但往往很多情况下十分有效的调试方式，也许可以说是程序员用的最多的调试方式。简单来说，就是在程序的重要代码附近加上像printf这类输出信息，这样可以跟踪并打印出段错误在代码中可能出现的位置。</p>
<p>为了方便使用这种方法，可以使用条件编译指令#ifdef DEBUG和#endif把printf函数包起来。这样在程序编译时，如果加上-DDEBUG参数就能查看调试信息；否则不加该参数就不会显示调试信息。</p>
<h2>4.2 使用gcc和gdb</h2>
<h3>4.2.1 调试步骤</h3>
<p>&nbsp;1、为了能够使用gdb调试程序，在编译阶段加上-g参数，以程序2.3为例：</p>
<div class="cnblogs_code"><pre>panfeng@ubuntu:~/segfault$ gcc -g -o segfault3 segfault3.c</pre></div>
<p>2、使用gdb命令调试程序：</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre>panfeng@ubuntu:~/segfault$ gdb ./segfault3 <br />GNU gdb (GDB) 7.0-ubuntu<br />Copyright (C) 2009 Free Software Foundation, Inc.<br />License GPLv3+: GNU GPL version 3 or later &lt;http://gnu.org/licenses/gpl.html&gt;<br />This is free software: you are free to change and redistribute it.<br />There is NO WARRANTY, to the extent permitted by law.  <span style="color: #0000ff">Type</span> "show copying"<br />and "show warranty" <span style="color: #0000ff">for</span> details.<br />This GDB was configured as "i486-linux-gnu".<br /><span style="color: #0000ff">For</span> bug reporting instructions, please see:<br />&lt;http://www.gnu.org/software/gdb/bugs/&gt;...<br />Reading symbols from /home/panfeng/segfault/segfault3...done.<br />(gdb) </pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<p>3、进入gdb后，运行程序：</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre>(gdb) <span style="color: #0000ff">run</span><br />Starting program: /home/panfeng/segfault/segfault3 <br /><br />Program received signal SIGSEGV, Segmentation fault.<br />0x001a306a in memcpy () from /lib/tls/i686/cmov/libc.so.6<br />(gdb) </pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<p>从输出看出，程序2.3收到SIGSEGV信号，触发段错误，并提示地址0x001a306a、调用memcpy报的错，位于/lib/tls/i686/cmov/libc.so.6库中。</p>
<p>4、完成调试后，输入quit命令退出gdb：</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre>(gdb) quit<br />A debugging session is active.<br /><br />    Inferior 1 [process 3207] will be killed.<br /><br />Quit anyway? (y or n) y</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<h3>4.2.2 适用场景</h3>
<p>1、仅当能确定程序一定会发生段错误的情况下使用。</p>
<p>2、当程序的源码可以获得的情况下，使用-g参数编译程序。</p>
<p>3、一般用于测试阶段，生产环境下gdb会有副作用：使程序运行减慢，运行不够稳定，等等。</p>
<p>4、即使在测试阶段，如果程序过于复杂，gdb也不能处理。</p>
<h2>4.3 使用core文件和gdb</h2>
<p>在4.2节中提到段错误会触发SIGSEGV信号，通过man&nbsp;7&nbsp;signal，可以看到SIGSEGV默认的handler会打印段错误出错信息，并产生core文件，由此我们可以借助于程序异常退出时生成的core文件中的调试信息，使用gdb工具来调试程序中的段错误。</p>
<h3>4.3.1 调试步骤</h3>
<p>1、在一些Linux版本下，默认是不产生core文件的，首先可以查看一下系统core文件的大小限制：</p>
<div class="cnblogs_code"><pre>panfeng@ubuntu:~/segfault$ ulimit -c<br />0</pre></div>
<p>2、可以看到默认设置情况下，本机Linux环境下发生段错误时不会自动生成core文件，下面设置下core文件的大小限制（单位为KB）：</p>
<div class="cnblogs_code"><pre>panfeng@ubuntu:~/segfault$ ulimit -c 1024<br />panfeng@ubuntu:~/segfault$ ulimit -c<br />1024</pre></div>
<p>3、运行程序2.3，发生段错误生成core文件：</p>
<div class="cnblogs_code"><pre>panfeng@ubuntu:~/segfault$ ./segfault3<br />段错误 (core dumped)</pre></div>
<p>4、加载core文件，使用gdb工具进行调试：</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre>panfeng@ubuntu:~/segfault$ gdb ./segfault3 ./core <br />GNU gdb (GDB) 7.0-ubuntu<br />Copyright (C) 2009 Free Software Foundation, Inc.<br />License GPLv3+: GNU GPL version 3 or later &lt;http://gnu.org/licenses/gpl.html&gt;<br />This is free software: you are free to change and redistribute it.<br />There is NO WARRANTY, to the extent permitted by law.  <span style="color: #0000ff">Type</span> "show copying"<br />and "show warranty" <span style="color: #0000ff">for</span> details.<br />This GDB was configured as "i486-linux-gnu".<br /><span style="color: #0000ff">For</span> bug reporting instructions, please see:<br />&lt;http://www.gnu.org/software/gdb/bugs/&gt;...<br />Reading symbols from /home/panfeng/segfault/segfault3...done.<br /><br />warning: Can't read pathname <span style="color: #0000ff">for</span> load map: 输入/输出错误.<br />Reading symbols from /lib/tls/i686/cmov/libc.so.6...(no debugging symbols found)...done.<br />Loaded symbols <span style="color: #0000ff">for</span> /lib/tls/i686/cmov/libc.so.6<br />Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.<br />Loaded symbols <span style="color: #0000ff">for</span> /lib/ld-linux.so.2<br />Core was generated by `./segfault3'.<br />Program terminated with signal 11, Segmentation fault.<br />#0  0x0018506a in memcpy () from /lib/tls/i686/cmov/libc.6</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<p>从输出看出，同4.2.1中一样的段错误信息。</p>
<p>5、完成调试后，输入quit命令退出gdb：</p>
<div class="cnblogs_code"><pre>(gdb) quit</pre></div>
<h3>4.3.2 适用场景</h3>
<p>1、适合于在实际生成环境下调试程序的段错误（即在不用重新发生段错误的情况下重现段错误）。</p>
<p>2、当程序很复杂，core文件相当大时，该方法不可用。</p>
<h2>4.4 使用objdump</h2>
<h3>4.4.1 调试步骤</h3>
<p>1、使用dmesg命令，找到最近发生的段错误输出信息：</p>
<div class="cnblogs_code"><pre>panfeng@ubuntu:~/segfault$ dmesg<br />... ...<br />[17257.502808] segfault3[3320]: segfault at 80484e0 ip 0018506a sp bfc1cd6c error 7 in libc-2.10.1.so[110000+13e000]</pre></div>
<p>其中，对我们接下来的调试过程有用的是发生段错误的地址：80484e0和指令指针地址：0018506a。</p>
<p>2、使用objdump生成二进制的相关信息，重定向到文件中：</p>
<div class="cnblogs_code"><pre>panfeng@ubuntu:~/segfault$ objdump -d ./segfault3 &gt; segfault3Dump</pre></div>
<p>其中，生成的segfault3Dump文件中包含了二进制文件的segfault3的汇编代码。</p>
<p>3、在segfault3Dump文件中查找发生段错误的地址：</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre>panfeng@ubuntu:~/segfault$ grep -n -A 10 -B 10 "80484e0" ./segfault3Dump <br />121- 80483df:    ff d0                    <span style="color: #0000ff">call</span>   *%eax<br />122- 80483e1:    c9                       leave  <br />123- 80483e2:    c3                       ret    <br />124- 80483e3:    90                       nop<br />125-<br />126-080483e4 &lt;main&gt;:<br />127- 80483e4:    55                       push   %ebp<br />128- 80483e5:    89 e5                    mov    %esp,%ebp<br />129- 80483e7:    83 e4 f0                 and    $0xfffffff0,%esp<br />130- 80483ea:    83 ec 20                 sub    $0x20,%esp<br />131: 80483ed:    c7 44 24 1c e0 84 04     movl   $0x80484e0,0x1c(%esp)<br />132- 80483f4:    08 <br />133- 80483f5:    b8 e5 84 04 08           mov    $0x80484e5,%eax<br />134- 80483fa:    c7 44 24 08 05 00 00     movl   $0x5,0x8(%esp)<br />135- 8048401:    00 <br />136- 8048402:    89 44 24 04              mov    %eax,0x4(%esp)<br />137- 8048406:    8b 44 24 1c              mov    0x1c(%esp),%eax<br />138- 804840a:    89 04 24                 mov    %eax,(%esp)<br />139- 804840d:    e8 0a ff ff ff           <span style="color: #0000ff">call</span>   804831c &lt;memcpy@plt&gt;<br />140- 8048412:    c9                       leave  <br />141- 8048413:    c3                       ret    </pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<p>通过对以上汇编代码分析，得知段错误发生main函数，对应的汇编指令是movl $0x80484e0,0x1c(%esp)，接下来打开程序的源码，找到汇编指令对应的源码，也就定位到段错误了。</p>
<h3>4.4.2 适用场景</h3>
<p>1、不需要-g参数编译，不需要借助于core文件，但需要有一定的汇编语言基础。</p>
<p>2、如果使用了gcc编译优化参数（-O1，-O2，-O3）的话，生成的汇编指令将会被优化，使得调试过程有些难度。</p>
<h2>4.5 使用catchsegv</h2>
<p>catchsegv命令专门用来扑获段错误，它通过动态加载器（ld-linux.so）的预加载机制（PRELOAD）把一个事先写好的库（/lib/libSegFault.so）加载上，用于捕捉断错误的出错信息。</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre>panfeng@ubuntu:~/segfault$ catchsegv ./segfault3<br />Segmentation fault (core dumped)<br />*** Segmentation fault<br />Register dump:<br /><br /> EAX: 00000000   EBX: 00fb3ff4   ECX: 00000002   EDX: 00000000<br /> ESI: 080484e5   EDI: 080484e0   EBP: bfb7ad38   ESP: bfb7ad0c<br /><br /> EIP: 00ee806a   EFLAGS: 00010203<br /><br /> CS: 0073   DS: 007b   ES: 007b   FS: 0000   GS: 0033   SS: 007b<br /><br /> Trap: 0000000e   Error: 00000007   OldMask: 00000000<br /> ESP/signal: bfb7ad0c   CR2: 080484e0<br /><br />Backtrace:<br />/lib/libSegFault.so[0x3b606f]<br />??:0(??)[0xc76400]<br />/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xe89b56]<br />/build/buildd/eglibc-2.10.1/csu/../sysdeps/i386/elf/<span style="color: #0000ff">start</span>.S:122(_start)[0x8048351]<br /><br />Memory map:<br /><br />00258000-00273000 r-xp 00000000 08:01 157 /lib/ld-2.10.1.so<br />00273000-00274000 r--p 0001a000 08:01 157 /lib/ld-2.10.1.so<br />00274000-00275000 rw-p 0001b000 08:01 157 /lib/ld-2.10.1.so<br />003b4000-003b7000 r-xp 00000000 08:01 13105 /lib/libSegFault.so<br />003b7000-003b8000 r--p 00002000 08:01 13105 /lib/libSegFault.so<br />003b8000-003b9000 rw-p 00003000 08:01 13105 /lib/libSegFault.so<br />00c76000-00c77000 r-xp 00000000 00:00 0 [vdso]<br />00e0d000-00e29000 r-xp 00000000 08:01 4817 /lib/libgcc_s.so.1<br />00e29000-00e2a000 r--p 0001b000 08:01 4817 /lib/libgcc_s.so.1<br />00e2a000-00e2b000 rw-p 0001c000 08:01 4817 /lib/libgcc_s.so.1<br />00e73000-00fb1000 r-xp 00000000 08:01 1800 /lib/tls/i686/cmov/libc-2.10.1.so<br />00fb1000-00fb2000 ---p 0013e000 08:01 1800 /lib/tls/i686/cmov/libc-2.10.1.so<br />00fb2000-00fb4000 r--p 0013e000 08:01 1800 /lib/tls/i686/cmov/libc-2.10.1.so<br />00fb4000-00fb5000 rw-p 00140000 08:01 1800 /lib/tls/i686/cmov/libc-2.10.1.so<br />00fb5000-00fb8000 rw-p 00000000 00:00 0<br />08048000-08049000 r-xp 00000000 08:01 303895 /home/panfeng/segfault/segfault3<br />08049000-0804a000 r--p 00000000 08:01 303895 /home/panfeng/segfault/segfault3<br />0804a000-0804b000 rw-p 00001000 08:01 303895 /home/panfeng/segfault/segfault3<br />09432000-09457000 rw-p 00000000 00:00 0 [heap]<br />b78cf000-b78d1000 rw-p 00000000 00:00 0<br />b78df000-b78e1000 rw-p 00000000 00:00 0<br />bfb67000-bfb7c000 rw-p 00000000 00:00 0 [stack]</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<h1>5. 一些注意事项</h1>
<p>1、出现段错误时，首先应该想到段错误的定义，从它出发考虑引发错误的原因。</p>
<p>2、在使用指针时，定义了指针后记得初始化指针，在使用的时候记得判断是否为NULL。</p>
<p>3、在使用数组时，注意数组是否被初始化，数组下标是否越界，数组元素是否存在等。</p>
<p>4、在访问变量时，注意变量所占地址空间是否已经被程序释放掉。</p>
<p>5、在处理变量时，注意变量的格式控制是否合理等。</p>
<h1>6. 参考资料列表</h1>
<p>1、http://www.docin.com/p-105923877.html</p>
<p>2、http://blog.chinaunix.net/space.php?uid=317451&amp;do=blog&amp;id=92412</p></div></div><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/89547.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2014-05-14 17:59 <a href="http://www.cnitblog.com/liaoqingshan/archive/2014/05/14/89547.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>强大的strace和ldd</title><link>http://www.cnitblog.com/liaoqingshan/archive/2013/05/29/87576.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Wed, 29 May 2013 11:03:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2013/05/29/87576.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/87576.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2013/05/29/87576.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/87576.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/87576.html</trackback:ping><description><![CDATA[<h1><strong><span style="font-size: 18pt">简介</span></strong></h1>
<p>strace常用来跟踪进程执行时的系统调用和所接收的信号。 在Linux世界，进程不能直接访问硬件设备，当进程需要访问硬件设备(比如读取磁盘文件，接收网络数据等等)时，必须由用户态模式切换至内核态模式，通 过系统调用访问硬件设备。strace可以跟踪到一个进程产生的系统调用,包括参数，返回值，执行消耗的时间。</p>
<h1><strong><span style="font-size: 18pt">输出参数含义</span></strong></h1>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre>root@ubuntu:/usr# strace cat /dev/<span style="color: #0000ff">null</span> <br />execve(<span style="color: #800000">"</span><span style="color: #800000">/bin/cat</span><span style="color: #800000">"</span>, [<span style="color: #800000">"</span><span style="color: #800000">cat</span><span style="color: #800000">"</span>, <span style="color: #800000">"</span><span style="color: #800000">/dev/null</span><span style="color: #800000">"</span>], [<span style="color: #008000">/*</span><span style="color: #008000"> 22 vars </span><span style="color: #008000">*/</span>]) = <span style="color: #800080">0</span><br />brk(<span style="color: #800080">0</span>)                                  = <span style="color: #800080">0xab1000</span><br />access(<span style="color: #800000">"</span><span style="color: #800000">/etc/ld.so.nohwcap</span><span style="color: #800000">"</span>, F_OK)      = -<span style="color: #800080">1</span> ENOENT (No such file or directory)<br />mmap(NULL, <span style="color: #800080">8192</span>, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -<span style="color: #800080">1</span>, <span style="color: #800080">0</span>) = <span style="color: #800080">0x7f29379a7000</span><br />access(<span style="color: #800000">"</span><span style="color: #800000">/etc/ld.so.preload</span><span style="color: #800000">"</span>, R_OK)      = -<span style="color: #800080">1</span> ENOENT (No such file or directory)<br />...<br />brk(<span style="color: #800080">0</span>) = <span style="color: #800080">0xab1000</span><br />brk(<span style="color: #800080">0xad2000</span>) = <span style="color: #800080">0xad2000</span><br />fstat(<span style="color: #800080">1</span>, {st_mode=S_IFCHR|<span style="color: #800080">0620</span>, st_rdev=makedev(<span style="color: #800080">136</span>, <span style="color: #800080">0</span>), ...}) = <span style="color: #800080">0</span><br />open(<span style="color: #800000">"</span><span style="color: #800000">/dev/null</span><span style="color: #800000">"</span>, O_RDONLY) = <span style="color: #800080">3</span><br />fstat(<span style="color: #800080">3</span>, {st_mode=S_IFCHR|<span style="color: #800080">0666</span>, st_rdev=makedev(<span style="color: #800080">1</span>, <span style="color: #800080">3</span>), ...}) = <span style="color: #800080">0</span><br />read(<span style="color: #800080">3</span>, <span style="color: #800000">""</span>, <span style="color: #800080">32768</span>) = <span style="color: #800080">0</span><br />close(<span style="color: #800080">3</span>) = <span style="color: #800080">0</span><br />close(<span style="color: #800080">1</span>) = <span style="color: #800080">0</span><br />close(<span style="color: #800080">2</span>) = <span style="color: #800080">0</span><br />exit_group(<span style="color: #800080">0</span>) = ?</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<p>每一行都是一条系统调用，等号左边是系统调用的函数名及其参数，右边是该调用的返回值。<br />strace 显示这些调用的参数并返回符号形式的值。strace 从内核接收信息，而且不需要以任何特殊的方式来构建内核。</p>
<h1><span style="font-size: 18pt"><strong>strace参数</strong></span></h1>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre>-c 统计每一系统调用的所执行的时间,次数和出错的次数等. <br />-d 输出strace关于标准错误的调试信息. <br />-f 跟踪由fork调用所产生的子进程. <br />-ff 如果提供-o filename,则所有进程的跟踪结果输出到相应的filename.pid中,pid是各进程的进程号. <br />-F 尝试跟踪vfork调用.在-f时,vfork不被跟踪. <br />-h 输出简要的帮助信息. <br />-i 输出系统调用的入口指针. <br />-q 禁止输出关于脱离的消息. <br />-r 打印出相对时间关于,,每一个系统调用. <br />-t 在输出中的每一行前加上时间信息. <br />-tt 在输出中的每一行前加上时间信息,微秒级. <br />-ttt 微秒级输出,以秒了表示时间. <br />-T 显示每一调用所耗的时间. <br />-v 输出所有的系统调用.一些调用关于环境变量,状态,输入输出等调用由于使用频繁,默认不输出. <br />-V 输出strace的版本信息. <br />-x 以十六进制形式输出非标准字符串 <br />-xx 所有字符串以十六进制形式输出. <br />-a column <br />设置返回值的输出位置.默认 为40. <br />-e expr <br />指定一个表达式,用来控制如何跟踪.格式如下: <br />[qualifier=][!]value1[,value2]... <br />qualifier只能是 trace,abbrev,verbose,raw,signal,read,write其中之一.value是用来限定的符号或数字.默认的 qualifier是 trace.感叹号是否定符号.例如: <br />-eopen等价于 -e trace=open,表示只跟踪open调用.而-etrace!=open表示跟踪除了open以外的其他调用.有两个特殊的符号 all 和 none. <br />注意有些shell使用!来执行历史记录里的命令,所以要使用\\. <br />-e trace=<span style="color: #0000ff">set</span> <br />只跟踪指定的系统 调用.例如:-e trace=open,close,rean,write表示只跟踪这四个系统调用.默认的为set=all. <br />-e trace=file <br />只跟踪有关文件操作的系统调用. <br />-e trace=process <br />只跟踪有关进程控制的系统调用. <br />-e trace=network <br />跟踪与网络有关的所有系统调用. <br />-e strace=signal <br />跟踪所有与系统信号有关的 系统调用 <br />-e trace=ipc <br />跟踪所有与进程通讯有关的系统调用 <br />-e abbrev=<span style="color: #0000ff">set</span> <br />设定 strace输出的系统调用的结果集.-v 等与 abbrev=none.默认为abbrev=all. <br />-e raw=<span style="color: #0000ff">set</span> <br />将指 定的系统调用的参数以十六进制显示. <br />-e signal=<span style="color: #0000ff">set</span> <br />指定跟踪的系统信号.默认为all.如 signal=!SIGIO(或者signal=!io),表示不跟踪SIGIO信号. <br />-e read=<span style="color: #0000ff">set</span> <br />输出从指定文件中读出 的数据.例如: <br />-e read=<span style="color: #800080">3</span>,<span style="color: #800080">5</span> <br />-e write=<span style="color: #0000ff">set</span> <br />输出写入到指定文件中的数据. <br />-o filename <br />将strace的输出写入文件filename <br />-p pid <br />跟踪指定的进程pid. <br />-s strsize <br />指定输出的字符串的最大长度.默认为32.文件名一直全部输出. <br />-u username <br />以username 的UID和GID执行被跟踪的命令</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<p>&nbsp;</p>
<h1><strong><span style="font-size: 18pt">命令实例</span></strong></h1>
<p><br /><strong>通用的完整用法：</strong></p>
<div class="cnblogs_code"><pre>strace -o output.txt -T -tt -e trace=all -p <span style="color: #800080">28979</span></pre></div>
<p>上面的含义是 跟踪28979进程的所有系统调用（-e trace=all），并统计系统调用的花费时间，以及开始时间（并以可视化的时分秒格式显示），最后将记录结果存在output.txt文件里面。</p>
<p>&nbsp;</p>
<h1><strong><span style="font-size: 18pt">strace案例</span></strong></h1>
<p><strong><span style="font-size: 18pt">&nbsp;</span></strong></p>
<h2><span style="font-size: 14pt"><strong>&nbsp; 用strace调试程序</strong></span></h2>
<p>在理想世界里，每当一个程序不能正常执行一个功能时，它就会给出一个有用的错误提示，告诉你在足够的改正错误的线索。但遗憾的是，我们不是生活在理想世界 里，起码不总是生活在理想世界里。有时候一个程序出现了问题，你无法找到原因。<br />这就是调试程序出现的原因。strace是一个必不可少的 调试工具，strace用来监视系统调用。你不仅可以调试一个新开始的程序，也可以调试一个已经在运行的程序（把strace绑定到一个已有的PID上 面）。<br />首先让我们看一个真实的例子：启动KDE时出现问题<br />前一段时间，我在 启动KDE的时候出了问题，KDE的错误信息无法给我任何有帮助的线索。</p>
<div class="cnblogs_code"><pre>_KDE_IceTransSocketCreateListener: failed to bind listener<br />_KDE_IceTransSocketUNIXCreateListener: ...SocketCreateListener() failed<br />_KDE_IceTransMakeAllCOTSServerListeners: failed to create listener <span style="color: #0000ff">for</span> local<br /><br />Cannot establish any listening sockets DCOPServer self-test failed.</pre></div>
<p>对 我来说这个错误信息没有太多意义，只是一个对KDE来说至关重要的负责进程间通信的程序无法启动。我还可以知道这个错误和ICE协议（Inter Client Exchange）有关，除此之外，我不知道什么是KDE启动出错的原因。<strong><br /></strong></p>
<p>我决定采用strace看一下在启动 dcopserver时到底程序做了什么：</p>
<div class="cnblogs_code"><pre>strace -f -F -o ~/dcop-strace.txt dcopserver</pre></div>
<p>这里 -f -F选项告诉strace同时跟踪fork和vfork出来的进程，-o选项把所有strace输出写到~/dcop-strace.txt里 面，dcopserver是要启动和调试的程序。</p>
<p>再次出现错误之后，我检查了错误输出文件dcop-strace.txt，文件里有很多 系统调用的记录。在程序运行出错前的有关记录如下：<strong><br /></strong></p>
<p>&nbsp;</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre><span style="color: #800080">27207</span> mkdir(<span style="color: #800000">"</span><span style="color: #800000">/tmp/.ICE-unix</span><span style="color: #800000">"</span>, <span style="color: #800080">0777</span>) = -<span style="color: #800080">1</span> EEXIST (File exists)<br /><span style="color: #800080">27207</span> lstat64(<span style="color: #800000">"</span><span style="color: #800000">/tmp/.ICE-unix</span><span style="color: #800000">"</span>, {st_mode=S_IFDIR|S_ISVTX|<span style="color: #800080">0755</span>, st_size=<span style="color: #800080">4096</span>, ...}) = <span style="color: #800080">0</span><br /><span style="color: #800080">27207</span> unlink(<span style="color: #800000">"</span><span style="color: #800000">/tmp/.ICE-unix/dcop27207-1066844596</span><span style="color: #800000">"</span>) = -<span style="color: #800080">1</span> ENOENT (No such file or directory)<br /><span style="color: #800080">27207</span> bind(<span style="color: #800080">3</span>, {sin_family=AF_UNIX, path=<span style="color: #800000">"</span><span style="color: #800000">/tmp/.ICE-unix/dcop27207-1066844596</span><span style="color: #800000">"</span>}, <span style="color: #800080">38</span>) = -<span style="color: #800080">1</span> EACCES (Permission denied) <br /><span style="color: #800080">27207</span> write(<span style="color: #800080">2</span>, <span style="color: #800000">"</span><span style="color: #800000">_KDE_IceTrans</span><span style="color: #800000">"</span>, <span style="color: #800080">13</span>) = <span style="color: #800080">13</span><br /><span style="color: #800080">27207</span> write(<span style="color: #800080">2</span>, <span style="color: #800000">"</span><span style="color: #800000">SocketCreateListener: failed to </span><span style="color: #800000">"</span>..., <span style="color: #800080">46</span>) = <span style="color: #800080">46</span><br /><span style="color: #800080">27207</span> close(<span style="color: #800080">3</span>) = <span style="color: #800080">0</span> <span style="color: #800080">27207</span> write(<span style="color: #800080">2</span>, <span style="color: #800000">"</span><span style="color: #800000">_KDE_IceTrans</span><span style="color: #800000">"</span>, <span style="color: #800080">13</span>) = <span style="color: #800080">13</span><br /><span style="color: #800080">27207</span> write(<span style="color: #800080">2</span>, <span style="color: #800000">"</span><span style="color: #800000">SocketUNIXCreateListener: ...Soc</span><span style="color: #800000">"</span>..., <span style="color: #800080">59</span>) = <span style="color: #800080">59</span><br /><span style="color: #800080">27207</span> umask(<span style="color: #800080">0</span>) = <span style="color: #800080">0</span> <span style="color: #800080">27207</span> write(<span style="color: #800080">2</span>, <span style="color: #800000">"</span><span style="color: #800000">_KDE_IceTrans</span><span style="color: #800000">"</span>, <span style="color: #800080">13</span>) = <span style="color: #800080">13</span><br /><span style="color: #800080">27207</span> write(<span style="color: #800080">2</span>, <span style="color: #800000">"</span><span style="color: #800000">MakeAllCOTSServerListeners: fail</span><span style="color: #800000">"</span>..., <span style="color: #800080">64</span>) = <span style="color: #800080">64</span><br /><span style="color: #800080">27207</span> write(<span style="color: #800080">2</span>, <span style="color: #800000">"</span><span style="color: #800000">Cannot establish any listening s</span><span style="color: #800000">"</span>..., <span style="color: #800080">39</span>) = <span style="color: #800080">39</span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<p><span style="font-size: small"><span style="font-size: small"><br /><span style="font-size: 14px">其中第一行显示程序试图创建/tmp/.ICE-unix目录，权限为0777，这个操作因为目录已经存在而失败了。第二个系统调用（lstat64）检查 了目录状态，并显示这个目录的权限是0755，这里出现了第一个程序运行错误的线索：程序试图创建属性为0777的目录，但是已经存在了一个属性为 0755的目录。第三个系统调用（unlink）试图删除一个文件，但是这个文件并不存在。这并不奇怪，因为这个操作只是试图删掉可能存在的老文件。</span></span></span></p>
<p><span style="font-size: 14px">但是，第四行确认了错误所在。他试图绑定到/tmp/.ICE-unix/dcop27207-1066844596，但是出现了拒绝访问错误。. ICE_unix目录的用户和组都是root，并且只有所有者具有写权限。一个非root用户无法在这个目录下面建立文件，如果把目录属性改成0777， 则前面的操作有可能可以执行，而这正是第一步错误出现时进行过的操作。</span></p>
<p><span style="font-size: 14px">所以我运行了chmod 0777 /tmp/.ICE-unix之后KDE就可以正常启动了，问题解决了，用strace进行跟踪调试只需要花很短的几分钟时间跟踪程序运行，然后检查并分 析输出文件。</span></p>
<p><span style="font-size: small"><span style="font-size: small"><span style="font-size: 14px">说明：运行chmod 0777只是一个测试，一般不要把一个目录设置成所有用户可读写，同时不设置粘滞位(sticky bit)。给目录设置粘滞位可以阻止一个用户随意删除可写目录下面其他人的文件。一般你会发现/tmp目录因为这个原因设置了粘滞位。KDE可以正常启动 之后，运行chmod +t /tmp/.ICE-unix给.ICE_unix设置粘滞位。</span><br /></span></span></p>
<p>&nbsp;</p>
<h2><span style="font-size: 14pt"><strong>&nbsp; 解决库依赖问题</strong></span></h2>
<p>starce 的另一个用处是解决和动态库相关的问题。当对一个可执行文件运行ldd时，它会告诉你程序使用的动态库和找到动态库的位置。但是如果你正在使用一个比较老 的glibc版本（2.2或更早），你可能会有一个有bug的ldd程序，它可能会报告在一个目录下发现一个动态库，但是真正运行程序时动态连接程序 （/lib/ld-linux.so.2）却可能到另外一个目录去找动态连接库。这通常因为/etc/ld.so.conf和 /etc/ld.so.cache文件不一致，或者/etc/ld.so.cache被破坏。在glibc 2.3.2版本上这个错误不会出现，可能ld-linux的这个bug已经被解决了。<br /><br />尽管这样，ldd并不能把所有程序依赖的动态库列出 来，系统调用dlopen可以在需要的时候自动调入需要的动态库，而这些库可能不会被ldd列出来。作为glibc的一部分的NSS（Name Server Switch）库就是一个典型的例子，NSS的一个作用就是告诉应用程序到哪里去寻找系统帐号数据库。应用程序不会直接连接到NSS库，glibc则会通 过dlopen自动调入NSS库。如果这样的库偶然丢失，你不会被告知存在库依赖问题，但这样的程序就无法通过用户名解析得到用户ID了。让我们看一个例子：<br />whoami程序会给出你自己的用户名，这个程序在一些需要知道运行程序的真正用户的脚本程序里面非常有用，whoami的一个示例 输出如下：</p>
<div class="cnblogs_code"><pre># whoami<br />root</pre></div>
<p>假设因为某种原因在升 级glibc的过程中负责用户名和用户ID转换的库NSS丢失，我们可以通过把nss库改名来模拟这个环境：</p>
<div class="cnblogs_code"><pre># mv /lib/libnss_files.so.<span style="color: #800080">2</span> /lib/libnss_files.so.<span style="color: #800080">2</span>.backup <br /># whoami<br />whoami: cannot find username <span style="color: #0000ff">for</span> UID <span style="color: #800080">0</span></pre></div>
<p>这里你可以看到，运行whoami时出现了错误，ldd程序的输出不会提供有用的帮助：</p>
<div class="cnblogs_code"><pre># ldd /usr/bin/whoami<br />libc.so.<span style="color: #800080">6</span> =&gt; /lib/libc.so.<span style="color: #800080">6</span> (<span style="color: #800080">0x4001f000</span>)<br />/lib/ld-linux.so.<span style="color: #800080">2</span> =&gt; /lib/ld-linux.so.<span style="color: #800080">2</span> (<span style="color: #800080">0x40000000</span>)</pre></div>
<p>你只会看到whoami依赖Libc.so.6和ld-linux.so.2，它没有给出运行whoami所必须的其他库。这里时用strace跟踪 whoami时的输出：</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre>strace -o whoami-strace.txt whoami<br /><br />open(<span style="color: #800000">"</span><span style="color: #800000">/lib/libnss_files.so.2</span><span style="color: #800000">"</span>, O_RDONLY) = -<span style="color: #800080">1</span> ENOENT (No such file or directory)<br />open(<span style="color: #800000">"</span><span style="color: #800000">/lib/i686/mmx/libnss_files.so.2</span><span style="color: #800000">"</span>, O_RDONLY) = -<span style="color: #800080">1</span> ENOENT (No such file or directory)<br />stat64(<span style="color: #800000">"</span><span style="color: #800000">/lib/i686/mmx</span><span style="color: #800000">"</span>, <span style="color: #800080">0xbffff190</span>) = -<span style="color: #800080">1</span> ENOENT (No such file or directory) <br />open(<span style="color: #800000">"</span><span style="color: #800000">/lib/i686/libnss_files.so.2</span><span style="color: #800000">"</span>, O_RDONLY) = -<span style="color: #800080">1</span> ENOENT (No such file or directory)<br />stat64(<span style="color: #800000">"</span><span style="color: #800000">/lib/i686</span><span style="color: #800000">"</span>, <span style="color: #800080">0xbffff190</span>) = -<span style="color: #800080">1</span> ENOENT (No such file or directory)<br />open(<span style="color: #800000">"</span><span style="color: #800000">/lib/mmx/libnss_files.so.2</span><span style="color: #800000">"</span>, O_RDONLY) = -<span style="color: #800080">1</span> ENOENT (No such file or directory)<br />stat64(<span style="color: #800000">"</span><span style="color: #800000">/lib/mmx</span><span style="color: #800000">"</span>, <span style="color: #800080">0xbffff190</span>) = -<span style="color: #800080">1</span> ENOENT (No such file or directory) <br />open(<span style="color: #800000">"</span><span style="color: #800000">/lib/libnss_files.so.2</span><span style="color: #800000">"</span>, O_RDONLY) = -<span style="color: #800080">1</span> ENOENT (No such file or directory)<br />stat64(<span style="color: #800000">"</span><span style="color: #800000">/lib</span><span style="color: #800000">"</span>, {st_mode=S_IFDIR|<span style="color: #800080">0755</span>, st_size=<span style="color: #800080">2352</span>, ...}) = <span style="color: #800080">0</span><br />open(<span style="color: #800000">"</span><span style="color: #800000">/usr/lib/i686/mmx/libnss_files.so.2</span><span style="color: #800000">"</span>, O_RDONLY) = -<span style="color: #800080">1</span> ENOENT (No such file or directory)<br />stat64(<span style="color: #800000">"</span><span style="color: #800000">/usr/lib/i686/mmx</span><span style="color: #800000">"</span>, <span style="color: #800080">0xbffff190</span>) = -<span style="color: #800080">1</span> ENOENT (No such file or directory) <br />open(<span style="color: #800000">"</span><span style="color: #800000">/usr/lib/i686/libnss_files.so.2</span><span style="color: #800000">"</span>, O_RDONLY) = -<span style="color: #800080">1</span> ENOENT (No such file or directory)</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" onclick="copyCnblogsCode(this)" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<p>你可以发现在不同目录下面查找libnss.so.2的尝试，但是都失败了。如果没有strace这样的工具，很难发现这个错误是由于缺少动态库造成的。现 在只需要找到libnss.so.2并把它放回到正确的位置就可以了。　</p>
<p>&nbsp;</p>
<h2><span style="font-size: 14pt"><strong>&nbsp; 限制strace只跟踪特定的系统调用</strong></span></h2>
<p>如果你已经知道你要找什么，你可以让strace只跟踪一些类型的系统调用。例如，你需要看看在configure脚本里面执行的程序，你需要监视的系统调 用就是execve。让strace只记录execve的调用用这个命令：</p>
<div class="cnblogs_code"><pre>strace -f -o configure-strace.txt -e execve ./configure</pre></div>
<p>&nbsp;</p>
<p>参考资料:<a href="http://blog.sina.com.cn/s/blog_6e07f1eb0100t7rg.html"><font color="#000080">http://blog.sina.com.cn/s/blog_6e07f1eb0100t7rg.html</font></a></p>
<p>　　　 　<a href="http://blog.csdn.net/zdl1016/article/details/6359598"><font color="#000080">http://blog.csdn.net/zdl1016/article/details/6359598</font></a></p><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/87576.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2013-05-29 19:03 <a href="http://www.cnitblog.com/liaoqingshan/archive/2013/05/29/87576.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>android的apk使用proguard混淆</title><link>http://www.cnitblog.com/liaoqingshan/archive/2013/05/18/proguard-eclipse.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Sat, 18 May 2013 05:56:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2013/05/18/proguard-eclipse.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/87465.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2013/05/18/proguard-eclipse.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/87465.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/87465.html</trackback:ping><description><![CDATA[自己辛苦写的程序总不希望被别人轻松反编译后修改成他人。我用的是proguard混淆。在网上找了许多文章，试了许多次，总算混淆成功了一回。<br /><strong>先提提我的失败经验：</strong><br />1.网上说需要proguard.cfg文件，我看是不需要的。开始我找关天，还手工生成此文件，也没有用。最终是不需要它的。<br />2.还有人说要打开项目目录下project.properties文件，去掉#proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt前的#号。我试了也没有用。<br />3.在proguard目录下有一个proguardgui.bat，大概可以脱离eclipse单独用来混淆。结果搞头天，不是说有duplicate class definitions，就是说有&nbsp;Warning: XXX: can't find referenced class。即使先生成配置文件apk.pro，然后在apk.pro中添加 -ignorewarnings，再加载此配置文件，然后生成没有错了，结果生成的结果为空。啥也没有。唉，水太深。搞不定。<br />最终在网上看到有文章说:<br />如果通过Run as -&gt; Android application生成的bin\*.apk是没有效果的，要通过export来生成！天杀的！<br />不知道正统的android教材有没有讲到要和export来生成程序，我是半路出家的，看到run可以直接生成apk就一直以为这样就行了。咳咳，学艺不精害死人啊。<br /><strong>下面再讲讲成功的方法</strong>，知道路子就很简单了。<br />前提：我用的环境是adt-bundle-windows-x86，这是一个已经包含eclipse+adk+proguard的IDE，只需要设置一下java目录就能用了。其它环境我就不知道了。<br />1.上面说的第2条，还是要的。<br />proguard.config=你的sdk/tools/proguard/proguard-android.txt:proguard-project.txt<br />我特地试了一下，前面加了#生成的结果就没有混淆。<br />2.创建一个新android程序，什么代码也不写----这样可以容易混淆，不出现其它错误。<br />在菜单上选择file-&gt;Export，然后选择Android-&gt;Export Android Application，<br />3.如果第一次这么做，需要创建一个key，我暂时也不知道干嘛用的，反正选择一个目录，定义一个新的名称，再输入密码，它就保存下来。后面还要输入一大堆信息创建这个key.<br />4.再次输入密码创建应用程序，然后输入最终的文件名。<br />5.完成。<br />你会发现，生成的apk，比原来小多了。用反编译工具查看，所有的类名，都成了a,b,c,d。<br />大功告成。<br /><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/87465.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2013-05-18 13:56 <a href="http://www.cnitblog.com/liaoqingshan/archive/2013/05/18/proguard-eclipse.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>android 程序安装路径选择----转载</title><link>http://www.cnitblog.com/liaoqingshan/archive/2013/03/26/87163.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Tue, 26 Mar 2013 06:05:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2013/03/26/87163.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/87163.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2013/03/26/87163.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/87163.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/87163.html</trackback:ping><description><![CDATA[<div><h3><a href="http://blog.csdn.net/q445697127/article/details/7587271">android  程序安装路径选择 </a></h3></div> <div>分类： <a href="http://blog.csdn.net/q445697127/article/category/1135706">android</a> 2012-05-21 14:46 <span title="阅读次数">1032人阅读</span> <span title="评论次数"><a href="http://blog.csdn.net/q445697127/article/details/7587271#comments">评论</a>(0)</span> <a title="收藏" href="http://blog.csdn.net/q445697127/article/details/7587271">收藏</a> <a title="举报" href="http://blog.csdn.net/q445697127/article/details/7587271#report">举报</a> </div> <div><a href="http://blog.csdn.net/tag/details.html?tag=android" target="_blank">android</a><a href="http://blog.csdn.net/tag/details.html?tag=%e5%ad%98%e5%82%a8" target="_blank">存储</a><a href="http://blog.csdn.net/tag/details.html?tag=%e6%89%8b%e6%9c%ba" target="_blank">手机</a><a href="http://blog.csdn.net/tag/details.html?tag=google" target="_blank">google</a><a href="http://blog.csdn.net/tag/details.html?tag=%e5%8a%a0%e5%af%86" target="_blank">加密</a></div> <div id="article_content"> <div bg_html"=""> <div> <div><strong>[html]</strong> <a title="view plain" href="http://blog.csdn.net/q445697127/article/details/7587271#">view  plain</a><a title="copy" href="http://blog.csdn.net/q445697127/article/details/7587271#">copy</a><a title="print" href="http://blog.csdn.net/q445697127/article/details/7587271#">print</a><a title="?" href="http://blog.csdn.net/q445697127/article/details/7587271#">?</a></div></div> <ol> <li>&lt;manifest&nbsp;android:installLocation="auto"&gt;&nbsp;&nbsp;&nbsp;</li></ol></div>android:installLocation可以设置为"auto"、"internalOnly"、"preferExternal"三个值中的任何一个.<br /><br />auto:程序可能被安装在外部存储介质上(例如:SD  Card),但是默认会被安装到手机内存中.当手机内存为空时,程序将被安装到外部存储介质上.当程序安装到手机上后,用户可以决定把程序放在外部储介质还是内存中.<br /><br />internalOnly:默认值.当设置为该值时,程序只能被安装在内存中,如果内存为空,则程序将不能成功安装.<br /><br />preferExternal:将程序安装在外部存储介质上,但是系统不保证程序一定会被安装到外部存储介质上.当外部存储介质不可以或空时,程序将被安装到内存中.程序使用了for  ward-locking机制时也将被安装到内存中,因为外部存储不支持此机制.程序安装后,用户可以自由切换程序应该在外部还是内部存储介质上.<br /><br />注意:当程序使用了Google  Play的Copy Protection特性时,只能安装到内存中.<br /><br />当程序被安装到外部存储介质时,<br /><br />&#9312;  .apk文件将被移动到外部存储介质上,但是程序的数据仍然会在内存中<br /><br />&#9313;  保存.apk文件的容器将会使用一个随机生成的密钥进行加密,这样只有安装该程序的设置可以使用存在外部存储介质上的数据.<br /><br />警告:当外部存储介质被卸载时,安装在该外部存储介质上的程序将立刻被终止掉!</div><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/87163.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2013-03-26 14:05 <a href="http://www.cnitblog.com/liaoqingshan/archive/2013/03/26/87163.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android中如何获取应用版本号----转载</title><link>http://www.cnitblog.com/liaoqingshan/archive/2013/03/10/87036.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Sun, 10 Mar 2013 03:35:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2013/03/10/87036.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/87036.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2013/03/10/87036.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/87036.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/87036.html</trackback:ping><description><![CDATA[<p><strong><span style="color: rgb(255,0,0)">应用场景</span></strong>：<br />1、在界面中显示应用程序的版本号；<br />2、用户启动该应用，后台判断该应用是否是最新版本。<br />上述情景都需要在程序中自动获取到应用的版本号。</p>
<p><strong><span style="color: rgb(255,0,0)">思路简介</span></strong>：<br />在Android中，应用程序的版本号是在AndroidManifest.xml文件中进行配置的，而PackageInfo类则封装了从该配置文件中获取的所有信息，描述了包内容的整体信息，因此，可以使用PackageInfo对象的versionName属性获取应用的版本号。<br />要怎么获取PackageInfo对象呢？可以通过PackageManager对象来获取。PackageManager是一个检索当前已安装在设备上的相关应用程序包的各种信息的类。PackageManager对象中的getPackageInfo方法可以获取PackageInfo对象，该方法需要传递两个参数：应用包名和条件。通常情况下，应用程序的包名可以通过Activity或Context（Activity继承自Context）的getPackageName()方法获取，而添加可以有很多设置，通常设置为0。<br />最后是PackageManager对象的获取，Context对象提供了getPackageManager()方法来获取该对象。</p>
<p>综上，<strong><span style="color: rgb(255,0,0)">模板代码</span></strong>如下：（注意，此处封装的方法位于某个Activity中，因此直接使用this来代替Context对象）</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre><span style="color: rgb(0,128,128)"> 1</span> <span style="color: rgb(0,128,0)">/**</span>
<span style="color: rgb(0,128,128)"> 2</span> <span style="color: rgb(0,128,0)"> * 获取版本号
</span><span style="color: rgb(0,128,128)"> 3</span> <span style="color: rgb(0,128,0)"> * </span><span style="color: rgb(128,128,128)">@return</span><span style="color: rgb(0,128,0)"> 当前应用的版本号
</span><span style="color: rgb(0,128,128)"> 4</span>  <span style="color: rgb(0,128,0)">*/</span>
<span style="color: rgb(0,128,128)"> 5</span> <span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)"> String getVersion() {
</span><span style="color: rgb(0,128,128)"> 6</span>     <span style="color: rgb(0,0,255)">try</span><span style="color: rgb(0,0,0)"> {
</span><span style="color: rgb(0,128,128)"> 7</span>         PackageManager manager = <span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.getPackageManager();
</span><span style="color: rgb(0,128,128)"> 8</span>         PackageInfo info = manager.getPackageInfo(<span style="color: rgb(0,0,255)">this</span>.getPackageName(), 0<span style="color: rgb(0,0,0)">);
</span><span style="color: rgb(0,128,128)"> 9</span>         String version =<span style="color: rgb(0,0,0)"> info.versionName;
</span><span style="color: rgb(0,128,128)">10</span>         <span style="color: rgb(0,0,255)">return</span> <span style="color: rgb(0,0,255)">this</span>.getString(R.string.version_name) +<span style="color: rgb(0,0,0)"> version;
</span><span style="color: rgb(0,128,128)">11</span>     } <span style="color: rgb(0,0,255)">catch</span><span style="color: rgb(0,0,0)"> (Exception e) {
</span><span style="color: rgb(0,128,128)">12</span> <span style="color: rgb(0,0,0)">        e.printStackTrace();
</span><span style="color: rgb(0,128,128)">13</span>         <span style="color: rgb(0,0,255)">return</span> <span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.getString(R.string.can_not_find_version_name);
</span><span style="color: rgb(0,128,128)">14</span> <span style="color: rgb(0,0,0)">    }
</span><span style="color: rgb(0,128,128)">15</span> }</pre></div><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/87036.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2013-03-10 11:35 <a href="http://www.cnitblog.com/liaoqingshan/archive/2013/03/10/87036.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>android软件的版本更新----转载</title><link>http://www.cnitblog.com/liaoqingshan/archive/2013/03/10/87035.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Sun, 10 Mar 2013 03:32:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2013/03/10/87035.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/87035.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2013/03/10/87035.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/87035.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/87035.html</trackback:ping><description><![CDATA[<p>做个网站的安卓客户端，用户安装到自己手机上，如果我出了新版本怎么办呢？要有版本更新功能。 <br />本来版本检测最好可以自动进行。但如果每次开启程序，都要先检测一轮，是一种浪费，毕竟版本更新是小概率的事情。或许可以程序开启的时候，判断一下时间，单日就检测，双日就不检测，或者随机什么的，降低一下检测的频率？ </p>
<p>我采取的做法是将检测功能做到了菜单上，用户有需要，就手动打开自己检测一下。反正我们这个是网站客户端，有版本更新，在网站上发个通告就行了。 <br />版本检测与更新有以下几个关键步骤： <br />1、检测有无新版本 <br />2、下载新版本 <br />3、安装替换新版本 <br />我处理的方案是 <br />1、在assets文件夹新增一个文件：ver.cfg，记录版本信息，纯文本格式，内容只有一句话： <br />复制代码 代码如下:<br />Version=1.0 </p>
<p>&nbsp;<br />这个会随安装包装到用户的手机上 <br />然后在网站里面，设置一XML文件ver_apk.xml，内容也只有这么一点： <br />复制代码 代码如下:<br />&lt;?xml version="1.0" encoding="utf-8" ?&gt; <br />&lt;string&gt;1.0&lt;/string&gt; </p>
<p>检测的时候，就先访问网站的这个XML，得到最新版本号，然后与手机上的ver.cfg文件里记录的进行比对，不同的话就可以认为存在新版本，提示进行更新。 <br />2、下载的话就是直接下载的，我还不知道怎么弄断点续传 <br />3、安装替换，关键在于签名。就是每个版本的签名要保持一致。否则新的无法替换旧的，提示安装未完成。 <br />------------------- 天气太冷，咯咯咯 ------------------------------------ <br />这个功能做在菜单上，触发代码如下： <br />复制代码 代码如下:<br />//========================================================================== <br />// 菜单 <br />//========================================================================== <br />private static final String urlApk = "<a href="http://3g.***.com/tool/***.apk">http://3g.***.com/tool/***.apk</a>"; <br />private static final String urlVer = "<a href="http://3g.***.com/tool/ver_apk.xml">http://3g.***.com/tool/ver_apk.xml</a>"; <br />@Override <br />public boolean onCreateOptionsMenu(Menu menu) { <br />menu.add(Menu.NONE, Menu.FIRST + 1, 5, "检测更新").setIcon( <br />android.R.drawable.ic_menu_upload); <br />menu.add(Menu.NONE,Menu.FIRST+2,4,"退出").setIcon(android.R.drawable.ic_lock_power_off); <br />return true; <br />} <br />@Override <br />public boolean onOptionsItemSelected(MenuItem item) { <br />switch (item.getItemId()) { <br />case Menu.FIRST + 1: <br />Toast.makeText(this, "正在检测版本", Toast.LENGTH_LONG).show(); <br />UpdateVer uv = new UpdateVer(urlApk,urlVer,MainActivity.this); <br />uv.checkVer(); <br />break; <br />case Menu.FIRST + 2: <br />confirmExit(); <br />break; <br />} <br />return false; <br />} </p>
<p>检测更新因为代码比较多，写成一个类进行封装 <br />UpdateVer.java <br />复制代码 代码如下:<br />package android.***; <br />import android.app.Activity; <br />import android.app.AlertDialog; <br />import android.app.Dialog; <br />import android.app.ProgressDialog; <br />import android.content.Context; <br />import android.content.DialogInterface; <br />import android.content.Intent; <br />import android.net.Uri; <br />import android.os.AsyncTask; <br />import android.util.Log; <br />import android.webkit.URLUtil; <br />import android.widget.Toast; <br />import java.io.File; <br />import java.io.FileNotFoundException; <br />import java.io.FileOutputStream; <br />import java.io.IOException; <br />import java.io.InputStream; <br />import java.net.MalformedURLException; <br />import java.net.URL; <br />import java.net.URLConnection; <br />import java.util.Properties; <br />import org.xml.sax.InputSource; <br />import java.text.SimpleDateFormat; <br />import java.util.Date; <br />public class UpdateVer extends Activity{ <br />private static final String TAG = "DOWNLOADAPK"; <br />private String PastVersion; <br />private String NowVersion; <br />public ProgressDialog pBar; <br />private String currentFilePath = ""; <br />private String fileEx=""; <br />private String fileNa=""; <br />private String strURL=""; <br />private String VersionUri =""; <br />private Context mContext; <br />private final String fileVer = "ver.cfg"; <br />public UpdateVer(String urlapk,String urlver,final Context context){ <br />SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss"); <br />String ver = "?ver=" + df.format(new Date());//主要是避开手机的缓存 <br />strURL = urlapk + ver; <br />VersionUri = urlver + ver; <br />mContext = context; <br />} <br />public void checkVer() { <br />// 解析Version网页，获取版本号 <br />getVersionxml(VersionUri); <br />} <br />private void compareVer() { <br />load(); </p>
<p>//当有最新版本的时候 <br />if(PastVersion != null &amp;&amp; !PastVersion.equals(NowVersion)){ <br />Dialog dialog = new AlertDialog.Builder(mContext).setTitle("系统更新") <br />.setMessage(String.format("发现新版本%s，目前版本为%s，请更新！",NowVersion,PastVersion))// 设置内容 <br />// 设置确定按钮 <br />.setPositiveButton("确定" <br />,new DialogInterface.OnClickListener() { <br />@Override <br />public void onClick(DialogInterface dialog, <br />int which) { <br />pBar = new ProgressDialog(mContext); <br />pBar.setTitle("正在下载"); <br />pBar.setMessage("请稍候..."); <br />pBar.setProgressStyle(ProgressDialog.STYLE_SPINNER); <br />fileEx = strURL.substring(strURL.lastIndexOf(".") + 1,strURL.length()).toLowerCase(); <br />fileEx = fileEx.substring(0,fileEx.lastIndexOf("?")); <br />fileNa = strURL.substring(strURL.lastIndexOf("/") + 1,strURL.lastIndexOf(".")); <br />getFile(strURL); <br />} <br />}).setNegativeButton("取消", <br />new DialogInterface.OnClickListener() { <br />@Override <br />public void onClick(DialogInterface dialog, <br />int whichButton) { <br />// 点击"取消"按钮之后退出程序 <br />} <br />}).create();// 创建 <br />// 显示对话框 <br />dialog.show(); <br />} <br />else{ <br />Toast.makeText(mContext, String.format("当前为最新版本%s",PastVersion), Toast.LENGTH_LONG).show(); <br />} <br />} <br />private void getFile(final String strPath) <br />{ <br />pBar.show(); <br />try{ <br />if (strPath.equals(currentFilePath) ){ <br />getDataSource(strPath); <br />} <br />currentFilePath = strPath; <br />Runnable r = new Runnable(){ <br />@Override <br />public void run() <br />{ <br />try{ <br />getDataSource(strPath); <br />} <br />catch (Exception e){ <br />Log.e(TAG, e.getMessage(), e); <br />} <br />} <br />}; <br />new Thread(r).start(); <br />} <br />catch(Exception e){ <br />e.printStackTrace(); <br />} <br />} <br />/*取得远程文件*/ <br />private void getDataSource(String strPath) throws Exception { <br />if (!URLUtil.isNetworkUrl(strPath)) { <br />Log.d("Tag","error"); <br />} <br />else { <br />/*取得URL*/ <br />URL myURL = new URL(strPath); <br />/*建立联机*/ <br />URLConnection conn = myURL.openConnection(); <br />conn.connect(); <br />/*InputStream 下载文件*/ <br />InputStream is = conn.getInputStream(); <br />if (is == null) { <br />Log.d("tag","error"); <br />throw new RuntimeException("没有读取到文件内容"); <br />} <br />/*建立临时文件*/ <br />File myTempFile = File.createTempFile(fileNa, "." + fileEx); <br />myTempFile.getAbsolutePath(); <br />/*将文件写入临时盘*/ <br />FileOutputStream fos = new FileOutputStream(myTempFile); <br />byte buf[] = new byte[128]; <br />do{ <br />int numread = is.read(buf); <br />if (numread &lt;= 0) { <br />break; <br />} <br />fos.write(buf, 0, numread); <br />}while (true); </p>
<p>/*打开文件进行安装*/ <br />openFile(myTempFile); <br />try { <br />is.close(); <br />} <br />catch (Exception ex){ <br />Log.d("Tag","error"); <br />Log.e(TAG, "error: " + ex.getMessage(), ex); <br />} <br />} <br />} <br />/* 在手机上打开文件 */ <br />private void openFile(File f) { <br />pBar.cancel(); <br />Intent intent = new Intent(); <br />intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); <br />intent.setAction(android.content.Intent.ACTION_VIEW); <br />/* 调用getMIMEType()来取得MimeType */ <br />String type = getMIMEType(f); <br />/* 设定intent的file与MimeType */ <br />intent.setDataAndType(Uri.fromFile(f),type); <br />mContext.startActivity(intent); <br />} <br />/* 判断文件MimeType的method */ <br />private String getMIMEType(File f) { <br />String type = ""; <br />String fName = f.getName(); <br />/* 取得扩展名 */ <br />String end = fName.substring(fName.lastIndexOf(".")+1,fName.length()).toLowerCase(); </p>
<p>/* 按扩展名的类型决定MimeType */ <br />if(end.equals("m4a") <br />|| end.equals("mp3") <br />|| end.equals("mid") <br />|| end.equals("xmf") <br />|| end.equals("ogg") <br />|| end.equals("wav")){ <br />type = "audio"; <br />} <br />else if(end.equals("3gp") || end.equals("mp4")){ <br />type = "video"; <br />} <br />else if(end.equals("jpg") <br />|| end.equals("gif") <br />|| end.equals("png") <br />|| end.equals("jpeg") <br />|| end.equals("bmp")){ <br />type = "image"; <br />} <br />else if(end.equals("apk")){ <br />/* android.permission.INSTALL_PACKAGES */ <br />type = "application/vnd.android.package-archive"; <br />} <br />else{ <br />type = "*"; <br />} <br />/*如果无法直接打开，就跳出软件清单给使用者选择 */ <br />if(!end.equals("apk")){ <br />type += "/*"; <br />} <br />return type; <br />} <br />private void getVersionxml(String resourceUrl){ <br />GetVer gv = new GetVer(); <br />gv.execute(resourceUrl); <br />} <br />private boolean load(){ <br />Properties properties = new Properties(); <br />try{ <br />InputStream stream = mContext.getAssets().open(fileVer); <br />//FileInputStream stream = mContext.openFileInput(fileVer); <br />//读取文件内容 <br />properties.load(stream); <br />} <br />catch (FileNotFoundException e){ <br />return false; <br />} <br />catch(IOException e){ <br />return false; <br />} <br />catch(Exception e){ <br />return false; <br />} <br />PastVersion = String.valueOf(properties.get("Version").toString()); <br />return true; <br />} </p>
<p>//========================================================================== <br />// GetVer <br />//========================================================================== <br />class GetVer extends AsyncTask&lt;String, Integer, String&gt; { <br />@Override <br />protected String doInBackground(String... urlVer) { <br />String db = null; <br />URL url = null; </p>
<p>try { <br />url = new URL(urlVer[0]); <br />} <br />catch (MalformedURLException e) { <br />e.printStackTrace(); <br />} <br />InputSource is = null; <br />try { <br />is = new InputSource(url.openStream()); <br />is.setEncoding("UTF-8"); <br />db = SAXGetVersionService.readRssXml(is); <br />} <br />catch (Exception e) { <br />e.printStackTrace(); <br />} <br />return db; <br />} <br />@Override <br />protected void onCancelled() { <br />super.onCancelled(); <br />} <br />@Override <br />protected void onPostExecute(String result) { <br />NowVersion = result; <br />compareVer(); <br />} <br />} <br />} </p>
<p>AndroidManifest.xml要加上几句 <br />复制代码 代码如下:<br />&lt;uses-permission android:name="android.permission.INTERNET" /&gt; <br />&lt;uses-permission android:name="android.permission.INSTALL_PACKAGES"/&gt; <br />&lt;uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/&gt; <br />&lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/&gt; <br />&lt;uses-permission android:name="android.permission.RESTART_PACKAGES" /&gt; <br />&lt;uses-permission android:name="android.permission.READ_PHONE_STATE" /&gt; <br />&lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt; <br />&lt;uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /&gt; <br />&lt;uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /&gt; <br />详细出处参考：<a href="http://www.jb51.net/article/33058.htm">http://www.jb51.net/article/33058.htm</a></p><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/87035.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2013-03-10 11:32 <a href="http://www.cnitblog.com/liaoqingshan/archive/2013/03/10/87035.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android ListView常用用法----转载</title><link>http://www.cnitblog.com/liaoqingshan/archive/2013/03/04/87025.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Mon, 04 Mar 2013 14:16:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2013/03/04/87025.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/87025.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2013/03/04/87025.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/87025.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/87025.html</trackback:ping><description><![CDATA[<p>ListView是比较常用的控件，但一直都觉得创建ListView步骤有点繁琐，故在此总结一下，方便查阅。</p>
<p>程序效果是实现一个ListView,ListView里面有标题，内容和图片，并加入点击和长按响应。</p>
<p>&nbsp;</p>
<p><img alt="" src="http://dl.iteye.com/upload/picture/pic/50539/53b86995-cb1d-3058-83fa-6550dcc94d00.png" /></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><img alt="" src="http://dl.iteye.com/upload/picture/pic/50537/dd6b52aa-a9b4-37c0-87e9-d9ee84eedd0d.png" /></p>
<p>&nbsp;</p>
<p>首先在xml里面定义一个ListView</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Xml代码 <a title="复制代码" href="http://www.iteye.com/topic/540423#"><img alt="复制代码" src="http://www.iteye.com/images/icon_copy.gif" /></a> <a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://www.iteye.com/images/icon_star.png" /><img style="display: none" class="spinner" src="http://www.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-xml"><li><span class="tag">&lt;?</span><span class="tag-name">xml</span><span> </span><span class="attribute">version</span><span>=</span><span class="attribute-value">"1.0"</span><span> </span><span class="attribute">encoding</span><span>=</span><span class="attribute-value">"utf-8"</span><span class="tag">?&gt;</span><span> </span></li><li><span class="tag">&lt;</span><span class="tag-name">LinearLayout</span><span> </span></li><li><span class="attribute">android:id</span><span>=</span><span class="attribute-value">"@+id/LinearLayout01"</span><span> </span></li><li><span class="attribute">android:layout_width</span><span>=</span><span class="attribute-value">"fill_parent"</span><span> </span></li><li><span class="attribute">android:layout_height</span><span>=</span><span class="attribute-value">"fill_parent"</span><span> </span></li><li><span class="attribute">xmlns:android</span><span>=</span><span class="attribute-value">"http://schemas.android.com/apk/res/android"</span><span class="tag">&gt;</span><span> </span></li><li><span class="tag">&lt;</span><span class="tag-name">ListView</span><span> </span><span class="attribute">android:layout_width</span><span>=</span><span class="attribute-value">"wrap_content"</span><span> </span></li><li><span class="attribute">android:layout_height</span><span>=</span><span class="attribute-value">"wrap_content"</span><span> </span></li><li><span class="attribute">android:id</span><span>=</span><span class="attribute-value">"@+id/ListView01"</span><span> </span></li><li><span class="tag">/&gt;</span><span> </span></li><li><span class="tag">&lt;/</span><span class="tag-name">LinearLayout</span><span class="tag">&gt;</span><span> </span></li></ol></div><pre style="display: none" class="xml" title="Android ListView常用用法" pre_index="0" source_url="http://www.iteye.com/topic/540423#1279134" codeable_id="1279134" codeable_type="Post" name="code">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout 
	android:id="@+id/LinearLayout01" 
	android:layout_width="fill_parent" 
	android:layout_height="fill_parent" 
	xmlns:android="http://schemas.android.com/apk/res/android"&gt;
&lt;ListView android:layout_width="wrap_content" 
          android:layout_height="wrap_content" 
          android:id="@+id/ListView01"
          /&gt;
&lt;/LinearLayout&gt;</pre>
<p>&nbsp;</p>
<p>定义ListView每个条目的Layout，用RelativeLayout实现：</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Xml代码 <a title="复制代码" href="http://www.iteye.com/topic/540423#"><img alt="复制代码" src="http://www.iteye.com/images/icon_copy.gif" /></a> <a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://www.iteye.com/images/icon_star.png" /><img style="display: none" class="spinner" src="http://www.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-xml"><li><span class="tag">&lt;?</span><span class="tag-name">xml</span><span> </span><span class="attribute">version</span><span>=</span><span class="attribute-value">"1.0"</span><span> </span><span class="attribute">encoding</span><span>=</span><span class="attribute-value">"utf-8"</span><span class="tag">?&gt;</span><span> </span></li><li><span class="tag">&lt;</span><span class="tag-name">RelativeLayout</span><span> </span></li><li><span class="attribute">android:id</span><span>=</span><span class="attribute-value">"@+id/RelativeLayout01"</span><span> </span></li><li><span class="attribute">android:layout_width</span><span>=</span><span class="attribute-value">"fill_parent"</span><span> </span></li><li><span class="attribute">xmlns:android</span><span>=</span><span class="attribute-value">"http://schemas.android.com/apk/res/android"</span><span> </span></li><li><span class="attribute">android:layout_height</span><span>=</span><span class="attribute-value">"wrap_content"</span><span> </span></li><li><span class="attribute">android:paddingBottom</span><span>=</span><span class="attribute-value">"4dip"</span><span> </span></li><li><span class="attribute">android:paddingLeft</span><span>=</span><span class="attribute-value">"12dip"</span><span> </span></li><li><span class="attribute">android:paddingRight</span><span>=</span><span class="attribute-value">"12dip"</span><span class="tag">&gt;</span><span> </span></li><li><span class="tag">&lt;</span><span class="tag-name">ImageView</span><span> </span></li><li><span class="attribute">android:paddingTop</span><span>=</span><span class="attribute-value">"12dip"</span><span> </span></li><li><span class="attribute">android:layout_alignParentRight</span><span>=</span><span class="attribute-value">"true"</span><span> </span></li><li><span class="attribute">android:layout_width</span><span>=</span><span class="attribute-value">"wrap_content"</span><span> </span></li><li><span class="attribute">android:layout_height</span><span>=</span><span class="attribute-value">"wrap_content"</span><span> </span></li><li><span class="attribute">android:id</span><span>=</span><span class="attribute-value">"@+id/ItemImage"</span><span> </span></li><li><span class="tag">/&gt;</span><span> </span></li><li><span class="tag">&lt;</span><span class="tag-name">TextView</span><span> </span></li><li><span class="attribute">android:text</span><span>=</span><span class="attribute-value">"TextView01"</span><span> </span></li><li><span class="attribute">android:layout_height</span><span>=</span><span class="attribute-value">"wrap_content"</span><span> </span></li><li><span class="attribute">android:textSize</span><span>=</span><span class="attribute-value">"20dip"</span><span> </span></li><li><span class="attribute">android:layout_width</span><span>=</span><span class="attribute-value">"fill_parent"</span><span> </span></li><li><span class="attribute">android:id</span><span>=</span><span class="attribute-value">"@+id/ItemTitle"</span><span> </span></li><li><span class="tag">/&gt;</span><span> </span></li><li><span class="tag">&lt;</span><span class="tag-name">TextView</span><span> </span></li><li><span class="attribute">android:text</span><span>=</span><span class="attribute-value">"TextView02"</span><span> </span></li><li><span class="attribute">android:layout_height</span><span>=</span><span class="attribute-value">"wrap_content"</span><span> </span></li><li><span class="attribute">android:layout_width</span><span>=</span><span class="attribute-value">"fill_parent"</span><span> </span></li><li><span class="attribute">android:layout_below</span><span>=</span><span class="attribute-value">"@+id/ItemTitle"</span><span> </span></li><li><span class="attribute">android:id</span><span>=</span><span class="attribute-value">"@+id/ItemText"</span><span> </span></li><li><span class="tag">/&gt;</span><span> </span></li><li><span class="tag">&lt;/</span><span class="tag-name">RelativeLayout</span><span class="tag">&gt;</span><span> </span></li></ol></div><pre style="display: none" class="xml" title="Android ListView常用用法" pre_index="1" source_url="http://www.iteye.com/topic/540423#1279134" codeable_id="1279134" codeable_type="Post" name="code">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;RelativeLayout 
	android:id="@+id/RelativeLayout01" 
	android:layout_width="fill_parent" 
	xmlns:android="http://schemas.android.com/apk/res/android" 
	android:layout_height="wrap_content" 
	android:paddingBottom="4dip" 
	android:paddingLeft="12dip"
	android:paddingRight="12dip"&gt;
&lt;ImageView 
	android:paddingTop="12dip"
	android:layout_alignParentRight="true"
	android:layout_width="wrap_content" 
	android:layout_height="wrap_content" 
	android:id="@+id/ItemImage"
	/&gt; 
&lt;TextView 
    android:text="TextView01" 
    android:layout_height="wrap_content" 
    android:textSize="20dip" 
    android:layout_width="fill_parent" 
    android:id="@+id/ItemTitle"
    /&gt;
&lt;TextView 
	android:text="TextView02" 
	android:layout_height="wrap_content" 
	android:layout_width="fill_parent" 
	android:layout_below="@+id/ItemTitle" 
	android:id="@+id/ItemText"
	/&gt;
&lt;/RelativeLayout&gt;</pre>
<p>&nbsp;</p>
<p>最后在Activity里面调用和加入Listener,具体见注释：</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <a title="复制代码" href="http://www.iteye.com/topic/540423#"><img alt="复制代码" src="http://www.iteye.com/images/icon_copy.gif" /></a> <a title="收藏这段代码" href="javascript:void()"><img class="star" alt="收藏代码" src="http://www.iteye.com/images/icon_star.png" /><img style="display: none" class="spinner" src="http://www.iteye.com/images/spinner.gif"  alt="" /></a></div></div>
<ol class="dp-j"><li><span class="keyword">package</span><span> com.ray.test; </span></li><li><span></span></li><li><span class="keyword">import</span><span> java.util.ArrayList; </span></li><li><span class="keyword">import</span><span> java.util.HashMap; </span></li><li><span></span></li><li><span class="keyword">import</span><span> android.app.Activity; </span></li><li><span class="keyword">import</span><span> android.os.Bundle; </span></li><li><span class="keyword">import</span><span> android.view.ContextMenu; </span></li><li><span class="keyword">import</span><span> android.view.MenuItem; </span></li><li><span class="keyword">import</span><span> android.view.View; </span></li><li><span class="keyword">import</span><span> android.view.ContextMenu.ContextMenuInfo; </span></li><li><span class="keyword">import</span><span> android.view.View.OnCreateContextMenuListener; </span></li><li><span class="keyword">import</span><span> android.widget.AdapterView; </span></li><li><span class="keyword">import</span><span> android.widget.ListView; </span></li><li><span class="keyword">import</span><span> android.widget.SimpleAdapter; </span></li><li><span class="keyword">import</span><span> android.widget.AdapterView.OnItemClickListener; </span></li><li><span></span></li><li><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> TestListView </span><span class="keyword">extends</span><span> Activity { </span></li><li><span class="annotation">@Override</span><span> </span></li><li><span class="keyword">public</span><span> </span><span class="keyword">void</span><span> onCreate(Bundle savedInstanceState) { </span></li><li><span class="keyword">super</span><span>.onCreate(savedInstanceState); </span></li><li><span>setContentView(R.layout.main); </span></li><li><span class="comment">//绑定Layout里面的ListView</span><span> </span></li><li><span>ListView list = (ListView) findViewById(R.id.ListView01); </span></li><li><span></span></li><li><span class="comment">//生成动态数组，加入数据</span><span> </span></li><li><span>ArrayList&lt;HashMap&lt;String, Object&gt;&gt; listItem = <span class="keyword">new</span><span> ArrayList&lt;HashMap&lt;String, Object&gt;&gt;(); </span></span></li><li><span class="keyword">for</span><span>(</span><span class="keyword">int</span><span> i=</span><span class="number">0</span><span>;i&lt;</span><span class="number">10</span><span>;i++) </span></li><li><span>{ </span></li><li><span>HashMap&lt;String, Object&gt; map = <span class="keyword">new</span><span> HashMap&lt;String, Object&gt;(); </span></span></li><li><span>map.put(<span class="string">"ItemImage"</span><span>, R.drawable.checked);</span><span class="comment">//图像资源的ID</span><span> </span></span></li><li><span>map.put(<span class="string">"ItemTitle"</span><span>, </span><span class="string">"Level "</span><span>+i); </span></span></li><li><span>map.put(<span class="string">"ItemText"</span><span>, </span><span class="string">"Finished in 1 Min 54 Secs, 70 Moves! "</span><span>); </span></span></li><li><span>listItem.add(map); </span></li><li><span>} </span></li><li><span class="comment">//生成适配器的Item和动态数组对应的元素</span><span> </span></li><li><span>SimpleAdapter listItemAdapter = <span class="keyword">new</span><span> SimpleAdapter(</span><span class="keyword">this</span><span>,listItem,</span><span class="comment">//数据源 </span><span></span></span></li><li><span>R.layout.list_items,<span class="comment">//ListItem的XML实现</span><span> </span></span></li><li><span class="comment">//动态数组与ImageItem对应的子项 </span><span></span></li><li><span class="keyword">new</span><span> String[] {</span><span class="string">"ItemImage"</span><span>,</span><span class="string">"ItemTitle"</span><span>, </span><span class="string">"ItemText"</span><span>}, </span></li><li><span class="comment">//ImageItem的XML文件里面的一个ImageView,两个TextView ID</span><span> </span></li><li><span class="keyword">new</span><span> </span><span class="keyword">int</span><span>[] {R.id.ItemImage,R.id.ItemTitle,R.id.ItemText} </span></li><li><span>); </span></li><li><span></span></li><li><span class="comment">//添加并且显示</span><span> </span></li><li><span>list.setAdapter(listItemAdapter); </span></li><li><span></span></li><li><span class="comment">//添加点击</span><span> </span></li><li><span>list.setOnItemClickListener(<span class="keyword">new</span><span> OnItemClickListener() { </span></span></li><li><span></span></li><li><span class="annotation">@Override</span><span> </span></li><li><span class="keyword">public</span><span> </span><span class="keyword">void</span><span> onItemClick(AdapterView&lt;?&gt; arg0, View arg1, </span><span class="keyword">int</span><span> arg2, </span></li><li><span class="keyword">long</span><span> arg3) { </span></li><li><span>setTitle(<span class="string">"点击第"</span><span>+arg2+</span><span class="string">"个项目"</span><span>); </span></span></li><li><span>} </span></li><li><span>}); </span></li><li><span></span></li><li><span class="comment">//添加长按点击</span><span> </span></li><li><span>list.setOnCreateContextMenuListener(<span class="keyword">new</span><span> OnCreateContextMenuListener() { </span></span></li><li><span></span></li><li><span class="annotation">@Override</span><span> </span></li><li><span class="keyword">public</span><span> </span><span class="keyword">void</span><span> onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) { </span></li><li><span>menu.setHeaderTitle(<span class="string">"长按菜单-ContextMenu"</span><span>); </span></span></li><li><span>menu.add(<span class="number">0</span><span>, </span><span class="number">0</span><span>, </span><span class="number">0</span><span>, </span><span class="string">"弹出长按菜单0"</span><span>); </span></span></li><li><span>menu.add(<span class="number">0</span><span>, </span><span class="number">1</span><span>, </span><span class="number">0</span><span>, </span><span class="string">"弹出长按菜单1"</span><span>); </span></span></li><li><span>} </span></li><li><span>}); </span></li><li><span>} </span></li><li><span></span></li><li><span class="comment">//长按菜单响应函数</span><span> </span></li><li><span class="annotation">@Override</span><span> </span></li><li><span class="keyword">public</span><span> </span><span class="keyword">boolean</span><span> onContextItemSelected(MenuItem item) { </span></li><li><span>setTitle(<span class="string">"点击了长按菜单里面的第"</span><span>+item.getItemId()+</span><span class="string">"个项目"</span><span>); </span></span></li><li><span class="keyword">return</span><span> </span><span class="keyword">super</span><span>.onContextItemSelected(item); </span></li><li><span>} </span></li><li><span>} </span></li></ol></div><pre style="display: none" class="java" title="Android ListView常用用法" pre_index="2" source_url="http://www.iteye.com/topic/540423#1279134" codeable_id="1279134" codeable_type="Post" name="code">package com.ray.test;

import java.util.ArrayList;
import java.util.HashMap;

import android.app.Activity;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.View.OnCreateContextMenuListener;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.AdapterView.OnItemClickListener;

public class TestListView extends Activity {
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //绑定Layout里面的ListView
        ListView list = (ListView) findViewById(R.id.ListView01);
        
        //生成动态数组，加入数据
        ArrayList&lt;HashMap&lt;String, Object&gt;&gt; listItem = new ArrayList&lt;HashMap&lt;String, Object&gt;&gt;();
        for(int i=0;i&lt;10;i++)
        {
        	HashMap&lt;String, Object&gt; map = new HashMap&lt;String, Object&gt;();
        	map.put("ItemImage", R.drawable.checked);//图像资源的ID
        	map.put("ItemTitle", "Level "+i);
        	map.put("ItemText", "Finished in 1 Min 54 Secs, 70 Moves! ");
        	listItem.add(map);
        }
        //生成适配器的Item和动态数组对应的元素
        SimpleAdapter listItemAdapter = new SimpleAdapter(this,listItem,//数据源 
            R.layout.list_items,//ListItem的XML实现
            //动态数组与ImageItem对应的子项        
            new String[] {"ItemImage","ItemTitle", "ItemText"}, 
            //ImageItem的XML文件里面的一个ImageView,两个TextView ID
            new int[] {R.id.ItemImage,R.id.ItemTitle,R.id.ItemText}
        );
       
        //添加并且显示
        list.setAdapter(listItemAdapter);
        
        //添加点击
        list.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView&lt;?&gt; arg0, View arg1, int arg2,
					long arg3) {
				setTitle("点击第"+arg2+"个项目");
			}
		});
        
      //添加长按点击
        list.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
			
			@Override
			public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) {
				menu.setHeaderTitle("长按菜单-ContextMenu");   
				menu.add(0, 0, 0, "弹出长按菜单0");
				menu.add(0, 1, 0, "弹出长按菜单1");   
			}
		}); 
    }
	
	//长按菜单响应函数
	@Override
	public boolean onContextItemSelected(MenuItem item) {
		setTitle("点击了长按菜单里面的第"+item.getItemId()+"个项目"); 
		return super.onContextItemSelected(item);
	}
}</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div class="attachments">
<ul><li><a href="http://dl.iteye.com/topics/download/a18b87bf-9ca0-369f-9af1-cfe7ef5badbd"><u><font color="#0066cc">TestListView02.rar</font></u></a> (40.1 KB)</li><li>下载次数: 9167</li></ul></div><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/87025.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2013-03-04 22:16 <a href="http://www.cnitblog.com/liaoqingshan/archive/2013/03/04/87025.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android实现程序前后台切换效果----转载</title><link>http://www.cnitblog.com/liaoqingshan/archive/2013/03/02/87017.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Sat, 02 Mar 2013 03:21:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2013/03/02/87017.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/87017.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2013/03/02/87017.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/87017.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/87017.html</trackback:ping><description><![CDATA[<div class="clear"><a id="cb_post_title_url" class="postTitle2" href="http://www.cnblogs.com/hanyonglu/archive/2012/04/15/2450551.html"><u><font color="#0066cc"><span style="font-size: 24pt">Android实现程序前后台切换效果</span></font></u></a> <u><font color="#0066cc"></font></u></div>
<div class="postBody">
<div id="cnblogs_post_body">
<p><strong>　　本文演示如何在Android中实现程序前后台切换效果。</strong></p>
<p>&nbsp;</p>
<p>　　在介绍程序实现之前，我们先看下Android中Activities和Task的基础知识。</p>
<p>　　我们都知道，一个Activity 可以启动另一个Activity,即使这个Activity是定义在别一个应用程序里的，比如说，想要给用户展示一个地图的信息，现在已经有一个Activity可以做这件事情，那么现在你的Activity需要做的就是将请求信息放进一个Intent对象里，并且将这个Intent对象传递给startActivity(),那么地图就可显示出来了，但用户按下Back键之后，你的Activity又重新出现在屏幕上。</p>
<p><br />　　对用户来讲，显示地图的Activity和你的Activity好像在一个应用程序中的，虽然是他们是定义在其他的应用程序中并且运行在那个应有进程中。Android将你的Activity和借用的那个Activity被放进一个Task中以维持用户的体验。那么Task是以栈的形式组织起来一组相互关联的Activity,栈中底部的Activity就是开辟这个Task的，通常是用户在应用程序启动器中选择的Activity。栈的顶部的Activity是当前正在运行的Activity--用户正在交互操作的Activity。</p>
<p><br />　　当一个Activity启动另一个Activity时，新启动的Activity被压进栈中，成为正在运行的Activity。旧的Activity仍然在栈中。当用户按下BACK键之后，正在运行的Activity弹出栈，旧的Activity恢复成为运行的Activity。栈中包含对象，因此如果一个任务中开启了同一个Activity子类的的多个对象&#8212;&#8212;例如，多个地图浏览器&#8212;&#8212;则栈对每一个实例都有一个单独的入口。栈中的Activity不会被重新排序，只会被、弹出。Task是一组Activity实例组成的栈，不是在manifest文件里的某个类或是元素，所以无法设定一个Task的属性而不管它的Activity，一个Task的所有属性值是在底部的Activity里设置的，这就需要用于Affinity。关于Affinity这里不再详述，大家可以查询文档。<br /><br /></p>
<p>　　一个Task里的所有Activity作为一个整体运转。整个Task（整个Activity堆栈）可以被推到前台或被推到后台。假设一个正在运行的Task中有四个Activity&#8212;&#8212;正在运行的Activity下面有三个Activity，这时用户按下HOME键，回到应有程序启动器然后运行新的应用程序（实际上是运行了一个新的Task），那么当前的Task就退到了后台，新开启的应用程序的root Activity此时就显示出来了，一段时间后，用户又回到应用程序器，又重新选择了之前的那个应用程序（先前的那个Task），那么先前的那个Task此时又回到了前台了，当用户按下BACK键时，屏幕不是显示刚刚离开的那个新开启的那个应用程序的Activity，而是被除回到前台的那个Task的栈顶Activity，将这个Task的下一个Activity显示出来。 上述便是Activity和Task一般的行为，但是这个行为的几乎所有方面都是可以修改的。Activity和Task的关系，以及Task中Activity的行为，是受启动该Activity的Intent对象的标识和在manifest文件中的Activity的&lt;Activity&gt;元素的属性共同影响的。</p>
<p><br />　　以上是关于Activity和Task的描述。<br /></p>
<p>　　在开发Android项目时，用户难免会进行程序切换，在切换过程中，程序将进入后台运行，需要用时再通过任务管理器或是重新点击程序或是通过点击信息通知栏中的图标返回原来的界面。这种效果类似于腾讯QQ的效果，打开QQ后显示主界面，在使用其他的程序时，QQ将以图标的形式显示在信息通知栏里，如果再用到QQ时再点击信息通知栏中的图标显示QQ主界面。</p>
<p>&nbsp;</p>
<p>　　先看下本示例实现效果图：</p>
<p>&nbsp;</p>
<p><img border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/hanyonglu/2012-04-15_163817.png" width="480" height="800" /> <img border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/hanyonglu/2012-04-15_164123.png" width="480" height="800" /></p>
<p>&nbsp;</p>
<p>　　在上图第二个图中，我们点击时将会返回到的原来的Activity中。 </p>
<p>&nbsp;</p>
<p>　　当我们的程序进入后台运作时，在我们的模拟器顶部将以图标形式出现，如下图：</p>
<p>&nbsp;</p>
<p><span style="white-space: pre" class="Apple-tab-span">　　<img border="0" alt="" src="http://images.cnblogs.com/cnblogs_com/hanyonglu/2012-04-15_170428.png" width="416" height="164" /></span> </p>
<p>&nbsp;</p>
<p>　　对于这种效果一般的做法是在Activity中的onStop()方法中编写相应代码，因为当Activity进入后台时将会调用onStop()方法，我们可以在onStop()方法以Notification形式显示程序图标及信息，其中代码如下所示：</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><pre><span style="color: rgb(0,0,0)">　　@Override
    </span><span style="color: rgb(0,0,255)">protected</span> <span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)"> onStop() {
    </span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> TODO Auto-generated method stub</span>
    　　<span style="color: rgb(0,0,255)">super</span><span style="color: rgb(0,0,0)">.onStop();
    　　Log.v(</span>"BACKGROUND", "程序进入后台"<span style="color: rgb(0,0,0)">);
    　　showNotification();
    }</span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<p>&nbsp;</p>
<p>　　以上的showNotification()方法就是Notification。</p>
<p>　　然后点击信息通知栏的Notification后再返回到原来的Activity。</p>
<p>&nbsp;</p>
<p>　　当然，我们也可以捕捉HOME键，在用户按下HOME键时显示Notification， 以下是代码示例：</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div>
<div><span style="line-height: 19px; font-family: 'Courier New'; font-size: 13px"><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 点击HOME键时程序进入后台运行</span></span><br />@Override<br /><span style="color: rgb(0,0,255)">public</span> <span style="color: rgb(0,0,255)">boolean</span> onKeyDown(<span style="color: rgb(0,0,255)">int</span> keyCode, KeyEvent event) {<br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> TODO Auto-generated method stub<br /></span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 按下HOME键</span><span style="color: rgb(0,128,0)"><br /></span><span style="color: rgb(0,0,255)">if</span>(keyCode == KeyEvent.KEYCODE_HOME){<br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 显示Notification</span><span style="color: rgb(0,128,0)"><br /></span>notification = <span style="color: rgb(0,0,255)">new</span> NotificationExtend(<span style="color: rgb(0,0,255)">this</span>);<br />notification.showNotification();<br />moveTaskToBack(<span style="color: rgb(0,0,255)">true</span>); <br /><br /><span style="color: rgb(0,0,255)">return</span> <span style="color: rgb(0,0,255)">true</span>;<br />}<br /><br /><span style="color: rgb(0,0,255)">return</span> <span style="color: rgb(0,0,255)">super</span>.onKeyDown(keyCode, event);<br />}</div>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<p>&nbsp;</p>
<p>　　这里的NotificationExtend是对显示Notification的一个封装，类中的代码如下：</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div>
<div>
<div><span style="color: rgb(0,0,255)">package</span> com.test.background;<br /><br /></div><span style="color: rgb(0,0,255)">import</span> android.app.Activity;<br /><span style="color: rgb(0,0,255)">import</span> android.app.Notification;<br /><span style="color: rgb(0,0,255)">import</span> android.app.NotificationManager;<br /><span style="color: rgb(0,0,255)">import</span> android.app.PendingIntent;<br /><span style="color: rgb(0,0,255)">import</span> android.content.Intent;<br /><span style="color: rgb(0,0,255)">import</span> android.graphics.Color;<br /><br /><span style="color: rgb(0,128,0)">/**</span><span style="color: rgb(0,128,0)"><br />* Notification扩展类<br />* @Description: Notification扩展类<br /><br />* @File: NotificationExtend.java<br /><br />* @Package com.test.background<br /><br />* @Author Hanyonglu<br /><br />* @Date 2012-4-13 下午02:00:44<br /><br />* @Version V1.0<br /></span><span style="color: rgb(0,128,0)">*/</span><br /><span style="color: rgb(0,0,255)">public</span> <span style="color: rgb(0,0,255)">class</span> NotificationExtend {<br /><span style="color: rgb(0,0,255)">private</span> Activity context;<br /><br /><span style="color: rgb(0,0,255)">public</span> NotificationExtend(Activity context) {<br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> TODO Auto-generated constructor stub</span><span style="color: rgb(0,128,0)"><br /></span><span style="color: rgb(0,0,255)">this</span>.context = context;<br />}<br /><br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 显示Notification</span><span style="color: rgb(0,128,0)"><br /></span><span style="color: rgb(0,0,255)">public</span> <span style="color: rgb(0,0,255)">void</span> showNotification() {<br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 创建一个NotificationManager的引用</span><span style="color: rgb(0,128,0)"><br /></span>NotificationManager notificationManager = (<br />NotificationManager)context.getSystemService(<br />android.content.Context.NOTIFICATION_SERVICE);<br /><br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 定义Notification的各种属性</span><span style="color: rgb(0,128,0)"><br /></span>Notification notification = <span style="color: rgb(0,0,255)">new</span> Notification(<br />R.drawable.icon,"阅读器", <br />System.currentTimeMillis());<br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 将此通知放到通知栏的"Ongoing"即"正在运行"组中</span><span style="color: rgb(0,128,0)"><br /></span>notification.flags |= Notification.FLAG_ONGOING_EVENT;<br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 表明在点击了通知栏中的"清除通知"后，此通知自动清除。</span><span style="color: rgb(0,128,0)"><br /></span>notification.flags |= Notification.FLAG_AUTO_CANCEL<br />notification.flags |= Notification.FLAG_SHOW_LIGHTS;<br />notification.defaults = Notification.DEFAULT_LIGHTS;<br />notification.ledARGB = Color.BLUE;<br />notification.ledOnMS = 5000;<br /><br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 设置通知的事件消息</span><span style="color: rgb(0,128,0)"><br /></span>CharSequence contentTitle = "阅读器显示信息"; <span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 通知栏标题</span><span style="color: rgb(0,128,0)"><br /></span>CharSequence contentText = "推送信息显示，请查看&#8230;&#8230;"; <span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 通知栏内容<br /><br /></span><span style="color: rgb(0,128,0)"></span>Intent notificationIntent = new Intent(context,context.getClass()); 
<div>
<div>notificationIntent.setAction(Intent.ACTION_MAIN);</div>
<div>notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);</div>
<div>PendingIntent contentIntent = PendingIntent.getActivity(</div>
<div>context, 0, notificationIntent,PendingIntent.FLAG_UPDATE_CURRENT);</div>
<div>notification.setLatestEventInfo(</div>
<div>context, contentTitle, contentText, contentIntent);</div>
<div>// 把Notification传递给NotificationManager</div>
<div>notificationManager.notify(0, notification);</div></div>}<br /><br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 取消通知</span><span style="color: rgb(0,128,0)"><br /></span><span style="color: rgb(0,0,255)">public</span> <span style="color: rgb(0,0,255)">void</span> cancelNotification(){<br />NotificationManager notificationManager = (<br />NotificationManager) context.getSystemService(<br />android.content.Context.NOTIFICATION_SERVICE);<br />notificationManager.cancel(0);<br />}<br />}</div>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<p><span style="font-family: 'Courier New'; font-size: small"><br /></span></p>
<p>　　这里需要在配置文件中设置每个Activity以单任务运行，否则，每次返回原Activity时会新增加一个Activity，而不会返回到原Activity。</p>
<p>&nbsp;</p>
<p>　　在使用FLAG_ACTIVITY_NEW_TASK控制标识时也会出现不会返回到原Activity的现象。如果该标识使一个Activity开始了一个新的Task，然后当用户按了HOME键离开这个Activity，在用户按下BACK键时将无法再返回到原Activity。一些应用(例如Notification)总是在一个新的Task里打开Activity，而从来不在自己的Task中打开，所以它们总是将包含FLAG_ACTIVITY_NEW_TASK的Intent传递给startActivity()。所以如果有一个可以被其他的东西以这个控制标志调用的Activity，请注意让应用程序有独立的回到原Activity的方法。 代码如下：</p>
<div class="cnblogs_code">
<div><span style="color: rgb(128,0,0)"></span><span style="color: rgb(0,0,255)">&lt;</span><span style="color: rgb(128,0,0)">activity </span><span style="color: rgb(255,0,0)">android:name</span><span style="color: rgb(0,0,255)">="ShowMessageActivity"</span><br /><span style="color: rgb(255,0,0)">android:launchMode</span><span style="color: rgb(0,0,255)">="singleTask"</span><span style="line-height: 19px; font-family: 'Courier New'; font-size: 13px"><span style="color: rgb(0,0,255)">&gt;&lt;/</span></span><span style="line-height: 19px; font-family: 'Courier New'; font-size: 13px"><span style="color: rgb(128,0,0)">activity</span></span><span style="line-height: 19px; font-family: 'Courier New'; font-size: 13px"><span style="color: rgb(0,0,255)">&gt;</span></span> </div></div>
<p><span style="color: rgb(255,0,0)"></span></p>
<p>　　这里需要注意的是：</p>
<p>　　&lt;activity&gt;下的launchMode属性可以设置四种启动方式： </p>
<ol><li>standard (默认模式) </li><li>singleTop </li><li>singleTask </li><li>singleInstance </li></ol>
<div></div>
<p>　　这四个模式有以下的几个不同点：</p>
<p><strong>　　1. 响应Intent时Activity将被装入哪个task。</strong></p>
<p>　　对于standard和singleTop模式，由产生该Intent(调用startActivity())的task持有该Activity&#8212;&#8212;除非Intent对象里含有FLAG_ACTIVITY_NEW_TASK标志，那么就会寻找一个新的task。 <br /><br />　　相反的，singTask和singleInstance模式，总是标志Activity为task的root Activity，开启这样的活动会新建一个task，而不是装入某个正在运行的任务。 </p>
<p>&nbsp;</p>
<p><strong>　　2. 一个Activity是否可以有多个实例。</strong></p>
<p>　　一个standard或者singleTop属性的Activity可以实例化多次，他们可以属于多个不同的task，而且一个task也可以含有相同Activity的多个实例。 <br /><br /></p>
<div>　　相反的，singleTask或者singleInstance属性的Activity只能有一个实例（单例），因为这些Activity是位于task的底部，这种限制意味着同一设备的同一时刻该task只能有一个实例。</div>
<p>&nbsp;</p>
<p><strong>　　3. 实例是否能允许在它的task里有其他的Activity。</strong> </p>
<div>　　一个singleInstance属性的Activity是它所在的task里仅有的一个Activity，如果他启动了另一个Activity，那个Activity会被加载进一个不同的task而无视它的启动模式&#8212;&#8212;就如Intent里有FLAG_ACTIVITY_NEW_TASK标识一样。在其他的方面，singleInstance和singleTask一样的。 </div>
<p>&nbsp;</p>
<div>　　其他三个模式允许有多个Activity在一个task里，一个singleTask属性的Activity总是一个task里的root Activity，但是他可以启动另外的Activity并且将这个新的Activity装进同一个task里，standard和singleTop属性的Activity可以出现在task的任何位置。 </div>
<p>&nbsp;</p>
<p><strong>　　4. 是否创建一个新的Activity实例来处理一个新的Intent。</strong></p>
<div>　　对于默认的standard方式，将会生成新的实例来处理每一个新的Intent。每个实例处理一个新的Intent。</div>
<p>&nbsp;</p>
<p>　　对singleTop模式，如果一个已经存在的实例在目标task的栈顶，那么就重用这个实例来处理这个新的Intent，如果这个实例存在但是不在栈顶，那就不重用他，而是重新创建一个实例来处理这个新的Intent并且将这个实例压入栈。 <br /><br /></p>
<div>　　例如现在有一个task堆栈ABCD，A是root Activity，D是栈顶Activity，现在有一个启动D的Intent来了，如果D是默认的standard方法，那么就会创建一个新的实例来处理这个Intent，所以这个堆栈就变为ABCDD，然而如果D是singleTop方式，这个已经存在的栈顶的D就会来处理这个Intent，所以堆栈还是ABCD。 </div>
<p>&nbsp;</p>
<p>　　如果另外一种情况，到来的Intent是给B的，不管B是standard还是singleTop（因为现在B不在栈顶），都会创建一个新的实例，所以堆栈变为ABCDB。 <br /><br /></p>
<p>　　如上所述，一个"singleTask"或"singleInstance"模式的activity只会有一个实例，这样它们的实例就会处理所有的新intent。一个"singleInstance" activity总是在栈里的最上面</p>
<div>(因为它是task里的唯一的activity)， 这样它总是可以处理一个intent。而一个"singleTask" activity在栈里可以有或没有其他activity在它上面。如果有的话，它就不能对新到的intent进行处理，intent将被丢弃。(即使intent被丢弃，它的到来将使task来到前台，并维持在那里。) </div>
<p>&nbsp;</p>
<p>　　当一个已有的Activity被请求去处理一个新的Intent时，Intent对象会通过onNewIntent()的调用传递给这个活动。(传递进来的原始的Intent对象可以通过调用getIntent()获取)。 <br /><br /></p>
<div>　　注意，当创建一个新的Activity的实例来处理一个新收到的Intent时，用户可以按BACK键回到上一个状态（上一个Activity）。但是使用一个已有的Activity实例操作新收到的Intent时，用户不能通过按下BACK键回到这个实例在接受到新Intent之前的状态。 </div>
<p>&nbsp;</p>
<p>　　呵呵，不好意思，扯得有点多了，我们继续看我们的程序。</p>
<p>&nbsp;</p>
<p>　　在这里，如果是对一个Activity实现时可以这样实现，如果有多个Activity，我们就需要在每个Activity里重写onKeyDown事件并捕捉用户是否按下HOME键。</p>
<p>　　为了实现方便，我们可以使用一个Service专门用于监听程序是否进入后台或前台工作，如果程序进入后台运行就显示Notification，这样不管程序中有多少个Activity就可以很方便的实现程序前后如切换。 </p>
<p>　　为此，我在程序中新添加了一个AppStatusService 类，目的是监听程序是否在前后台运行，如果在后台运行则显示信息提示。</p>
<p>　　代码如下：</p>
<div class="cnblogs_code">
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div><font face=""><span style="line-height: 21px; font-family: verdana, 'courier new'; color: rgb(0,0,255); font-size: 14px">package</span><span style="line-height: 21px; font-family: verdana, 'courier new'; font-size: 14px"> com.test.service;</span></font> <br /><br /><span style="color: rgb(0,0,255)">import</span> java.util.List;<br /><span style="color: rgb(0,0,255)">import</span> com.test.background.MainActivity;<br /><span style="color: rgb(0,0,255)">import</span> com.test.background.NotificationExtend;<br /><span style="color: rgb(0,0,255)">import</span> com.test.background.R;<br /><span style="color: rgb(0,0,255)">import</span> com.test.util.AppManager;<br /><br /><span style="color: rgb(0,0,255)">import</span> android.app.ActivityManager;<br /><span style="color: rgb(0,0,255)">import</span> android.app.Notification;<br /><span style="color: rgb(0,0,255)">import</span> android.app.NotificationManager;<br /><span style="color: rgb(0,0,255)">import</span> android.app.PendingIntent;<br /><span style="color: rgb(0,0,255)">import</span> android.app.ActivityManager.RunningAppProcessInfo;<br /><span style="color: rgb(0,0,255)">import</span> android.app.Service;<br /><span style="color: rgb(0,0,255)">import</span> android.content.Context;<br /><span style="color: rgb(0,0,255)">import</span> android.content.Intent;<br /><span style="color: rgb(0,0,255)">import</span> android.graphics.Color;<br /><span style="color: rgb(0,0,255)">import</span> android.os.IBinder;<br /><span style="color: rgb(0,0,255)">import</span> android.util.Log;<br /><br /><span style="color: rgb(0,128,0)">/**</span><span style="color: rgb(0,128,0)"><br />* 监听程序是否在前后台运行Service<br />* @Description: 监听程序是否在前后台运行Service<br /><br />* @FileName: AppStatusService.java <br /><br />* @Package com.test.service<br /><br />* @Author Hanyonglu<br /><br />* @Date 2012-4-13 下午04:13:47 <br /><br />* @Version V1.0<br /></span><span style="color: rgb(0,128,0)">*/</span><br /><span style="color: rgb(0,0,255)">public</span> <span style="color: rgb(0,0,255)">class</span> AppStatusService <span style="color: rgb(0,0,255)">extends</span> Service{<br /><span style="color: rgb(0,0,255)">private</span> <span style="color: rgb(0,0,255)">static</span> <span style="color: rgb(0,0,255)">final</span> String TAG = "AppStatusService"; <br /><span style="color: rgb(0,0,255)">private</span> ActivityManager activityManager; <br /><span style="color: rgb(0,0,255)">private</span> String packageName;<br /><span style="color: rgb(0,0,255)">private</span> <span style="color: rgb(0,0,255)">boolean</span> isStop = <span style="color: rgb(0,0,255)">false</span>;<br /><br />@Override<br /><span style="color: rgb(0,0,255)">public</span> IBinder onBind(Intent intent) {<br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> TODO Auto-generated method stub</span><span style="color: rgb(0,128,0)"><br /></span><span style="color: rgb(0,0,255)">return</span> <span style="color: rgb(0,0,255)">null</span>;<br />}<br /><br />@Override<br /><span style="color: rgb(0,0,255)">public</span> <span style="color: rgb(0,0,255)">int</span> onStartCommand(Intent intent, <span style="color: rgb(0,0,255)">int</span> flags, <span style="color: rgb(0,0,255)">int</span> startId) {<br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> TODO Auto-generated method stub</span><span style="color: rgb(0,128,0)"><br /></span>activityManager = (ActivityManager) <span style="color: rgb(0,0,255)">this</span>.getSystemService(Context.ACTIVITY_SERVICE); <br />packageName = <span style="color: rgb(0,0,255)">this</span>.getPackageName(); <br />System.out.println("启动服务");<br /><br /><span style="color: rgb(0,0,255)">new</span> Thread() { <br /><span style="color: rgb(0,0,255)">public</span> <span style="color: rgb(0,0,255)">void</span> run() { <br /><span style="color: rgb(0,0,255)">try</span> { <br /><span style="color: rgb(0,0,255)">while</span> (!isStop) { <br />Thread.sleep(1000); <br /><br /><span style="color: rgb(0,0,255)">if</span> (isAppOnForeground()) { <br />Log.v(TAG, "前台运行");<br />} <span style="color: rgb(0,0,255)">else</span> { <br />Log.v(TAG, "后台运行");<br />showNotification();<br />} <br />} <br />} <span style="color: rgb(0,0,255)">catch</span> (Exception e) { <br />e.printStackTrace(); <br />} <br />} <br />}.start(); <br /><br /><span style="color: rgb(0,0,255)">return</span> <span style="color: rgb(0,0,255)">super</span>.onStartCommand(intent, flags, startId);<br />}<br /><br /><span style="color: rgb(0,128,0)">/**</span><span style="color: rgb(0,128,0)"><br />* 程序是否在前台运行<br />* </span><span style="color: rgb(128,128,128)">@return</span><span style="color: rgb(0,128,0)"><br /></span><span style="color: rgb(0,128,0)">*/</span><br /><span style="color: rgb(0,0,255)">public</span> <span style="color: rgb(0,0,255)">boolean</span> isAppOnForeground() { <br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> Returns a list of application processes that are running on the device </span><span style="color: rgb(0,128,0)"><br /></span>List&lt;RunningAppProcessInfo&gt; appProcesses = activityManager.getRunningAppProcesses(); <br /><span style="color: rgb(0,0,255)">if</span> (appProcesses == <span style="color: rgb(0,0,255)">null</span>) <span style="color: rgb(0,0,255)">return</span> <span style="color: rgb(0,0,255)">false</span>; <br /><br /><span style="color: rgb(0,0,255)">for</span> (RunningAppProcessInfo appProcess : appProcesses) { <br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> The name of the process that this object is associated with. </span><span style="color: rgb(0,128,0)"><br /></span><span style="color: rgb(0,0,255)">if</span> (appProcess.processName.equals(packageName) <br />&amp;&amp; appProcess.importance == RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { <br /><span style="color: rgb(0,0,255)">return</span> <span style="color: rgb(0,0,255)">true</span>; <br />} <br />} <br /><br /><span style="color: rgb(0,0,255)">return</span> <span style="color: rgb(0,0,255)">false</span>; <br />} <br /><br />@Override<br /><span style="color: rgb(0,0,255)">public</span> <span style="color: rgb(0,0,255)">void</span> onDestroy() {<br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> TODO Auto-generated method stub</span><span style="color: rgb(0,128,0)"><br /></span><span style="color: rgb(0,0,255)">super</span>.onDestroy();<br />System.out.println("终止服务");<br />isStop = <span style="color: rgb(0,0,255)">true</span>;<br />}<br /><br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 显示Notification</span><span style="color: rgb(0,128,0)"><br /></span><span style="color: rgb(0,0,255)">public</span> <span style="color: rgb(0,0,255)">void</span> showNotification() {<br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 创建一个NotificationManager的引用</span><span style="color: rgb(0,128,0)"><br /></span>NotificationManager notificationManager = (<br />NotificationManager)getSystemService(<br />android.content.Context.NOTIFICATION_SERVICE);<br /><br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 定义Notification的各种属性</span><span style="color: rgb(0,128,0)"><br /></span>Notification notification = <span style="color: rgb(0,0,255)">new</span> Notification(<br />R.drawable.icon,"阅读器", <br />System.currentTimeMillis());<br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 将此通知放到通知栏的"Ongoing"即"正在运行"组中</span><span style="color: rgb(0,128,0)"><br /></span>notification.flags |= Notification.FLAG_ONGOING_EVENT;<br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 点击后自动清除Notification</span><span style="color: rgb(0,128,0)"><br /></span>notification.flags |= Notification.FLAG_AUTO_CANCEL;<br />notification.flags |= Notification.FLAG_SHOW_LIGHTS;<br />notification.defaults = Notification.DEFAULT_LIGHTS;<br />notification.ledARGB = Color.BLUE;<br />notification.ledOnMS = 5000;<br /><br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 设置通知的事件消息</span><span style="color: rgb(0,128,0)"><br /></span>CharSequence contentTitle = "阅读器显示信息"; <span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 通知栏标题</span><span style="color: rgb(0,128,0)"><br /></span>CharSequence contentText = "推送信息显示，请查看&#8230;&#8230;"; <span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 通知栏内容</span><span style="color: rgb(0,128,0)"><br /></span><br />Intent notificationIntent = <span style="color: rgb(0,0,255)">new</span> Intent(AppManager.context,AppManager.context.getClass());<br />notificationIntent.setAction(Intent.ACTION_MAIN);<br />notificationIntent.addCategory(Intent.CATEGORY_LAUNCHER);<br />PendingIntent contentIntent = PendingIntent.getActivity(<br />AppManager.context, 0, notificationIntent,PendingIntent.FLAG_UPDATE_CURRENT);<br />notification.setLatestEventInfo(<br />AppManager.context, contentTitle, contentText, contentIntent);<br /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)"> 把Notification传递给NotificationManager</span><span style="color: rgb(0,128,0)"><br /></span>notificationManager.notify(0, notification);<br />}<br />} 
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a title="复制代码" href="javascript:void(0);"><img alt="复制代码" src="http://common.cnblogs.com/images/copycode.gif" /></a></span></div></div>
<p>&nbsp;</p>
<p>　　在这里为了在信息提示栏里点击后能够返回到原来的Activity，需要在AppManager里记下我们当前的Activity。</p>
<p>&nbsp;</p>
<p>　　最后，希望转载的朋友能够尊重作者的劳动成果，加上转载地址：<a href="http://www.cnblogs.com/hanyonglu/archive/2012/04/15/2450551.html"><u><font color="#0066cc">http://www.cnblogs.com/hanyonglu/archive/2012/04/15/2450551.html</font></u></a> 谢谢。 </p>
<p>&nbsp;</p>
<p>　　示例下载：<a href="http://files.cnblogs.com/hanyonglu/AndroidFile/MyAppExchange.rar"><u><font color="#0066cc">点击下载</font></u></a> </p>
<p>&nbsp;</p>
<p>　　完毕。^_^ </p>
<p>&nbsp;</p></div></div><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/87017.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2013-03-02 11:21 <a href="http://www.cnitblog.com/liaoqingshan/archive/2013/03/02/87017.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>状态栏通知Notification、NotificationManager详解（源码）----转载</title><link>http://www.cnitblog.com/liaoqingshan/archive/2013/02/26/87011.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Tue, 26 Feb 2013 12:21:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2013/02/26/87011.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/87011.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2013/02/26/87011.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/87011.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/87011.html</trackback:ping><description><![CDATA[<u>
<p style="margin: 10px 0px 0px 3px; color: rgb(170,0,0); font-weight: bold">&nbsp;</p>
<div class="Content">
<div class="detail">
<p>在Android系统中，发一个状态栏通知还是很方便的。下面我们就来看一下，怎么发送状态栏通知，状态栏通知又有哪些参数可以设置？</p>
<p>&nbsp;</p>
<p>首先，发送一个状态栏通知必须用到两个类： NotificationManager 、 Notification。</p>
<p>&nbsp;</p>
<p>NotificationManager ： 是状态栏通知的管理类，负责发通知、清楚通知等。</p>
<p>NotificationManager 是一个系统Service，必须通过 <code>getSystemService()方法来获取。</code></p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools"><a href="http://www.oschina.net/question/234345_40111#">源码</a><a href="http://www.oschina.net/question/234345_40111#">copy to clipboard</a><a href="http://www.oschina.net/question/234345_40111#">打印</a><a href="http://www.oschina.net/question/234345_40111#">？</a></div></div>
<ol class="dp-j"><li class="alt"><span>NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); </span></li></ol></div><pre style="display: none" class="java" rows="15" cols="50" name="code">NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>Notification：是具体的状态栏通知对象，可以设置icon、文字、提示声音、振动等等参数。</p>
<p>&nbsp;</p>
<p>下面是设置一个通知需要的基本参数：</p>
<p>&nbsp;</p>
<ul><li>An icon (通知的图标)</li><li>A title and expanded message (通知的标题和内容)</li><li>A <code>PendingIntent (点击通知执行页面跳转)</code></li></ul>
<p>&nbsp;</p>
<p>可选的设置：</p>
<p>&nbsp;</p>
<ul><li>A ticker-text message (状态栏顶部提示消息)</li><li>An alert sound (提示音)</li><li>A vibrate setting (振动)</li><li>A flashing LED setting (灯光)</li><li>等等</li></ul>
<p>&nbsp;</p>
<p>一、创建Notification</p>
<p><span style="white-space: pre"></span>通过NotificationManager 的 <span style="font-family: mceinline">notify(int, Notification) 方法来启动Notification。</span></p>
<p><span style="font-family: mceinline"><span style="white-space: pre"></span>第一个参数唯一的标识该Notification，第二个参数就是Notification对象。</span></p>
<p>二、更新Notification</p>
<p><span style="white-space: pre">调用Notification的 setLatestEventInfo方法来更新内容，然后再调用NotificationManager的notify()方法即可。(具体可以看下面的实例)</span></p>
<p>&nbsp;</p>
<p>三、删除Notification</p>
<p><span style="white-space: pre"></span>通过NotificationManager 的<code>cancel(int)方法，来清除某个通知。其中参数就是</code>Notification的唯一标识ID。</p>
<p><span style="white-space: pre"></span>当然也可以通过 <code>cancelAll() 来清除状态栏所有的通知。</code></p>
<p>&nbsp;</p>
<p>四、Notification设置(振动、铃声等)</p>
<p>&nbsp;</p>
<p><span style="white-space: pre">1. <span style="white-space: normal">基本设置：</span></span> </p>
<p><span style="white-space: pre"><span style="white-space: pre"></span><span style="font-family: monospace; font-size: x-small"><span style="white-space: pre-wrap"></span></span></span></p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools"><a href="http://www.oschina.net/question/234345_40111#">源码</a><a href="http://www.oschina.net/question/234345_40111#">copy to clipboard</a><a href="http://www.oschina.net/question/234345_40111#">打印</a><a href="http://www.oschina.net/question/234345_40111#">？</a></div></div>
<ol class="dp-j"><li class="alt"><span class="comment">//新建状态栏通知</span><span> </span></li><li><span>baseNF = <span class="keyword">new</span><span> Notification(); </span></span></li><li class="alt"><span></span></li><li><span class="comment">//设置通知在状态栏显示的图标</span><span> </span></li><li class="alt"><span>baseNF.icon = R.drawable.icon; </span></li><li><span></span></li><li class="alt"><span class="comment">//通知时在状态栏显示的内容</span><span> </span></li><li><span>baseNF.tickerText = <span class="string">"You clicked BaseNF!"</span><span>; </span></span></li><li class="alt"><span></span></li><li><span class="comment">//通知的默认参数 DEFAULT_SOUND, DEFAULT_VIBRATE, DEFAULT_LIGHTS. </span><span></span></li><li class="alt"><span class="comment">//如果要全部采用默认值, 用 DEFAULT_ALL.</span><span> </span></li><li><span class="comment">//此处采用默认声音</span><span> </span></li><li class="alt"><span>baseNF.defaults = Notification.DEFAULT_SOUND; </span></li><li><span></span></li><li class="alt"><span class="comment">//第二个参数 ：下拉状态栏时显示的消息标题 expanded message title</span><span> </span></li><li><span class="comment">//第三个参数：下拉状态栏时显示的消息内容 expanded message text</span><span> </span></li><li class="alt"><span class="comment">//第四个参数：点击该通知时执行页面跳转</span><span> </span></li><li><span>baseNF.setLatestEventInfo(Lesson_10.<span class="keyword">this</span><span>, </span><span class="string">"Title01"</span><span>, </span><span class="string">"Content01"</span><span>, pd); </span></span></li><li class="alt"><span></span></li><li><span class="comment">//发出状态栏通知</span><span> </span></li><li class="alt"><span class="comment">//The first parameter is the unique ID for the Notification </span><span></span></li><li><span class="comment">// and the second is the Notification object.</span><span> </span></li><li class="alt"><span>nm.notify(Notification_ID_BASE, baseNF); </span></li></ol></div><pre style="display: none" class="java" rows="15" cols="50" name="code">					//新建状态栏通知
					baseNF = new Notification();
					 
					//设置通知在状态栏显示的图标
					baseNF.icon = R.drawable.icon;
					
					//通知时在状态栏显示的内容
					baseNF.tickerText = "You clicked BaseNF!";
					
					//通知的默认参数 DEFAULT_SOUND, DEFAULT_VIBRATE, DEFAULT_LIGHTS. 
					//如果要全部采用默认值, 用 DEFAULT_ALL.
					//此处采用默认声音
					baseNF.defaults = Notification.DEFAULT_SOUND;
					
					//第二个参数 ：下拉状态栏时显示的消息标题 expanded message title
					//第三个参数：下拉状态栏时显示的消息内容 expanded message text
					//第四个参数：点击该通知时执行页面跳转
					baseNF.setLatestEventInfo(Lesson_10.this, "Title01", "Content01", pd);
					
					//发出状态栏通知
					//The first parameter is the unique ID for the Notification 
					// and the second is the Notification object.
					nm.notify(Notification_ID_BASE, baseNF);</pre>
<p>&nbsp;</p>
<p><span style="white-space: pre"><span style="white-space: normal"><span style="white-space: pre"></span>配一张图作说明:</span></span></p>
<p><span style="white-space: pre"><span style="white-space: normal"><span style="white-space: pre"></span></span></span></p>
<p><span style="white-space: pre"><a href="http://static.oschina.net/uploads/img/201203/01195914_DeAS.gif" target="_blank"><img style="cursor: pointer" alt="" src="http://static.oschina.net/uploads/img/201203/01195914_DeAS.gif" /></a></span></p>
<p>&nbsp;</p>
<p>2. 添加声音</p>
<p><span style="white-space: pre"></span>如果要采用默认声音，只要使用default就可以了。</p>
<p><span style="white-space: pre"></span></p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools"><a href="http://www.oschina.net/question/234345_40111#">源码</a><a href="http://www.oschina.net/question/234345_40111#">copy to clipboard</a><a href="http://www.oschina.net/question/234345_40111#">打印</a><a href="http://www.oschina.net/question/234345_40111#">？</a></div></div>
<ol class="dp-j"><li class="alt"><span>baseNF.defaults = Notification.DEFAULT_SOUND; </span></li></ol></div><pre style="display: none" class="java" rows="15" cols="50" name="code">baseNF.defaults = Notification.DEFAULT_SOUND;</pre>
<p>&nbsp;</p>
<p><span style="white-space: pre"></span>如果要使用自定义声音，那么就要用到sound了。如下：</p>
<p><span style="white-space: pre"></span></p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools"><a href="http://www.oschina.net/question/234345_40111#">源码</a><a href="http://www.oschina.net/question/234345_40111#">copy to clipboard</a><a href="http://www.oschina.net/question/234345_40111#">打印</a><a href="http://www.oschina.net/question/234345_40111#">？</a></div></div>
<ol class="dp-j"><li class="alt"><span>notification.sound = Uri.parse(</span><span class="string">"file:///sdcard/notification/ringer.mp3"</span><span>); </span></li></ol></div><pre style="display: none" class="java" rows="15" cols="50" name="code">notification.sound = Uri.parse("file:///sdcard/notification/ringer.mp3");</pre>
<p>&nbsp;</p>
<p><span style="white-space: pre"></span>上面这种方法，使用的是自己的铃声，如果想用系统自带的铃声，可以这样：</p>
<p><span style="white-space: pre"></span></p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools"><a href="http://www.oschina.net/question/234345_40111#">源码</a><a href="http://www.oschina.net/question/234345_40111#">copy to clipboard</a><a href="http://www.oschina.net/question/234345_40111#">打印</a><a href="http://www.oschina.net/question/234345_40111#">？</a></div></div>
<ol class="dp-j"><li class="alt"><span>notification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, </span><span class="string">"6"</span><span>); </span></li></ol></div><pre style="display: none" class="java" rows="15" cols="50" name="code">notification.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6");</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="white-space: pre"><span style="white-space: pre"></span><span style="white-space: normal">需要注意一点，如果default、sound同时出现，那么sound无效，会使用默认铃声。</span></span></p>
<p>&nbsp;</p>
<p><span style="white-space: pre"><span style="white-space: pre"><span style="white-space: pre"></span><span style="white-space: normal">默认情况下，通知的声音播放一遍就会结束。 如果你想让声音循环播放，需要为flags参数加上</span></span></span>FLAG_INSISTENT。 这样声音会到用户响应才结束，比如下拉状态栏。</p>
<p><span style="white-space: pre"></span></p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools"><a href="http://www.oschina.net/question/234345_40111#">源码</a><a href="http://www.oschina.net/question/234345_40111#">copy to clipboard</a><a href="http://www.oschina.net/question/234345_40111#">打印</a><a href="http://www.oschina.net/question/234345_40111#">？</a></div></div>
<ol class="dp-j"><li class="alt"><span>notification.flags |= notification.FLAG_INSISTENT; </span></li></ol></div><pre style="display: none" class="java" rows="15" cols="50" name="code">notification.flags |= notification.FLAG_INSISTENT;</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="white-space: pre"><span style="white-space: normal">3. 添加振动</span></span></p>
<p><span style="white-space: pre"><span style="white-space: normal"><span style="white-space: pre"></span>如果是使用默认的振动方式，那么同样也是使用default。</span></span></p>
<p><span style="white-space: pre"><span style="white-space: normal"><span style="white-space: pre"></span></span></span></p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools"><a href="http://www.oschina.net/question/234345_40111#">源码</a><a href="http://www.oschina.net/question/234345_40111#">copy to clipboard</a><a href="http://www.oschina.net/question/234345_40111#">打印</a><a href="http://www.oschina.net/question/234345_40111#">？</a></div></div>
<ol class="dp-j"><li class="alt"><span>notification.defaults |= Notification.DEFAULT_VIBRATE; </span></li></ol></div><pre style="display: none" class="java" rows="15" cols="50" name="code">notification.defaults |= Notification.DEFAULT_VIBRATE;</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="white-space: pre"><span style="white-space: pre"><span style="white-space: pre"></span><span style="white-space: normal">当然也可以自己定义振动形式，这边需要用到Long型数组。 </span></span></span></p>
<p><span style="white-space: pre"><span style="white-space: pre"><span style="white-space: normal"><span style="white-space: pre"></span></span></span></span></p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools"><a href="http://www.oschina.net/question/234345_40111#">源码</a><a href="http://www.oschina.net/question/234345_40111#">copy to clipboard</a><a href="http://www.oschina.net/question/234345_40111#">打印</a><a href="http://www.oschina.net/question/234345_40111#">？</a></div></div>
<ol class="dp-j"><li class="alt"><span class="keyword">long</span><span>[] vibrate = {</span><span class="number">0</span><span>,</span><span class="number">100</span><span>,</span><span class="number">200</span><span>,</span><span class="number">300</span><span>}; </span></li><li><span>notification.vibrate = vibrate; </span></li></ol></div><pre style="display: none" class="java" rows="15" cols="50" name="code">long[] vibrate = {0,100,200,300};
notification.vibrate = vibrate;</pre>
<p>&nbsp;</p>
<p><span style="white-space: pre"><span style="white-space: pre"><span style="white-space: normal"><span style="white-space: pre"></span>这边的Long型数组中，第一个参数是开始振动前等待的时间，第二个参数是第一次振动的时间，第三个参数是第二次振动的时间，以此类推，随便定义多长的数组。但是采用这种方法，没有办法做到重复振动。</span></span></span></p>
<p>&nbsp;</p>
<p><span style="white-space: pre"><span style="white-space: pre"></span><span style="white-space: normal">同样，如果default、vibrate同时出现时，会采用默认形式。</span></span></p>
<p>&nbsp;</p>
<p><span style="white-space: pre"><span style="white-space: pre"><span style="white-space: normal"><span style="white-space: pre"></span>另外还需要注意一点：使用振动器时需要权限，如下：</span></span></span></p>
<p><span style="white-space: pre"><span style="white-space: pre"><span style="white-space: normal"><span style="white-space: pre"></span></span></span></span></p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools"><a href="http://www.oschina.net/question/234345_40111#">源码</a><a href="http://www.oschina.net/question/234345_40111#">copy to clipboard</a><a href="http://www.oschina.net/question/234345_40111#">打印</a><a href="http://www.oschina.net/question/234345_40111#">？</a></div></div>
<ol class="dp-xml"><li class="alt"><span class="tag">&lt;</span><span class="tag-name">uses-permission</span><span> </span><span class="attribute">android:name</span><span>=</span><span class="attribute-value">"android.permission.VIBRATE"</span><span class="tag">&gt;</span><span class="tag">&lt;/</span><span class="tag-name">uses-permission</span><span class="tag">&gt;</span><span> </span></li></ol></div><pre style="display: none" class="xhtml" rows="15" cols="50" name="code"> &lt;uses-permission android:name="android.permission.VIBRATE"&gt;&lt;/uses-permission&gt;</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="white-space: pre"><span style="white-space: pre"><span style="white-space: normal">4. 闪光</span></span></span></p>
<p>&nbsp;</p>
<p><span style="white-space: pre"></span>使用默认的灯光，如下：</p>
<p><span style="white-space: pre"><span style="white-space: pre"><span style="white-space: normal"><span style="white-space: pre"><span style="white-space: pre"></span></span></span></span></span></p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools"><a href="http://www.oschina.net/question/234345_40111#">源码</a><a href="http://www.oschina.net/question/234345_40111#">copy to clipboard</a><a href="http://www.oschina.net/question/234345_40111#">打印</a><a href="http://www.oschina.net/question/234345_40111#">？</a></div></div>
<ol class="dp-j"><li class="alt"><span>notification.defaults |= Notification.DEFAULT_LIGHTS; </span></li></ol></div><pre style="display: none" class="java" rows="15" cols="50" name="code">notification.defaults |= Notification.DEFAULT_LIGHTS;</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="white-space: pre"><span style="white-space: pre"><span style="white-space: normal"><span style="white-space: pre"><span style="white-space: pre"><span style="white-space: pre"></span>自定义</span>：</span></span></span></span></p>
<p><span style="white-space: pre"><span style="white-space: pre"><span style="white-space: normal"><span style="white-space: pre"><span style="white-space: pre"></span><span style="font-family: monospace; font-size: x-small"><span style="white-space: pre-wrap"></span></span></span></span></span></span></p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools"><a href="http://www.oschina.net/question/234345_40111#">源码</a><a href="http://www.oschina.net/question/234345_40111#">copy to clipboard</a><a href="http://www.oschina.net/question/234345_40111#">打印</a><a href="http://www.oschina.net/question/234345_40111#">？</a></div></div>
<ol class="dp-j"><li class="alt"><span>notification.ledARGB = </span><span class="number">0xff00ff00</span><span>; </span></li><li><span>notification.ledOnMS = <span class="number">300</span><span>; </span></span></li><li class="alt"><span>notification.ledOffMS = <span class="number">1000</span><span>; </span></span></li><li><span>notification.flags |= Notification.FLAG_SHOW_LIGHTS; </span></li></ol></div><pre style="display: none" class="java" rows="15" cols="50" name="code">notification.ledARGB = 0xff00ff00;
notification.ledOnMS = 300;
notification.ledOffMS = 1000;
notification.flags |= Notification.FLAG_SHOW_LIGHTS;</pre>
<p>&nbsp;</p>
<p><span style="white-space: pre"><span style="white-space: pre"><span style="white-space: normal"><span style="white-space: pre"><span style="white-space: pre"></span>其中</span></span></span></span>ledARGB 表示灯光颜色、 ledOnMS 亮持续时间、ledOffMS 暗的时间。</p>
<p><span style="white-space: pre"></span>注意：这边的颜色跟设备有关，不是所有的颜色都可以，要看具体设备。</p>
<p>&nbsp;</p>
<p>5. 其他有用的设置：</p>
<p><span style="white-space: pre">flags</span>：</p>
<p><span style="white-space: pre">Notification.FLAG_INSISTENT;</span> <span style="white-space: pre"></span>//让声音、振动无限循环，直到用户响应</p>
<p><span style="white-space: pre">Notification.FLAG_AUTO_CANCEL;</span> <span style="white-space: pre"></span><span style="white-space: pre">//通知被点击后，自动消失</span></p>
<p><span style="white-space: pre">Notification.FLAG_NO_CLEAR; </span><span style="white-space: pre">//点击'Clear'时，不清楚该通知(QQ的通知无法清除，就是用的这个)</span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<hr />

<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="white-space: pre">下面附上我做的例子，供大家参考。 里面包括创建通知、更新通知、清除通知、设置自定义铃声、自定义振动、自定义通知视图等。</span></p>
<p><a href="http://static.oschina.net/uploads/img/201203/01195915_ewnD.gif" target="_blank"><img style="cursor: pointer" alt="" src="http://static.oschina.net/uploads/img/201203/01195915_ewnD.gif" /></a> <a href="http://static.oschina.net/uploads/img/201203/01195915_mSC9.gif" target="_blank"><img style="cursor: pointer" alt="" src="http://static.oschina.net/uploads/img/201203/01195915_mSC9.gif" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>附上代码：</p>
<p>&nbsp;</p>
<p>主类：</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools"><a href="http://www.oschina.net/question/234345_40111#">源码</a><a href="http://www.oschina.net/question/234345_40111#">copy to clipboard</a><a href="http://www.oschina.net/question/234345_40111#">打印</a><a href="http://www.oschina.net/question/234345_40111#">？</a></div></div>
<ol class="dp-j"><li class="alt"><span class="keyword">package</span><span> com.yfz; </span></li><li><span class="keyword">import</span><span> android.app.Activity; </span></li><li class="alt"><span class="keyword">import</span><span> android.app.Notification; </span></li><li><span class="keyword">import</span><span> android.app.NotificationManager; </span></li><li class="alt"><span class="keyword">import</span><span> android.app.PendingIntent; </span></li><li><span class="keyword">import</span><span> android.content.Intent; </span></li><li class="alt"><span class="keyword">import</span><span> android.net.Uri; </span></li><li><span class="keyword">import</span><span> android.os.Bundle; </span></li><li class="alt"><span class="keyword">import</span><span> android.provider.MediaStore.Audio; </span></li><li><span class="keyword">import</span><span> android.util.Log; </span></li><li class="alt"><span class="keyword">import</span><span> android.view.View; </span></li><li><span class="keyword">import</span><span> android.view.View.OnClickListener; </span></li><li class="alt"><span class="keyword">import</span><span> android.widget.Button; </span></li><li><span class="keyword">import</span><span> android.widget.RemoteViews; </span></li><li class="alt"><span class="keyword">import</span><span> android.widget.SeekBar; </span></li><li><span class="keyword">import</span><span> android.widget.TextView; </span></li><li class="alt"><span class="comment">/**</span> </li><li><span class="comment">* Notification</span> </li><li class="alt"><span class="comment">* @author Administrator</span> </li><li><span class="comment">*</span> </li><li class="alt"><span class="comment">*/</span><span> </span></li><li><span class="keyword">public</span><span> </span><span class="keyword">class</span><span> Lesson_10 </span><span class="keyword">extends</span><span> Activity { </span></li><li class="alt"><span></span></li><li><span class="comment">//BaseNotification</span><span> </span></li><li class="alt"><span class="keyword">private</span><span> Button bt01; </span></li><li><span></span></li><li class="alt"><span class="comment">//UpdateBaseNotification</span><span> </span></li><li><span class="keyword">private</span><span> Button bt02; </span></li><li class="alt"><span></span></li><li><span class="comment">//ClearBaseNotification</span><span> </span></li><li class="alt"><span class="keyword">private</span><span> Button bt03; </span></li><li><span></span></li><li class="alt"><span class="comment">//MediaNotification</span><span> </span></li><li><span class="keyword">private</span><span> Button bt04; </span></li><li class="alt"><span></span></li><li><span class="comment">//ClearMediaNotification</span><span> </span></li><li class="alt"><span class="keyword">private</span><span> Button bt05; </span></li><li><span></span></li><li class="alt"><span class="comment">//ClearALL</span><span> </span></li><li><span class="keyword">private</span><span> Button bt06; </span></li><li class="alt"><span></span></li><li><span class="comment">//CustomNotification</span><span> </span></li><li class="alt"><span class="keyword">private</span><span> Button bt07; </span></li><li><span></span></li><li class="alt"><span class="comment">//通知管理器</span><span> </span></li><li><span class="keyword">private</span><span> NotificationManager nm; </span></li><li class="alt"><span></span></li><li><span class="comment">//通知显示内容</span><span> </span></li><li class="alt"><span class="keyword">private</span><span> PendingIntent pd; </span></li><li><span></span></li><li class="alt"><span class="annotation">@Override</span><span> </span></li><li><span class="keyword">public</span><span> </span><span class="keyword">void</span><span> onCreate(Bundle savedInstanceState) { </span></li><li class="alt"><span class="keyword">super</span><span>.onCreate(savedInstanceState); </span></li><li><span class="comment">/*加载页面*/</span><span> </span></li><li class="alt"><span>setContentView(R.layout.lesson10); </span></li><li><span></span></li><li class="alt"><span>init(); </span></li><li><span>} </span></li><li class="alt"><span></span></li><li><span class="keyword">private</span><span> </span><span class="keyword">void</span><span> init() { </span></li><li class="alt"><span>bt01 = (Button)findViewById(R.id.le10bt01); </span></li><li><span>bt02 = (Button)findViewById(R.id.le10bt02); </span></li><li class="alt"><span>bt03 = (Button)findViewById(R.id.le10bt03); </span></li><li><span>bt04 = (Button)findViewById(R.id.le10bt04); </span></li><li class="alt"><span>bt05 = (Button)findViewById(R.id.le10bt05); </span></li><li><span>bt06 = (Button)findViewById(R.id.le10bt06); </span></li><li class="alt"><span>bt07 = (Button)findViewById(R.id.le10bt07); </span></li><li><span></span></li><li class="alt"><span>bt01.setOnClickListener(onclick); </span></li><li><span>bt02.setOnClickListener(onclick); </span></li><li class="alt"><span>bt03.setOnClickListener(onclick); </span></li><li><span>bt04.setOnClickListener(onclick); </span></li><li class="alt"><span>bt05.setOnClickListener(onclick); </span></li><li><span>bt06.setOnClickListener(onclick); </span></li><li class="alt"><span>bt07.setOnClickListener(onclick); </span></li><li><span></span></li><li class="alt"><span>nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); </span></li><li><span></span></li><li class="alt"><span>Intent intent = <span class="keyword">new</span><span> Intent(</span><span class="keyword">this</span><span>,Lesson_10.</span><span class="keyword">class</span><span>); </span></span></li><li><span></span></li><li class="alt"><span>pd = PendingIntent.getActivity(Lesson_10.<span class="keyword">this</span><span>, </span><span class="number">0</span><span>, intent, </span><span class="number">0</span><span>); </span></span></li><li><span>} </span></li><li class="alt"><span></span></li><li><span>OnClickListener onclick = <span class="keyword">new</span><span> OnClickListener() { </span></span></li><li class="alt"><span></span></li><li><span class="comment">//BASE Notification ID</span><span> </span></li><li class="alt"><span class="keyword">private</span><span> </span><span class="keyword">int</span><span> Notification_ID_BASE = </span><span class="number">110</span><span>; </span></li><li><span></span></li><li class="alt"><span class="keyword">private</span><span> Notification baseNF; </span></li><li><span></span></li><li class="alt"><span class="comment">//Notification ID</span><span> </span></li><li><span class="keyword">private</span><span> </span><span class="keyword">int</span><span> Notification_ID_MEDIA = </span><span class="number">119</span><span>; </span></li><li class="alt"><span></span></li><li><span class="keyword">private</span><span> Notification mediaNF; </span></li><li class="alt"><span></span></li><li><span class="annotation">@Override</span><span> </span></li><li class="alt"><span class="keyword">public</span><span> </span><span class="keyword">void</span><span> onClick(View v) { </span></li><li><span class="keyword">switch</span><span>(v.getId()) { </span></li><li class="alt"><span class="keyword">case</span><span> R.id.le10bt01: </span></li><li><span class="comment">//新建状态栏通知</span><span> </span></li><li class="alt"><span>baseNF = <span class="keyword">new</span><span> Notification(); </span></span></li><li><span></span></li><li class="alt"><span class="comment">//设置通知在状态栏显示的图标</span><span> </span></li><li><span>baseNF.icon = R.drawable.icon; </span></li><li class="alt"><span></span></li><li><span class="comment">//通知时在状态栏显示的内容</span><span> </span></li><li class="alt"><span>baseNF.tickerText = <span class="string">"You clicked BaseNF!"</span><span>; </span></span></li><li><span></span></li><li class="alt"><span class="comment">//通知的默认参数 DEFAULT_SOUND, DEFAULT_VIBRATE, DEFAULT_LIGHTS. </span><span></span></li><li><span class="comment">//如果要全部采用默认值, 用 DEFAULT_ALL.</span><span> </span></li><li class="alt"><span class="comment">//此处采用默认声音</span><span> </span></li><li><span>baseNF.defaults |= Notification.DEFAULT_SOUND; </span></li><li class="alt"><span>baseNF.defaults |= Notification.DEFAULT_VIBRATE; </span></li><li><span>baseNF.defaults |= Notification.DEFAULT_LIGHTS; </span></li><li class="alt"><span></span></li><li><span class="comment">//让声音、振动无限循环，直到用户响应</span><span> </span></li><li class="alt"><span>baseNF.flags |= Notification.FLAG_INSISTENT; </span></li><li><span></span></li><li class="alt"><span class="comment">//通知被点击后，自动消失</span><span> </span></li><li><span>baseNF.flags |= Notification.FLAG_AUTO_CANCEL; </span></li><li class="alt"><span></span></li><li><span class="comment">//点击'Clear'时，不清楚该通知(QQ的通知无法清除，就是用的这个)</span><span> </span></li><li class="alt"><span>baseNF.flags |= Notification.FLAG_NO_CLEAR; </span></li><li><span></span></li><li class="alt"><span></span></li><li><span class="comment">//第二个参数 ：下拉状态栏时显示的消息标题 expanded message title</span><span> </span></li><li class="alt"><span class="comment">//第三个参数：下拉状态栏时显示的消息内容 expanded message text</span><span> </span></li><li><span class="comment">//第四个参数：点击该通知时执行页面跳转</span><span> </span></li><li class="alt"><span>baseNF.setLatestEventInfo(Lesson_10.<span class="keyword">this</span><span>, </span><span class="string">"Title01"</span><span>, </span><span class="string">"Content01"</span><span>, pd); </span></span></li><li><span></span></li><li class="alt"><span class="comment">//发出状态栏通知</span><span> </span></li><li><span class="comment">//The first parameter is the unique ID for the Notification </span><span></span></li><li class="alt"><span class="comment">// and the second is the Notification object.</span><span> </span></li><li><span>nm.notify(Notification_ID_BASE, baseNF); </span></li><li class="alt"><span></span></li><li><span class="keyword">break</span><span>; </span></li><li class="alt"><span></span></li><li><span class="keyword">case</span><span> R.id.le10bt02: </span></li><li class="alt"><span class="comment">//更新通知</span><span> </span></li><li><span class="comment">//比如状态栏提示有一条新短信，还没来得及查看，又来一条新短信的提示。</span><span> </span></li><li class="alt"><span class="comment">//此时采用更新原来通知的方式比较。</span><span> </span></li><li><span class="comment">//(再重新发一个通知也可以，但是这样会造成通知的混乱，而且显示多个通知给用户，对用户也不友好)</span><span> </span></li><li class="alt"><span>baseNF.setLatestEventInfo(Lesson_10.<span class="keyword">this</span><span>, </span><span class="string">"Title02"</span><span>, </span><span class="string">"Content02"</span><span>, pd); </span></span></li><li><span>nm.notify(Notification_ID_BASE, baseNF); </span></li><li class="alt"><span class="keyword">break</span><span>; </span></li><li><span></span></li><li class="alt"><span class="keyword">case</span><span> R.id.le10bt03: </span></li><li><span></span></li><li class="alt"><span class="comment">//清除 baseNF</span><span> </span></li><li><span>nm.cancel(Notification_ID_BASE); </span></li><li class="alt"><span class="keyword">break</span><span>; </span></li><li><span></span></li><li class="alt"><span class="keyword">case</span><span> R.id.le10bt04: </span></li><li><span>mediaNF = <span class="keyword">new</span><span> Notification(); </span></span></li><li class="alt"><span>mediaNF.icon = R.drawable.icon; </span></li><li><span>mediaNF.tickerText = <span class="string">"You clicked MediaNF!"</span><span>; </span></span></li><li class="alt"><span></span></li><li><span class="comment">//自定义声音</span><span> </span></li><li class="alt"><span>mediaNF.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, <span class="string">"6"</span><span>); </span></span></li><li><span></span></li><li class="alt"><span class="comment">//通知时发出的振动</span><span> </span></li><li><span class="comment">//第一个参数: 振动前等待的时间</span><span> </span></li><li class="alt"><span class="comment">//第二个参数： 第一次振动的时长、以此类推</span><span> </span></li><li><span class="keyword">long</span><span>[] vir = {</span><span class="number">0</span><span>,</span><span class="number">100</span><span>,</span><span class="number">200</span><span>,</span><span class="number">300</span><span>}; </span></li><li class="alt"><span>mediaNF.vibrate = vir; </span></li><li><span></span></li><li class="alt"><span>mediaNF.setLatestEventInfo(Lesson_10.<span class="keyword">this</span><span>, </span><span class="string">"Title03"</span><span>, </span><span class="string">"Content03"</span><span>, pd); </span></span></li><li><span></span></li><li class="alt"><span>nm.notify(Notification_ID_MEDIA, mediaNF); </span></li><li><span class="keyword">break</span><span>; </span></li><li class="alt"><span></span></li><li><span class="keyword">case</span><span> R.id.le10bt05: </span></li><li class="alt"><span class="comment">//清除 mediaNF</span><span> </span></li><li><span>nm.cancel(Notification_ID_MEDIA); </span></li><li class="alt"><span class="keyword">break</span><span>; </span></li><li><span></span></li><li class="alt"><span class="keyword">case</span><span> R.id.le10bt06: </span></li><li><span>nm.cancelAll(); </span></li><li class="alt"><span class="keyword">break</span><span>; </span></li><li><span></span></li><li class="alt"><span class="keyword">case</span><span> R.id.le10bt07: </span></li><li><span class="comment">//自定义下拉视图，比如下载软件时，显示的进度条。</span><span> </span></li><li class="alt"><span>Notification notification = <span class="keyword">new</span><span> Notification(); </span></span></li><li><span></span></li><li class="alt"><span>notification.icon = R.drawable.icon; </span></li><li><span>notification.tickerText = <span class="string">"Custom!"</span><span>; </span></span></li><li class="alt"><span></span></li><li><span>RemoteViews contentView = <span class="keyword">new</span><span> RemoteViews(getPackageName(), R.layout.custom); </span></span></li><li class="alt"><span>contentView.setImageViewResource(R.id.image, R.drawable.icon); </span></li><li><span>contentView.setTextViewText(R.id.text, <span class="string">"Hello, this message is in a custom expanded view"</span><span>); </span></span></li><li class="alt"><span>notification.contentView = contentView; </span></li><li><span></span></li><li class="alt"><span class="comment">//使用自定义下拉视图时，不需要再调用setLatestEventInfo()方法</span><span> </span></li><li><span class="comment">//但是必须定义 contentIntent</span><span> </span></li><li class="alt"><span>notification.contentIntent = pd; </span></li><li><span></span></li><li class="alt"><span>nm.notify(<span class="number">3</span><span>, notification); </span></span></li><li><span class="keyword">break</span><span>; </span></li><li class="alt"><span>} </span></li><li><span>} </span></li><li class="alt"><span>}; </span></li><li><span></span></li><li class="alt"><span></span></li><li><span>} </span></li></ol></div><pre style="display: none" class="java" rows="15" cols="50" name="code">package com.yfz;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore.Audio;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.RemoteViews;
import android.widget.SeekBar;
import android.widget.TextView;
/**
 * Notification
 * @author Administrator
 *
 */
public class Lesson_10 extends Activity {
	
	//BaseNotification
	private Button bt01;
	
	//UpdateBaseNotification
	private Button bt02;
	
	//ClearBaseNotification
	private Button bt03;
	
	//MediaNotification
	private Button bt04;
	
	//ClearMediaNotification
	private Button bt05;
	
	//ClearALL
	private Button bt06;
	
	//CustomNotification
	private Button bt07;
	
	//通知管理器
	private NotificationManager nm;
	
	//通知显示内容
	private PendingIntent pd;
	
	@Override
	 public void onCreate(Bundle savedInstanceState) {
	        super.onCreate(savedInstanceState);
	        /*加载页面*/
	        setContentView(R.layout.lesson10);
	        
	        init();
	}
	
	private void init() {
		bt01 = (Button)findViewById(R.id.le10bt01);
		bt02 = (Button)findViewById(R.id.le10bt02);
		bt03 = (Button)findViewById(R.id.le10bt03);
		bt04 = (Button)findViewById(R.id.le10bt04);
		bt05 = (Button)findViewById(R.id.le10bt05);
		bt06 = (Button)findViewById(R.id.le10bt06);
		bt07 = (Button)findViewById(R.id.le10bt07);
		
		bt01.setOnClickListener(onclick);
		bt02.setOnClickListener(onclick);
		bt03.setOnClickListener(onclick);
		bt04.setOnClickListener(onclick);
		bt05.setOnClickListener(onclick);
		bt06.setOnClickListener(onclick);	
		bt07.setOnClickListener(onclick);
		
		nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		
		Intent intent = new Intent(this,Lesson_10.class);
		
		pd = PendingIntent.getActivity(Lesson_10.this, 0, intent, 0);
	}
	
	OnClickListener onclick = new OnClickListener() {
		
		//BASE Notification ID
		private int Notification_ID_BASE = 110;
		
		private Notification baseNF;
		
		//Notification ID
		private int Notification_ID_MEDIA = 119;
		
		private Notification mediaNF;
		
		@Override
		public void onClick(View v) {
			switch(v.getId()) {
				case R.id.le10bt01:
					//新建状态栏通知
					baseNF = new Notification();
					 
					//设置通知在状态栏显示的图标
					baseNF.icon = R.drawable.icon;
					
					//通知时在状态栏显示的内容
					baseNF.tickerText = "You clicked BaseNF!";
					
					//通知的默认参数 DEFAULT_SOUND, DEFAULT_VIBRATE, DEFAULT_LIGHTS. 
					//如果要全部采用默认值, 用 DEFAULT_ALL.
					//此处采用默认声音
					baseNF.defaults |= Notification.DEFAULT_SOUND;
					baseNF.defaults |= Notification.DEFAULT_VIBRATE;
					baseNF.defaults |= Notification.DEFAULT_LIGHTS;
					
					//让声音、振动无限循环，直到用户响应
					baseNF.flags |= Notification.FLAG_INSISTENT;
					
					//通知被点击后，自动消失
					baseNF.flags |= Notification.FLAG_AUTO_CANCEL;
					
					//点击'Clear'时，不清楚该通知(QQ的通知无法清除，就是用的这个)
					baseNF.flags |= Notification.FLAG_NO_CLEAR;
					
					
					//第二个参数 ：下拉状态栏时显示的消息标题 expanded message title
					//第三个参数：下拉状态栏时显示的消息内容 expanded message text
					//第四个参数：点击该通知时执行页面跳转
					baseNF.setLatestEventInfo(Lesson_10.this, "Title01", "Content01", pd);
					
					//发出状态栏通知
					//The first parameter is the unique ID for the Notification 
					// and the second is the Notification object.
					nm.notify(Notification_ID_BASE, baseNF);
					
					break;
					
				case R.id.le10bt02:
					//更新通知
					//比如状态栏提示有一条新短信，还没来得及查看，又来一条新短信的提示。
					//此时采用更新原来通知的方式比较。
					//(再重新发一个通知也可以，但是这样会造成通知的混乱，而且显示多个通知给用户，对用户也不友好)
					baseNF.setLatestEventInfo(Lesson_10.this, "Title02", "Content02", pd);
					nm.notify(Notification_ID_BASE, baseNF);
					break;
					
				case R.id.le10bt03:
					
					//清除 baseNF
					nm.cancel(Notification_ID_BASE);
					break;
					
				case R.id.le10bt04:
					mediaNF = new Notification();
					mediaNF.icon = R.drawable.icon;
					mediaNF.tickerText = "You clicked MediaNF!";
					
					//自定义声音
					mediaNF.sound = Uri.withAppendedPath(Audio.Media.INTERNAL_CONTENT_URI, "6");
					
					//通知时发出的振动
					//第一个参数: 振动前等待的时间
					//第二个参数： 第一次振动的时长、以此类推
					long[] vir = {0,100,200,300};
					mediaNF.vibrate = vir;
					
					mediaNF.setLatestEventInfo(Lesson_10.this, "Title03", "Content03", pd);
					
					nm.notify(Notification_ID_MEDIA, mediaNF);
					break;
					
				case R.id.le10bt05:
					//清除 mediaNF
					nm.cancel(Notification_ID_MEDIA);
					break;
					
				case R.id.le10bt06:
					nm.cancelAll();
					break;
					
				case R.id.le10bt07:
					//自定义下拉视图，比如下载软件时，显示的进度条。
					Notification notification = new Notification();
					
					notification.icon = R.drawable.icon;
					notification.tickerText = "Custom!";
					
					RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.custom);
					contentView.setImageViewResource(R.id.image, R.drawable.icon);
					contentView.setTextViewText(R.id.text, "Hello, this message is in a custom expanded view");
					notification.contentView = contentView;
					
					//使用自定义下拉视图时，不需要再调用setLatestEventInfo()方法
					//但是必须定义 contentIntent
					notification.contentIntent = pd;
					
					nm.notify(3, notification);
					break;
			}
		}
	};
	
	
}</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>主页面：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools"><a href="http://www.oschina.net/question/234345_40111#">源码</a><a href="http://www.oschina.net/question/234345_40111#">copy to clipboard</a><a href="http://www.oschina.net/question/234345_40111#">打印</a><a href="http://www.oschina.net/question/234345_40111#">？</a></div></div>
<ol class="dp-xml"><li class="alt"><span class="tag">&lt;?</span><span class="tag-name">xml</span><span> </span><span class="attribute">version</span><span>=</span><span class="attribute-value">"1.0"</span><span> </span><span class="attribute">encoding</span><span>=</span><span class="attribute-value">"utf-8"</span><span class="tag">?&gt;</span><span> </span></li><li><span class="tag">&lt;</span><span class="tag-name">LinearLayout</span><span> </span></li><li class="alt"><span class="attribute">xmlns:android</span><span>=</span><span class="attribute-value">"http://schemas.android.com/apk/res/android"</span><span> </span></li><li><span class="attribute">android:layout_width</span><span>=</span><span class="attribute-value">"fill_parent"</span><span> </span></li><li class="alt"><span class="attribute">android:layout_height</span><span>=</span><span class="attribute-value">"fill_parent"</span><span> </span></li><li><span class="attribute">android:orientation</span><span>=</span><span class="attribute-value">"vertical"</span><span class="tag">&gt;</span><span> </span></li><li class="alt"><span class="tag">&lt;</span><span class="tag-name">Button</span><span> </span></li><li><span class="attribute">android:id</span><span>=</span><span class="attribute-value">"@+id/le10bt01"</span><span> </span></li><li class="alt"><span class="attribute">android:layout_width</span><span>=</span><span class="attribute-value">"fill_parent"</span><span> </span></li><li><span class="attribute">android:layout_height</span><span>=</span><span class="attribute-value">"wrap_content"</span><span> </span></li><li class="alt"><span class="attribute">android:text</span><span>=</span><span class="attribute-value">"BaseNotification"</span><span> </span></li><li><span class="tag">/&gt;</span><span> </span></li><li class="alt"><span class="tag">&lt;</span><span class="tag-name">Button</span><span> </span></li><li><span class="attribute">android:id</span><span>=</span><span class="attribute-value">"@+id/le10bt02"</span><span> </span></li><li class="alt"><span class="attribute">android:layout_width</span><span>=</span><span class="attribute-value">"fill_parent"</span><span> </span></li><li><span class="attribute">android:layout_height</span><span>=</span><span class="attribute-value">"wrap_content"</span><span> </span></li><li class="alt"><span class="attribute">android:text</span><span>=</span><span class="attribute-value">"UpdateBaseNotification"</span><span> </span></li><li><span class="tag">/&gt;</span><span> </span></li><li class="alt"><span class="tag">&lt;</span><span class="tag-name">Button</span><span> </span></li><li><span class="attribute">android:id</span><span>=</span><span class="attribute-value">"@+id/le10bt03"</span><span> </span></li><li class="alt"><span class="attribute">android:layout_width</span><span>=</span><span class="attribute-value">"fill_parent"</span><span> </span></li><li><span class="attribute">android:layout_height</span><span>=</span><span class="attribute-value">"wrap_content"</span><span> </span></li><li class="alt"><span class="attribute">android:text</span><span>=</span><span class="attribute-value">"ClearBaseNotification"</span><span> </span></li><li><span class="tag">/&gt;</span><span> </span></li><li class="alt"><span class="tag">&lt;</span><span class="tag-name">Button</span><span> </span></li><li><span class="attribute">android:id</span><span>=</span><span class="attribute-value">"@+id/le10bt04"</span><span> </span></li><li class="alt"><span class="attribute">android:layout_width</span><span>=</span><span class="attribute-value">"fill_parent"</span><span> </span></li><li><span class="attribute">android:layout_height</span><span>=</span><span class="attribute-value">"wrap_content"</span><span> </span></li><li class="alt"><span class="attribute">android:text</span><span>=</span><span class="attribute-value">"MediaNotification"</span><span> </span></li><li><span class="tag">/&gt;</span><span> </span></li><li class="alt"><span class="tag">&lt;</span><span class="tag-name">Button</span><span> </span></li><li><span class="attribute">android:id</span><span>=</span><span class="attribute-value">"@+id/le10bt05"</span><span> </span></li><li class="alt"><span class="attribute">android:layout_width</span><span>=</span><span class="attribute-value">"fill_parent"</span><span> </span></li><li><span class="attribute">android:layout_height</span><span>=</span><span class="attribute-value">"wrap_content"</span><span> </span></li><li class="alt"><span class="attribute">android:text</span><span>=</span><span class="attribute-value">"ClearMediaNotification"</span><span> </span></li><li><span class="tag">/&gt;</span><span> </span></li><li class="alt"><span class="tag">&lt;</span><span class="tag-name">Button</span><span> </span></li><li><span class="attribute">android:id</span><span>=</span><span class="attribute-value">"@+id/le10bt06"</span><span> </span></li><li class="alt"><span class="attribute">android:layout_width</span><span>=</span><span class="attribute-value">"fill_parent"</span><span> </span></li><li><span class="attribute">android:layout_height</span><span>=</span><span class="attribute-value">"wrap_content"</span><span> </span></li><li class="alt"><span class="attribute">android:text</span><span>=</span><span class="attribute-value">"ClearALL"</span><span> </span></li><li><span class="tag">/&gt;</span><span> </span></li><li class="alt"><span class="tag">&lt;</span><span class="tag-name">Button</span><span> </span></li><li><span class="attribute">android:id</span><span>=</span><span class="attribute-value">"@+id/le10bt07"</span><span> </span></li><li class="alt"><span class="attribute">android:layout_width</span><span>=</span><span class="attribute-value">"fill_parent"</span><span> </span></li><li><span class="attribute">android:layout_height</span><span>=</span><span class="attribute-value">"wrap_content"</span><span> </span></li><li class="alt"><span class="attribute">android:text</span><span>=</span><span class="attribute-value">"CustomNotification"</span><span> </span></li><li><span class="tag">/&gt;</span><span> </span></li><li class="alt"><span class="tag">&lt;/</span><span class="tag-name">LinearLayout</span><span class="tag">&gt;</span><span> </span></li></ol></div><pre style="display: none" class="xhtml" rows="15" cols="50" name="code">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  android:orientation="vertical"&gt;
	&lt;Button
		android:id="@+id/le10bt01"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:text="BaseNotification"
	/&gt;
	&lt;Button
		android:id="@+id/le10bt02"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:text="UpdateBaseNotification"
	/&gt;
	&lt;Button
		android:id="@+id/le10bt03"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:text="ClearBaseNotification"
	/&gt;
	&lt;Button
		android:id="@+id/le10bt04"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:text="MediaNotification"
	/&gt;
	&lt;Button
		android:id="@+id/le10bt05"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:text="ClearMediaNotification"
	/&gt;
	&lt;Button
		android:id="@+id/le10bt06"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:text="ClearALL"
	/&gt;
	&lt;Button
		android:id="@+id/le10bt07"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:text="CustomNotification"
	/&gt;
&lt;/LinearLayout&gt;
</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>自定义视图页面：</p>
<p>&nbsp;</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools"><a href="http://www.oschina.net/question/234345_40111#">源码</a><a href="http://www.oschina.net/question/234345_40111#">copy to clipboard</a><a href="http://www.oschina.net/question/234345_40111#">打印</a><a href="http://www.oschina.net/question/234345_40111#">？</a></div></div>
<ol class="dp-c"><li class="alt"><span>&lt;?xml version=</span><span class="string">"1.0"</span><span> encoding=</span><span class="string">"utf-8"</span><span>?&gt; </span></li><li><span>&lt;LinearLayout xmlns:android=<span class="string">"http://schemas.android.com/apk/res/android"</span><span> </span></span></li><li class="alt"><span>android:orientation=<span class="string">"horizontal"</span><span> </span></span></li><li><span>android:layout_width=<span class="string">"fill_parent"</span><span> </span></span></li><li class="alt"><span>android:layout_height=<span class="string">"fill_parent"</span><span> </span></span></li><li><span>android:padding=<span class="string">"3dp"</span><span> </span></span></li><li class="alt"><span>&gt; </span></li><li><span>&lt;ImageView android:id=<span class="string">"@+id/image"</span><span> </span></span></li><li class="alt"><span>android:layout_width=<span class="string">"wrap_content"</span><span> </span></span></li><li><span>android:layout_height=<span class="string">"fill_parent"</span><span> </span></span></li><li class="alt"><span>android:layout_marginRight=<span class="string">"10dp"</span><span> </span></span></li><li><span>/&gt; </span></li><li class="alt"><span>&lt;TextView android:id=<span class="string">"@+id/text"</span><span> </span></span></li><li><span>android:layout_width=<span class="string">"wrap_content"</span><span> </span></span></li><li class="alt"><span>android:layout_height=<span class="string">"fill_parent"</span><span> </span></span></li><li><span>android:textColor=<span class="string">"#000"</span><span> </span></span></li><li class="alt"><span>/&gt; </span></li><li><span>&lt;/LinearLayout&gt; </span></li></ol></div><pre style="display: none" class="c-sharp" rows="15" cols="50" name="code">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="horizontal"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:padding="3dp"
              &gt;
    &lt;ImageView android:id="@+id/image"
              android:layout_width="wrap_content"
              android:layout_height="fill_parent"
              android:layout_marginRight="10dp"
              /&gt;
    &lt;TextView android:id="@+id/text"
              android:layout_width="wrap_content"
              android:layout_height="fill_parent"
              android:textColor="#000"
              /&gt;
&lt;/LinearLayout&gt;
</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>就讲这么多。</p></div></div></u><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/87011.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2013-02-26 20:21 <a href="http://www.cnitblog.com/liaoqingshan/archive/2013/02/26/87011.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>浅析Android 4.0的通知系统----转载</title><link>http://www.cnitblog.com/liaoqingshan/archive/2013/02/26/87010.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Tue, 26 Feb 2013 12:18:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2013/02/26/87010.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/87010.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2013/02/26/87010.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/87010.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/87010.html</trackback:ping><description><![CDATA[<span style="float: left">浅析Android 4.0的通知系统（附Android 4.0设计指南全文翻译）</span> <span style="font-size: 14px; padding-top: 8px" class="comm"><a href="http://mux.baidu.com/?p=3183#comments">评论[20]</a> </span>
<div style="clear: both" class="info">[ 2012-06-18 | <span class="tag"><a title="查看 交互设计 的全部文章" href="http://mux.baidu.com/?cat=3" rel="category">交互设计</a> </span>] </div>
<div class="text">
<p><img alt="" src="http://mux.baidu.com/img/97/top.jpg" /></p>
<p>通过手机的通知系统，可以将应用程序的一些重要消息告知给用户。流畅、舒适、友好的应用程序离不开精心设计的消息提醒机制。但是并不是所有的通知都是用户想看的，否则只会给用户造成骚扰，所以要谨慎使用通知。</p>
<p>在对《Android Design》进行翻译时发现：Android系统已经提出了一些关于通知消息的设计建议，故在此分享给大家。<br /><span id="more-3183"></span></p>
<h2><strong>一、何时使用通知？</strong></h2>
<p>通知主要用于对<strong>时间敏感</strong>（Time Sensitive）的事件，尤其是<strong>涉及他人</strong>（Involve another person）的同步事件。例如下面的Gtalk和日历发出的通知就是时间敏感，且与人相关的事件。<br /><img alt="" src="http://mux.baidu.com/img/97/1.jpg" /><br />那么什么时候又不应该使用通知呢？官方的建议是：</p>
<ul><li>不直接针对用户的，或不紧急的信息。例如SNS中与用户没有直接关系的新鲜事。Path可能就犯了这个错误。</li><li>正显示在当前屏幕的信息也不必创建一个通知。即正在聊天的时候，就不必再创建关于聊天消息的通知了。</li><li>系统可以自己完成而无需用户操作的简单动作，例如保存、同步或者是更新应用程序等。</li><li>如果发生错误了，但是应用程序可以快速自我恢复，此时也不必用通知去打断用户，甚至都可以不用让用户知道这个错误。</li><li>对于用户不能手动启动或停止的服务，也不必使用通知。</li><li>不要为了让用户对你的品牌记忆深刻而创建多余的通知，否则只会让用户反感。想让用户对你的应用程序保持注意力并且提供少量内容的最好方式是提供小部件（widget）给用户，让用户可以将它放到首页。 </li></ul>
<h2><strong>二、通知的设计指南</strong></h2>
<h3><strong>1. 使其私有化</strong></h3>
<p>其他用户发过来的通知应该在通知里包含用户的头像（Icon/Photo），还要显示通知的标题（Title）、消息内容（Message）、时间戳（Timestamp），以及应用程序的图标（Secondary Icon）。<img alt="" src="http://mux.baidu.com/img/97/2.jpg" /></p>
<h3><strong>2. 合并同类通知</strong></h3>
<p>如果一个应用程序发出了多个相同类型的通知，而且这些通知都还没被处理的话（被处理的通知会被移出通知抽屉），那么请将相同类型的通知合并为一个。</p>
<p>合并后的通知会有一个总结性的描述，并且能让用户知道一共合并了多少条通知（Number Pending）。</p>
<p><img alt="" src="http://mux.baidu.com/img/97/3.jpg" /></p>
<h3><strong>3. 对时间敏感事件的时间戳</strong></h3>
<p>默认的系统通知会在通知右上角打上时间戳，如果你认为显示时间戳对你的通知是没有意义的，那你可能就要重新考虑是否值得为这条消息创建一条通知了。如果这条通知确实足够重要，再决定是否不显示时间戳。</p>
<p>常见的需要显示时间戳的通知是通讯通知，如Email、短信、聊天消息这种，用户需要通过时间戳来理解消息的上下文。</p>
<h3><strong>4. 通知相关的导航机制</strong></h3>
<p>如果用户点击了一条通知，此时应该将相关的应用程序打开到可以对通知中提到的内容进行操作的状态。但如果用户点击了一个合并的通知，应该去到列表页面（内容页的上一层级），后面第三部分会详细阐述。</p>
<h3><strong>5. 自我清理</strong></h3>
<p>有些通知会在某个时间点出现告知用户一些相关的信息和提示，但是如果过了那个时间点，这个通知可能对用户来说就不重要了，此时就应该考虑自动删除这条通知。</p>
<p>同样的，用户查看过的聊天消息或邮件，也应该让用户不必手动操作就移除这些通知。</p>
<h3><strong>6. 为通知提供预览</strong></h3>
<p>提供一段简短的文本作为通知的预览可以让用户大致了解通知的内容，从而帮助用户决定是否立刻查看该通知。</p>
<p><img alt="" src="http://mux.baidu.com/img/97/4.jpg" /></p>
<h3><strong>7. 让用户决定是否显示通知</strong></h3>
<p>用户可能对频繁出现的通知感到厌烦，所以应该让用户决定是否显示通知。因此，在应用程序的设置中应该让用户可以取消通知。</p>
<h3><strong>8. 使用不同的图标</strong></h3>
<p>为了让用户在通知栏看一眼就能知道是哪个应用程序发出的通知，应该采用有自己特色的图标。所以在设计应用程序的图标的时候，应该注意与其他Android应用的通知图标有比较明显的区别。</p>
<p>但需要注意的是不要用颜色来区分，因为通知图标通常都是黑白的。</p>
<h2><strong>三、通知的导航机制</strong></h2>
<h3><strong>1. 单条通知与合并通知</strong></h3>
<p>如果用户点击了一条通知，此时应该将相关的应用程序打开到可以对通知中提到的内容进行操作的状态。例如用户收到一封新邮件的通知，用户点开该通知后应该去到这封邮件的内容页。<br /><img alt="" src="http://mux.baidu.com/img/97/5.jpg" /><br />因为同类通知会被合并，如果用户点击了一个合并的通知，应该去到列表页面（内容页的上一层级）。在下面的例子中，用户点开一条合并的新邮件通知后，进入了收件箱界面。<img alt="" src="http://mux.baidu.com/img/97/6.jpg" /></p>
<h3><strong>2. 间接通知</strong></h3>
<p>如果应用程序需要同时展示多个事件的信息，可以使用一条通知将用户指引到一个中间界面。这个界面会展示这些事件，并为用户提供进入应用程序的入口。这种类型的通知被称为间接通知。</p>
<p>例如一个用户在Gmail中收到了Calendar发出的一条间接通知。点击这条通知后打开一个中间界面（calendar interstitial），这个界面下显示了几个事件的提醒，在这个界面点&#8220;返回&#8221;键会回到Gmail，但是如果用户点击了某个事件提醒，就会离开这个中间界面并打开Calendar应用程序以显示这个事件的详细内容。在这个事件的详细内容的界面下，点&#8220;向上&#8221;和&#8220;返回&#8221;都会去到Calendar应用的首页。<br /><img alt="" src="http://mux.baidu.com/img/97/7.jpg" /><br />在间接通知的中间界面点&#8220;返回&#8221;会回到触发该通知的界面，返回路径中不会被插入其他界面。一旦用户通过中间界面进入了应用程序，&#8220;向上&#8221;和&#8220;返回&#8221;的逻辑就与标准通知一样了：在应用程序之间进行导航，而不会返回到中间界面。</p>
<p>关于间接通知的详细内容请查看百度MUX翻译的《Android Design》的模式Patterns&#8212;-导航Navigation章节。</p>
<h3><strong>3. 弹出通知</strong></h3>
<p>弹出通知会绕过抽屉通知直接出现在用户面前。一般情况下很少使用，只在需要及时地反馈并且必须打断用户的场合下才会使用。例如Talk应用使用这种形式的通知来提醒用户有好友邀请他加入视频聊天，因为这个邀请会在几秒后自动失效。</p>
<p>对于导航行为，弹出通知严格遵循间接通知的中间界面的导航逻辑。点&#8220;返回&#8221;会关闭弹出通知。如果用户从这条弹出通知进入了发出通知的应用程序，&#8220;向上&#8221;和&#8220;返回&#8221;的逻辑会与标准通知的逻辑保持一致，在应用程序内进行导航。<br /><img alt="" src="http://mux.baidu.com/img/97/8.jpg" /><br />关于间接通知的详细内容请查看百度MUX翻译的《Android Design》的模式Patterns&#8212;-导航Navigation章节。</p>
<h2><strong>四、通知的相关交互</strong></h2>
<h3><strong>1. 通知抽屉</strong></h3>
<p>默认情况下，待处理的通知是以图标形式显示在状态栏中，从屏幕上方向下滑即可打开通知抽屉。<br /><img alt="" src="http://mux.baidu.com/img/97/9.jpg" /><br />最近的通知排在最前面，点击一条通知会将其应用程序打开到与这条通知相关的界面。<br /><img alt="" src="http://mux.baidu.com/img/97/10.jpg" /><br />在一条通知上向左或向右横划即可移除该通知。<br /><img alt="" src="http://mux.baidu.com/img/97/11.jpg" /><br />在Android 4.0的平板电脑中，通知栏则被集成到底部的系统栏里，在通知区域的任意位置点击即可打开通知抽屉。<br /><img alt="" src="http://mux.baidu.com/img/97/12.jpg" /></p>
<h3><strong>2. 进行中的通知</strong></h3>
<p>有一些通知是让用户了解后台正在运行的进程。例如正在播放的音乐播放器、正在后台运行的省电程序、正在保护系统的安全软件等。另外也可以对下载上传、视频编码这种持续时间较长的任务提供反馈。这种进行中的通知是不可以被移除的。<br /><img alt="" src="http://mux.baidu.com/img/97/13.jpg" /></p>
<h3><strong>3. Dialog和Toast用作反馈</strong></h3>
<p>如果某个应用程序没有在当前屏幕运行，它就不应该弹出对话框（Dialog）和提示条（Toast）。对话框和提示条应该是用户在当前应用程序下执行操作时，用来提供即时的操作反馈的。比如对话框可以让用户知道某个操作的危险后果，而提示条可以让用户知道某个操作已成功执行。<br /><img alt="" src="http://mux.baidu.com/img/97/14.jpg" /></p>
<h2><strong>五、总结</strong></h2>
<p>在Android平台设计应用程序的通知消息时应该明确在哪些场景下使用通知；不同的场景显示什么类型的通知。在设计的时候还要注意通知的私有化、导航逻辑、清理机制、同类通知的合并、图标的设计等。为避免对用户造成骚扰，还应该在应用程序的设置中增加对是否显示通知消息的设置。</p>
<p>从较早版本的Android系统开始，就具备了比较成熟的通知系统，新版iOS系统也参考了类似的设计。所以充分利用Android的通知系统，一定可以让用户对你的应用程序了如指掌。<br /><br class="spacer_" /><br />另附上MUX翻译的最新版《Android Design》，欢迎大家下载阅读。</p>
<p>译文：<a href="http://mux.baidu.com/img/97/AndroidDesign-BaiduMUX.pdf" target="_blank">http://mux.baidu.com/img/97/AndroidDesign-BaiduMUX.pdf</a><br />原文：<a href="http://developer.android.com/design/" target="_blank">http://developer.android.com/design/</a><br /></p></div><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/87010.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2013-02-26 20:18 <a href="http://www.cnitblog.com/liaoqingshan/archive/2013/02/26/87010.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android中定时器的3种实现方法--转载</title><link>http://www.cnitblog.com/liaoqingshan/archive/2013/02/21/86994.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Thu, 21 Feb 2013 10:33:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2013/02/21/86994.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/86994.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2013/02/21/86994.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/86994.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/86994.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 在Android开发中，定时器一般有以下3种实现方法：一、采用Handler与线程的sleep(long)方法二、采用Handler的postDelayed(Runnable, long)方法三、采用Handler与timer及TimerTask结合的方法下面逐一介绍：一、采用Handle与线程的sleep(long)方法Handler主要用来处理接受到的消息。这只是最主要的方法，当然Handle...&nbsp;&nbsp;<a href='http://www.cnitblog.com/liaoqingshan/archive/2013/02/21/86994.html'>阅读全文</a><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/86994.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2013-02-21 18:33 <a href="http://www.cnitblog.com/liaoqingshan/archive/2013/02/21/86994.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android数据保存之ContentProvider</title><link>http://www.cnitblog.com/liaoqingshan/archive/2013/02/20/86987.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Wed, 20 Feb 2013 02:41:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2013/02/20/86987.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/86987.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2013/02/20/86987.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/86987.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/86987.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 内容提供器&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在Android安全模型中，一个应用程序编写的文件无法被其他任何应用程序所读写。每个应用程序都有自己的Linux用户ID和数据目录，以及其受保护的内存空间。Android程序可以通过下面两种方式进行彼此间的通信。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第一种是IPC（Inter-P...&nbsp;&nbsp;<a href='http://www.cnitblog.com/liaoqingshan/archive/2013/02/20/86987.html'>阅读全文</a><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/86987.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2013-02-20 10:41 <a href="http://www.cnitblog.com/liaoqingshan/archive/2013/02/20/86987.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android数据保存之SQLite方法</title><link>http://www.cnitblog.com/liaoqingshan/archive/2013/02/20/86986.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Wed, 20 Feb 2013 02:38:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2013/02/20/86986.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/86986.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2013/02/20/86986.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/86986.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/86986.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: /*&nbsp;* &nbsp;Android开发之数据保存技术（一）&nbsp;*&nbsp; 北京Android俱乐部群：167839253&nbsp;*&nbsp; Created on: 2011-8-17&nbsp;*&nbsp; Author: blueeagle&nbsp;*&nbsp; Email: liujiaxiang@gmail.com&nbsp;*/&nbsp;&nbsp;...&nbsp;&nbsp;<a href='http://www.cnitblog.com/liaoqingshan/archive/2013/02/20/86986.html'>阅读全文</a><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/86986.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2013-02-20 10:38 <a href="http://www.cnitblog.com/liaoqingshan/archive/2013/02/20/86986.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android保存数据四种方法简介--转载</title><link>http://www.cnitblog.com/liaoqingshan/archive/2013/02/20/86985.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Wed, 20 Feb 2013 02:12:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2013/02/20/86985.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/86985.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2013/02/20/86985.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/86985.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/86985.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Android保存数据总共有四种方法。我们可以通过这篇文章介绍的内容对此进行充分的掌握，以满足我们在实际应用中的需求。Android&nbsp;手机操作系统是一款基于Linux平台的开源操作系统。它应用于手机中能够帮助我们实现许多需求。比如今天为大家介绍的Android保存数据，就是其中一个比较重要的操作技巧。对于我们所熟悉的大部分软件都有一个比较典型的特点，应用现有的数据根据不同的需求来得到相应...&nbsp;&nbsp;<a href='http://www.cnitblog.com/liaoqingshan/archive/2013/02/20/86985.html'>阅读全文</a><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/86985.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2013-02-20 10:12 <a href="http://www.cnitblog.com/liaoqingshan/archive/2013/02/20/86985.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>XMPP协议--转载</title><link>http://www.cnitblog.com/liaoqingshan/archive/2013/02/19/86983.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Tue, 19 Feb 2013 10:06:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2013/02/19/86983.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/86983.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2013/02/19/86983.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/86983.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/86983.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 深入学习XMPP协议&nbsp;一．XMPP（协议简介）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XMPP协议（Extensible&nbsp;Messaging&nbsp;and&nbsp;PresenceProtocol，可扩展消息处理现场协议）是一种基于XML的协议，目的是为了解决及时通信标准而提出来的，最早是在Jabber上实现的。它继承了在XML环境中灵活的发展性。因此...&nbsp;&nbsp;<a href='http://www.cnitblog.com/liaoqingshan/archive/2013/02/19/86983.html'>阅读全文</a><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/86983.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2013-02-19 18:06 <a href="http://www.cnitblog.com/liaoqingshan/archive/2013/02/19/86983.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Android消息推送--转载</title><link>http://www.cnitblog.com/liaoqingshan/archive/2013/02/19/86982.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Tue, 19 Feb 2013 06:40:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2013/02/19/86982.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/86982.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2013/02/19/86982.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/86982.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/86982.html</trackback:ping><description><![CDATA[<h1><a id="cb_post_title_url" href="http://www.cnblogs.com/devinzhang/archive/2012/02/16/2354981.html">Android消息推送</a></h1><div id="cnblogs_post_body" style="font-family: serif; "><p><strong>1.</strong><strong>引言</strong><strong></strong></p><p>　　所谓的消息推送就是从服务器端向移动终端发送连接，传输一定的信息。比如一些新闻客户端，每隔一段时间收到一条或者多条通知，这就是从服务器端传来的推送消息；还比如常用的一些IM软件如微信、GTalk等，都具有服务器推送功能。</p><p>　　推送方法如下：</p><p>　　1)通过SMS进行服务器端和客户端的交流通信。</p><p>　　在Android平台上，你可以通过拦截SMS消息并且解析消息内容来了解服务器的意图，可以实现完全的实时操作。但是问题是这个方案的成本相对比较高，且依赖于运营商。</p><p>　　2)循环主动定时获取</p><p>　　这种方法需要客户端来做一个定时或者周期性的访问服务器端接口，以获得最新的消息。轮询的频率太慢可能导致某些消息的延迟，太快则会大量消耗网络带宽和电池。</p><p>　　3)持久连接</p><p>　　这个方案可以解决由轮询带来的性能问题，但是还是会消耗手机的电池。我们需要开一个服务来保持和服务器端的持久连接（苹果就和谷歌的C2DM是这种机制）。但是对于Android系统，当系统可用资源较低，系统会强制关闭我们的服务或者是应用，这种情况下连接会强制中断。（Apple的推送服务之所以工作的很好，是因为每一台手机仅仅保持一个与服务器之间的连接，事实上C2DM也是这么工作的。即所有的推送服务都是经由一个代理服务器完成的，这种情况下只需要和一台服务器保持持久连接即可。C2DM=<em>Cloud to Device Messaging</em>）。</p><p>　　相比之下第三种还是最可行的。为软件编写系统服务或开机启动功能；或者如果系统资源较低，服务被关闭后可以在onDestroy ()方法里面再重启该服务，进而实现持久连接的方式。</p><p>　　C2DM内置于Android的2.2系统上，无法兼容老的1.6到2.1系统；且依赖于Google官方提供的C2DM服务器，由于国内的网络环境，这个服务经常不可用。</p><p>　　建立在TCP协议之上的XMPP协议，不仅可提供可这种持久连接的功能，能实现服务器和客户机的双工通信，还能不依赖与系统版本和google服务器的限制，提供了比较好的解决方案。</p><p><strong>2. XMPP</strong><strong>协议</strong><strong></strong></p><p>　　XMPP全称Extensible Messaging and Presence Protocol，前身是Jabber项目，是一种以XML为基础的开放式即时通讯协议。XMPP因为被Google Talk和网易泡泡应用而被广大网民所接触。XMPP的关键特色是，分散式的即时通讯系统，以及使用XML串流。XMPP目前被IETF国际标准组织完成了标准化工作。</p><p>　　<strong>Android push notification</strong>(androidpn) 是一个基于XMPP协议的java开源实现，它包含了完整的客户端和服务器端。该服务器端基本是在另外一个开源工程openfire基础上修改实现的。</p><p>　　androidpn客户端需要用到一个基于java的开源XMPP协议包asmack，这个包同样也是基于openfire下的另外一个开源项目smack，不过我们不需要自己编译，可以直接把androidpn客户端里面的asmack.jar拿来使用。客户端利用asmack中提供的XMPPConnection类与服务器建立持久连接，并通过该连接进行用户注册和登录认证，同样也是通过这条连接，接收服务器发送的通知。</p><p>　　androidpn服务器端也是java语言实现的，基于openfire开源工程，不过它的Web部分采用的是spring框架，这一点与openfire是不同的。Androidpn服务器包含两个部分，一个是侦听在5222端口上的XMPP服务，负责与客户端的XMPPConnection类进行通信，作用是用户注册和身份认证，并发送推送通知消息。另外一部分是Web服务器，采用一个轻量级的HTTP服务器，负责接收用户的Web请求。服务器的这两方式，意义非凡：当相应的TCP端口被防火墙封闭，可以使用轮询的方式进行访问，因此又有助于通过防火墙。</p></div><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/86982.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2013-02-19 14:40 <a href="http://www.cnitblog.com/liaoqingshan/archive/2013/02/19/86982.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>两年没来了</title><link>http://www.cnitblog.com/liaoqingshan/archive/2013/02/19/86981.html</link><dc:creator>游子</dc:creator><author>游子</author><pubDate>Tue, 19 Feb 2013 06:19:00 GMT</pubDate><guid>http://www.cnitblog.com/liaoqingshan/archive/2013/02/19/86981.html</guid><wfw:comment>http://www.cnitblog.com/liaoqingshan/comments/86981.html</wfw:comment><comments>http://www.cnitblog.com/liaoqingshan/archive/2013/02/19/86981.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/liaoqingshan/comments/commentRss/86981.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/liaoqingshan/services/trackbacks/86981.html</trackback:ping><description><![CDATA[哈哈，这么久时间没来照料你了。<br />博客排名还是第4，怎么没什么变化呀。<br /><small style="font-family: Verdana; line-height: 18px; background-color: #fafafa; ">4.&nbsp;</small><a href="http://www.cnitblog.com/liaoqingshan/" style="color: #000099; font-family: Verdana; font-size: 12px; line-height: 18px; background-color: #fafafa; ">游子</a>&nbsp;<a href="http://www.cnitblog.com/liaoqingshan/rss.aspx" style="padding-left: 0px; color: #000099; font-family: Verdana; font-size: 12px; line-height: 18px; background-color: #fafafa; ">(rss)</a><br style="font-family: Verdana; font-size: 12px; line-height: 18px; background-color: #fafafa; " /><small style="font-family: Verdana; line-height: 18px; background-color: #fafafa; ">(312,02-19 14:14,250153)<br /><br /><span style="font-size: 12pt; ">第一篇android日志，学习android软件编程。<br />新年新气象，希望在这上面收获第一桶金哈。</span></small><img src ="http://www.cnitblog.com/liaoqingshan/aggbug/86981.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/liaoqingshan/" target="_blank">游子</a> 2013-02-19 14:19 <a href="http://www.cnitblog.com/liaoqingshan/archive/2013/02/19/86981.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>