<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="css/rss.xslt"?>
<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>spridu</title><link>http://www.spridu.cn/</link><description>专注互联网体系和软件开发技术。</description><generator>RainbowSoft Studio Z-Blog 1.8 Walle Build 100427</generator><language>zh-CN</language><copyright>Copyright www.spridu.cn All Rights Reserved.【闽ICP备09047731号】&amp;amp;nbsp &amp;amp;nbsp &amp;amp;nbspQQ:1560894&amp;amp;nbsp||&amp;amp;nbspemail:admin@spridu.cn|------在线投稿-------|</copyright><pubDate>Thu, 16 Feb 2012 13:08:56 +0800</pubDate><item><title>关于c中的结构体指针转换问题</title><author>admin@spridu.cn (spridu)</author><link>http://www.spridu.cn/article/c-c++/2012/02/16/c-struct-convert-froce-mem-stack.shtml</link><pubDate>Thu, 16 Feb 2012 12:57:37 +0800</pubDate><guid>http://www.spridu.cn/article/c-c++/2012/02/16/c-struct-convert-froce-mem-stack.shtml</guid><description><![CDATA[<p>#include&lt;stdio.h&gt;<br />#include&lt;malloc.h&gt;<br />//结构体1<br />typedef struct Atom<br />{<br />&nbsp;&nbsp;&nbsp; int param1;<br />&nbsp;&nbsp;&nbsp; long param2;<br />&nbsp;&nbsp;&nbsp; char *param_str3;<br />} *TpAtom;<br />//结构体2<br />typedef struct Wrapper<br />{<br />&nbsp;&nbsp;&nbsp; //TpAtom pAtom01;<br />&nbsp;&nbsp;&nbsp; struct Atom atom;<br />&nbsp;&nbsp;&nbsp; char *param_1;<br />&nbsp;&nbsp;&nbsp; double dvalue;<br />} *TpWrapper;<br />int main(void)<br />{<br />&nbsp;&nbsp;&nbsp; TpAtom pAtom = (TpAtom)malloc(sizeof(struct Atom));<br />&nbsp;&nbsp;&nbsp; pAtom-&gt;param1 = 10;<br />&nbsp;&nbsp;&nbsp; pAtom-&gt;param2 = 14445522;<br />&nbsp;&nbsp;&nbsp; pAtom-&gt;param_str3 = &quot;hello world!&quot;;<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; TpWrapper pWrapper = (TpWrapper)pAtom;<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; //查看pWrapper的内存值情况<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //printf(&quot;转换后没赋值前的pWrapper：%s\n&quot;,pWrapper-&gt;param_1);<br />&nbsp;&nbsp;&nbsp; printf(&quot;获取原始Atom中的值%s\n&quot;,pWrapper-&gt;atom.param_str3);<br />&nbsp;&nbsp;&nbsp; //对pWrapper进行赋值<br /><br />&nbsp;&nbsp;&nbsp; pWrapper-&gt;param_1 = &quot;hello world!2222&quot;;<br />&nbsp;&nbsp;&nbsp; pWrapper-&gt;dvalue = 45552;<br />&nbsp;&nbsp;&nbsp; printf(&quot;转换后赋值后的pWrapper：%s\n&quot;,pWrapper-&gt;param_1);<br />&nbsp;&nbsp;&nbsp; pWrapper-&gt;atom.param2 = 1536;<br />&nbsp;&nbsp;&nbsp; printf(&quot;查看Atom中原始的值:%ld\n&quot;,pAtom-&gt;param2);<br />&nbsp;&nbsp;&nbsp; TpAtom pAtom02 = (TpAtom)pWrapper;<br />&nbsp;&nbsp;&nbsp; // 并没有对pAtom02赋值<br />&nbsp;&nbsp;&nbsp; printf(&quot;转换后的pAtom02：%s\n&quot;,pAtom02-&gt;param_str3);<br />&nbsp;&nbsp;&nbsp; printf(&quot;atom-double-拷贝:%ld\n&quot;,pAtom02-&gt;param2);<br />&nbsp;&nbsp;&nbsp; pAtom02-&gt;param2 = 1537;<br />&nbsp;&nbsp;&nbsp; printf(&quot;atom-double-原始:%ld\n&quot;,pAtom-&gt;param2); free(pAtom);<br />&nbsp;&nbsp;&nbsp; return 0;<br />}</p><p>Copyright © 2008 www.spridu.cn</p><p><a href="http://www.spridu.cn/article/c-c++/2012/02/16/c-struct-convert-froce-mem-stack.shtml" target="_blank">继续阅读《关于c中的结构体指针转换问题》的全文内容...</a></p><p>分类: <a href="http://www.spridu.cn/c-c++.shtml">c/c++</a> | Tags: <a href="http://www.spridu.cn/catalog.asp?tags=c">c</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=struct">struct</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=%E7%BB%93%E6%9E%84%E4%BD%93%E6%8C%87%E9%92%88">结构体指针</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=%E8%BD%AC%E6%8D%A2">转换</a>&nbsp;&nbsp; | <a href="http://www.spridu.cn/article/c-c++/2012/02/16/c-struct-convert-froce-mem-stack.shtml#comment" target="_blank">添加评论</a>(0)</p><h3>相关文章:</h3><ul><li><a href="http://www.spridu.cn/article/javaweb/2012/01/10/jvm-c++-android-dalvik-call.shtml">如何使用c++来操作jvm并调取java类</a> (2012-1-10 15:53:54)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/12/16/toolchain-ndk-c-c++-native-tools-serises.shtml">定制自己的toolchain环境搭建教程(1)</a> (2011-12-16 16:19:24)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/03/15/androidTongGuojniLaiShiXiandhcpShenQingYiJiwifiWangLuoDeJianKong.shtml">android通过jni来实现dhcp申请以及wifi网络的监控</a> (2011-3-15 22:45:30)  </li><li><a href="http://www.spridu.cn/article/c-c++/2011/02/22/EclipseForCOrC++-Action-android-jni-linux_5966.shtml">windows下面使用Eclipse c/c++工具的注意要点</a> (2011-2-22 16:14:28)  </li><li><a href="http://www.spridu.cn/article/c-c++/2010/12/13/c++Stack-dui-programe-javahexinjiangjie.shtml">c++堆栈大体的理解</a> (2010-12-13 21:57:15)  </li></ul>]]></description><category>c/c++</category><comments>http://www.spridu.cn/article/c-c++/2012/02/16/c-struct-convert-froce-mem-stack.shtml#comment</comments><wfw:comment>http://www.spridu.cn/</wfw:comment><wfw:commentRss>http://www.spridu.cn/feed.asp?cmt=355</wfw:commentRss><trackback:ping>http://www.spridu.cn/cmd.asp?act=tb&amp;id=355&amp;key=d8926426</trackback:ping></item><item><title>如何使用c++来操作jvm并调取java类</title><author>admin@spridu.cn (spridu)</author><link>http://www.spridu.cn/article/javaweb/2012/01/10/jvm-c++-android-dalvik-call.shtml</link><pubDate>Tue, 10 Jan 2012 15:53:54 +0800</pubDate><guid>http://www.spridu.cn/article/javaweb/2012/01/10/jvm-c++-android-dalvik-call.shtml</guid><description><![CDATA[<p>在做mtk和研究android的dalvik源码时会遇到过不知如何去从大体理解dalvik，掌握了dalvik的创建过程对于分析和研究启动过程是十分必要的。</p><p>在C++中调用Java的方法一般分为五个步骤：初始化虚拟机、获取类、创建类对象、调用方法和退出虚拟机。</p><p>1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 初始化虚拟机。</p><p>&nbsp;&nbsp;&nbsp; JNIEnv *env;</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;JavaVM *jvm;</p><p>&nbsp;&nbsp;&nbsp; JavaVMInitArgs vm_args;</p><p>&nbsp;&nbsp;&nbsp; JavaVMOption options[3];</p><p>&nbsp;&nbsp;&nbsp; int res;</p><p>&nbsp;&nbsp;&nbsp; //设置参数</p><p>&nbsp;&nbsp;&nbsp; options[0].optionString = &quot;-Djava.compiler=NONE&quot;;</p><p>&nbsp;&nbsp;&nbsp; options[1].optionString = &quot;-Djava.class.path=.&quot;;</p><p>&nbsp;&nbsp;&nbsp; options[2].optionString = &quot;-verbose:jni&quot;;</p><p>&nbsp;&nbsp;&nbsp; vm_args.version = JNI_VERSION_1_4;</p><p>&nbsp;&nbsp;&nbsp; vm_args.nOptions = 3;</p><p>&nbsp;&nbsp;&nbsp; vm_args.options = options;</p><p>&nbsp;&nbsp;&nbsp; vm_args.ignoreUnrecognized = JNI_TRUE;</p><p>&nbsp;&nbsp;&nbsp; res = JNI_CreateJavaVM(&amp;jvm, (void**)&amp;env, &amp;vm_args);</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;if (res &gt;= 0)</p><p>{</p><p>&nbsp;&nbsp;&nbsp;&nbsp; //创建虚拟机成功</p><p>}</p><p>一个应用程序只需要一个虚拟机，但是每个线程需要自己的虚拟机运行环境。我们从一个虚拟机获取多个当前线程的运行环境，代码如下：</p><p>int result=0;</p><p>result=jvm-&gt;AttachCurrentThread( reinterpret_cast( &amp;env ), 0 );</p><p>if(result&gt;=0)</p><p>{</p><p>&nbsp;&nbsp;&nbsp;&nbsp; //获取运行环境成功</p><p>}</p><p>当线程退出时，需要释放本线程使用的运行环境。</p><p>jvm-&gt;DetachCurrentThread();</p><p>2)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 获取类</p><p>在进行方法调用之前，需要先获取相应的类，类名称必须包括包名，其中的&ldquo;.&rdquo;用&ldquo;/&rdquo;代替。</p><p>jclass JavaClass;</p><p>JavaClass = env-&gt;FindClass(&quot;com/test/TestInterface&quot;);</p><p>&nbsp;&nbsp; if(JavaClass != 0)</p><p>&nbsp;&nbsp; {</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //获取成功</p><p>&nbsp;&nbsp; }</p><p>3)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 创建类对象</p><p>如果需要调用的方法静态方法，则可以跳过本步骤。反之，则需要构造该对象。构造对象是通过调用类的构造函数来实现的，构咱函数的方法声明为, GetMethodID方法的参数在下一步骤详细说明。</p><p>jobject obj;</p><p>jmethodID ctor;</p><p>ctor = env-&gt;GetMethodID(JavaClass,&quot;&quot;,&quot;()V&quot;);</p><p>if(ctor != 0)//获取方法成功</p><p>&nbsp;&nbsp; {</p><p>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj = env-&gt;NewObject(JavaClass, ctor);</p><p>&nbsp;&nbsp; }</p><p>4)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 调用方法</p><p>调用一个方法需要两个步骤：获取方法句柄和调用方法。</p><p>jmethodID methodID = env-&gt;GetMethodID( JavaClass, &quot;setTest&quot;,&quot;(I)V&quot;);</p><p>if(methodID!=0)//获取方法成功</p><p>{</p><p>env-&gt;CallVoidMethod( obj, methodID,12);</p><p>}</p><p>GetStaticMethodID是用来获取静态方法的定义，GetMethodID则是获取非静态的方法定义。他们传入参数的参数依次为：类定义、方法名称和方法的定义，方法的定义可以用jdk中带的javap工具反编译class文件获取，其格式如下：</p><p>public void setTest(int inTest);</p><p>&nbsp; Signature: (I)V</p><p>Signature后面的内容就是方法的定义。</p><p>CallVoidMethod 是对获取的方法进行调用，JNI接口中提供了一系列的同类方法，包括静态方法的调用函数（如：CallStaticXXXMethod）和非静态的方法（如：CallXXXMethod），其中XXX表示的不同方法返回类型，包括int、object等等。</p><p>5)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 退出虚拟机</p><p>退出虚拟机调用方法如下：</p><p>jvm-&gt;DestroyJavaVM();</p><p>在JNI接口定义和众多文档中都说，只有最后一个线程退出时，该方法才会返回，但是我只用一个线程，调用该方法也无法返回。故此建议系统退出时执行该方法，或者整个程序退出时，让<a rel="nofollow" target="_blank">虚拟机</a>自己释放。</p><p>[注意]：</p><p>&Oslash;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在处理中文字符串时，需要注意Java的char是双字节的，采用Unicode编码，在和C++中的char转换时，需要用到系统API：WideCharToMultiByte和MultiByteToWideChar。</p><p>&Oslash;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注意对运行环境中对象引用时的释放，以免引起内存泄漏。</p><p>jstring str;</p><p>wchar_t *w_buffer =(wchar_t *)env-&gt;GetStringChars(str,0);</p><p>env-&gt;ReleaseStringChars(str,(const unsigned short *)w_buffer);</p><p>Copyright © 2008 www.spridu.cn</p><p><a href="http://www.spridu.cn/article/javaweb/2012/01/10/jvm-c++-android-dalvik-call.shtml" target="_blank">继续阅读《如何使用c++来操作jvm并调取java类》的全文内容...</a></p><p>分类: <a href="http://www.spridu.cn/javaweb.shtml">JavaWeb</a> | Tags: <a href="http://www.spridu.cn/catalog.asp?tags=JVM">JVM</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=c">c</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=Android">Android</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=dalvik">dalvik</a>&nbsp;&nbsp; | <a href="http://www.spridu.cn/article/javaweb/2012/01/10/jvm-c++-android-dalvik-call.shtml#comment" target="_blank">添加评论</a>(0)</p><h3>相关文章:</h3><ul><li><a href="http://www.spridu.cn/article/c-c++/2012/02/16/c-struct-convert-froce-mem-stack.shtml">关于c中的结构体指针转换问题</a> (2012-2-16 12:57:37)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/12/16/toolchain-ndk-c-c++-native-tools-serises.shtml">定制自己的toolchain环境搭建教程(1)</a> (2011-12-16 16:19:24)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/12/07/AndroidKuaJinCongChuanDiParcelYuanLiJieXi.shtml">Android跨进程传递Parcel原理解析</a> (2011-12-7 11:53:55)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/12/07/androidZhongZiDingYi-soDongTaiKuDeWeiZhi.shtml">android中自定义.so动态库的位置</a> (2011-12-7 11:28:32)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/11/24/androidDeIntentServiceYuanMaFenXi.shtml">android的IntentService源码分析</a> (2011-11-24 11:29:26)  </li></ul>]]></description><category>JavaWeb</category><comments>http://www.spridu.cn/article/javaweb/2012/01/10/jvm-c++-android-dalvik-call.shtml#comment</comments><wfw:comment>http://www.spridu.cn/</wfw:comment><wfw:commentRss>http://www.spridu.cn/feed.asp?cmt=354</wfw:commentRss><trackback:ping>http://www.spridu.cn/cmd.asp?act=tb&amp;id=354&amp;key=657d339a</trackback:ping></item><item><title>定制自己的toolchain环境搭建教程(1)</title><author>admin@spridu.cn (spridu)</author><link>http://www.spridu.cn/article/android-dev/2011/12/16/toolchain-ndk-c-c++-native-tools-serises.shtml</link><pubDate>Fri, 16 Dec 2011 16:19:24 +0800</pubDate><guid>http://www.spridu.cn/article/android-dev/2011/12/16/toolchain-ndk-c-c++-native-tools-serises.shtml</guid><description><![CDATA[<p>1.操作系统是ubuntu11.10</p><p>2.去官网下载<a target="_blank" href="http://ftp.gnu.org/gnu/texinfo/texinfo-4.9.tar.gz">texinfo4.9</a>源码</p><p>3.安装依赖包:</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sudo apt-get install libncurses5-dev</p><p>4.编译并安装到自己的机器中</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ./configure --prefix /bin --enable-widec</p><p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; make install</p><p>这样就解决来安装toolchain的第一步，texinfo4.9的依赖</p><p>结果:</p><p>spridu@ubuntu:~/soft$ cd texinfo<br />spridu@ubuntu:~/soft/texinfo$ ls<br />bin&nbsp; share<br />spridu@ubuntu:~/soft/texinfo$ cd bin/<br />spridu@ubuntu:~/soft/texinfo/bin$ ls<br />info&nbsp; infokey&nbsp; install-info&nbsp; makeinfo&nbsp; texi2dvi&nbsp; texi2pdf&nbsp; texindex<br />spridu@ubuntu:~/soft/texinfo/bin$ cd ..<br />spridu@ubuntu:~/soft/texinfo$ cd share/<br />spridu@ubuntu:~/soft/texinfo/share$ ls<br />info&nbsp; locale&nbsp; man&nbsp; texinfo<br />spridu@ubuntu:~/soft/texinfo/share$</p><p>5.使用<a target="_blank" href="http://gcc.parentingamerica.com/releases/gcc-4.1.0/gcc-4.1.0.tar.bz2">gcc-4.1</a>,如果高于这个版本需要卸载gcc，但是在卸载之前要编译gcc4.1</p><p>因为<span style="widows: 2; text-transform: none; text-indent: 0px; border-collapse: separate; font: medium Simsun; white-space: normal; orphans: 2; letter-spacing: normal; color: rgb(0,0,0); word-spacing: 0px; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px" class="Apple-style-span"><span style="border-collapse: collapse; font-size: 13px" class="Apple-style-span">源码中有些函数定义不规范，用对函数格式非常严格的GCC 4.3编译就会出错，而GCC 4.1 不会报错。</span></span></p><p>&nbsp;6.错误总结:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a target="_blank" href="http://www.spridu.cn/article/android-dev/2011/07/26/androidPoJiegoogleNDKXianZhi.shtml">编译期间</a></p><p>编译参考网站：<a target="_blank" href="http://blog.sina.com.cn/s/blog_4a0a39c30100crhl.html">疯子博客</a></p><p>Copyright © 2008 www.spridu.cn</p><p><a href="http://www.spridu.cn/article/android-dev/2011/12/16/toolchain-ndk-c-c++-native-tools-serises.shtml" target="_blank">继续阅读《定制自己的toolchain环境搭建教程(1)》的全文内容...</a></p><p>分类: <a href="http://www.spridu.cn/android-dev.shtml">Android</a> | Tags: <a href="http://www.spridu.cn/catalog.asp?tags=toolchain">toolchain</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=ndk">ndk</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=c">c</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=c">c</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=Native">Native</a>&nbsp;&nbsp; | <a href="http://www.spridu.cn/article/android-dev/2011/12/16/toolchain-ndk-c-c++-native-tools-serises.shtml#comment" target="_blank">添加评论</a>(0)</p><h3>相关文章:</h3><ul><li><a href="http://www.spridu.cn/article/c-c++/2012/02/16/c-struct-convert-froce-mem-stack.shtml">关于c中的结构体指针转换问题</a> (2012-2-16 12:57:37)  </li><li><a href="http://www.spridu.cn/article/javaweb/2012/01/10/jvm-c++-android-dalvik-call.shtml">如何使用c++来操作jvm并调取java类</a> (2012-1-10 15:53:54)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/12/07/androidZhongZiDingYi-soDongTaiKuDeWeiZhi.shtml">android中自定义.so动态库的位置</a> (2011-12-7 11:28:32)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/09/05/android-ndk-r5ZhongWenFanYi.shtml">android-ndk-r5中文翻译</a> (2011-9-5 15:42:19)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/07/26/androidPoJiegoogleNDKXianZhi.shtml">android破解googleNDK限制</a> (2011-7-26 16:4:50)  </li></ul>]]></description><category>Android</category><comments>http://www.spridu.cn/article/android-dev/2011/12/16/toolchain-ndk-c-c++-native-tools-serises.shtml#comment</comments><wfw:comment>http://www.spridu.cn/</wfw:comment><wfw:commentRss>http://www.spridu.cn/feed.asp?cmt=353</wfw:commentRss><trackback:ping>http://www.spridu.cn/cmd.asp?act=tb&amp;id=353&amp;key=76438b36</trackback:ping></item><item><title>Android跨进程传递Parcel原理解析</title><author>admin@spridu.cn (spridu)</author><link>http://www.spridu.cn/article/android-dev/2011/12/07/AndroidKuaJinCongChuanDiParcelYuanLiJieXi.shtml</link><pubDate>Wed, 07 Dec 2011 11:53:55 +0800</pubDate><guid>http://www.spridu.cn/article/android-dev/2011/12/07/AndroidKuaJinCongChuanDiParcelYuanLiJieXi.shtml</guid><description><![CDATA[<div id="blog_text" class="cnt">在android里面跨进从传递数据只能传递基本的数据类型，对象是不能传递的其实也可以要使用aidl，不过原理还是在新的进程中创建一个一样的对象，类的描述就在aidl里面，所以在跨进程的时候为什么要有aidl的原因，下面是用c++的方式通过nativeAPI的soket传递Parcel。之前做过了在android下通过socket发送数据的实验，也做过了parcel包的制作和解包的实验（这两个实验的源程序之前都在本博客的其他文章中贴过）。昨天和今天把这两个过程合并了起来：即在Android环境下，甲程序（C++程序）将数据封装在Parcel中，并把Parcel发送到SOCKET；乙程序（C++程序）通过SOCKET接收到Parcel包，并解出封装在其中数据。<br /><br />原先认为分开的过程都做过了，合并起来应该不是什么问题。但昨天一下午却未能成功，一直到今天上午才基本上弄了出来。现将程序的源代码放在下面：<br /><br /><em>程序里面的一些无用的调试信息没有去掉，都已经注释掉了，不影响编译运行。如果觉得影响阅读，可先复制下来，再将其中的调试信息删除即可。</em><br /><br /><font color="#ff00ff">/****************** server program （server.cpp）*****************/<br />#include &lt;stdio.h&gt;<br />#include &lt;sys/types.h&gt;<br />#include &lt;sys/socket.h&gt;<br />#include &lt;string.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;sys/un.h&gt;<br />#include &lt;unistd.h&gt;<br />#include &lt;arpa/inet.h&gt;<br />#include &lt;utils/Parcel.h&gt;<br />using namespace android;<br />Parcel p;<br />void write_Parcel();<br />int main()<br />{<br />&nbsp;&nbsp;&nbsp; int sockfd,newfd,ret,send_num,send_num_total=0;<br />&nbsp;&nbsp;&nbsp; char buf[200];<br />&nbsp;&nbsp;&nbsp; struct sockaddr_in server_addr;<br />//&nbsp;&nbsp;&nbsp; remove(&quot;/data/server.socket&quot;);/*不管有没有，先删除一下，否则如果该文件已经存在的的话，bind会失败。*/<br />//&nbsp;&nbsp;&nbsp; memset(&amp;server_addr,0,sizeof(server_addr));<br />&nbsp;&nbsp;&nbsp; server_addr.sin_family=AF_INET;<br />//&nbsp;&nbsp;&nbsp; strcpy(server_addr.sin_path,&quot;/data/server.socket&quot;);<br />&nbsp;&nbsp;&nbsp; server_addr.sin_addr.s_addr=INADDR_ANY;<br />&nbsp;&nbsp;&nbsp; server_addr.sin_port=htons(5678);<br />&nbsp;&nbsp;&nbsp; sockfd=socket(AF_INET,SOCK_STREAM,0);<br />&nbsp;&nbsp;&nbsp; printf(&quot;this is the socket_server *TCP* mode.\n&quot;);<br />&nbsp;&nbsp;&nbsp; if (sockfd&lt;0)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;调用socket函数建立socket描述符出错！\n&quot;);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; exit(1);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; printf(&quot;@调用socket函数建立socket描述符成功！\n&quot;);<br />&nbsp;&nbsp;&nbsp; ret=bind(sockfd,(struct sockaddr *)(&amp;server_addr),sizeof(server_addr));<br />&nbsp;&nbsp;&nbsp; if (ret&lt;0)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;调用bind函数绑定套接字与地址出错！\n&quot;);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; exit(2);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; printf(&quot;调用bind函数绑定套接字与地址成功！\n&quot;);<br />&nbsp;&nbsp;&nbsp; ret=listen(sockfd,4);<br />&nbsp;&nbsp;&nbsp; if (ret&lt;0)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;调用listen函数出错，无法宣告服务器已经可以接受连接！\n&quot;);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; exit(3);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; printf(&quot;调用listen函数成功，宣告服务器已经可以接受连接请求！\n&quot;);<br />&nbsp;&nbsp;&nbsp; newfd=accept(sockfd,NULL,NULL);/*newfd连接到调用connect的客户端*/<br />&nbsp;&nbsp;&nbsp; if (newfd&lt;0)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;调用accept函数出错，无法接受连接请求，建立连接失败！\n&quot;);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; exit(4);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; printf(&quot;调用accept函数成功，服务器与客户端建立连接成功！\n&quot;);<br /><br />&nbsp;&nbsp;&nbsp; write_Parcel();<br /><br />&nbsp;&nbsp;&nbsp; while (1)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; send_num=send(newfd,p.data(), p.dataSize(),MSG_DONTWAIT);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (send_num&lt;0)<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;调用send函数失败！&quot;);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; send_num_total+=send_num;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;调用send函数成功，本次发送%d个字节。目前共发送了%d个字节的数据。\n&quot;,send_num,send_num_total);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sleep(2);<br />&nbsp;&nbsp;&nbsp; }<br />}<br /><br />/****************** 向Parcel内写入数据 ********************/<br />void write_Parcel()<br />{<br />&nbsp;&nbsp;&nbsp; status_t status;<br />&nbsp;&nbsp;&nbsp; size_t parcel_position;<br />&nbsp;&nbsp;&nbsp; int intp=987654;<br />&nbsp;&nbsp;&nbsp; char charp='g';<br />&nbsp;&nbsp;&nbsp; float floatp=3.14159;<br />&nbsp;&nbsp;&nbsp; double doublep=12345.6789012;<br />&nbsp;&nbsp;&nbsp; long longp=1234567890;<br />&nbsp;&nbsp;&nbsp; char *stringp=&quot;this is my parcel test! this is my parcel test! this is my parcel test! this is my parcel test!&quot;;<br /><br />//&nbsp;&nbsp;&nbsp; printf(&quot;1：Parcel包的大小是%d字节，Parcel结构体的大小是%d字节\n&quot;,sizeof(p),sizeof(Parcel));<br />//&nbsp;&nbsp;&nbsp; readParcel(&amp;p);<br />&nbsp;&nbsp;&nbsp; parcel_position = p.dataPosition();/*备份位置*/<br />//&nbsp;&nbsp;&nbsp; printf(&quot;当前Parcel的读写位置是：%d\n&quot;,parcel_position);<br />&nbsp;&nbsp;&nbsp; /*************写int类型***************/<br />&nbsp;&nbsp;&nbsp; status=p.writeInt32(intp);<br />&nbsp;&nbsp;&nbsp; if (status==NO_ERROR)<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;write int type success!\n&quot;);<br />&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;write int type fail,the errno=%d\n&quot;,errno);<br />&nbsp;&nbsp;&nbsp; /*************写char类型***************/<br />&nbsp;&nbsp;&nbsp; status=p.writeInt32(charp);<br />&nbsp;&nbsp;&nbsp; if (status==NO_ERROR)<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;write char type success!\n&quot;);<br />&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;write char type fail,the errno=%d\n&quot;,errno);<br />&nbsp;&nbsp;&nbsp; /*************写Float类型***************/<br />&nbsp;&nbsp;&nbsp; status=p.writeFloat(floatp);<br />&nbsp;&nbsp;&nbsp; if (status==NO_ERROR)<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;write Float type success!\n&quot;);<br />&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;write Float type fail,the errno=%d\n&quot;,errno);<br />&nbsp;&nbsp;&nbsp; /*************写Double类型***************/<br />&nbsp;&nbsp;&nbsp; status=p.writeDouble(doublep);<br />&nbsp;&nbsp;&nbsp; if (status==NO_ERROR)<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;write Double type success!\n&quot;);<br />&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;write Double type fail,the errno=%d\n&quot;,errno);<br />&nbsp;&nbsp;&nbsp; /*************写long类型***************/<br />&nbsp;&nbsp;&nbsp; status=p.writeInt64(longp);<br />&nbsp;&nbsp;&nbsp; if (status==NO_ERROR)<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;write long type success!\n&quot;);<br />&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;write long type fail,the errno=%d\n&quot;,errno);<br />&nbsp;&nbsp;&nbsp; /*************写String类型***************/<br />&nbsp;&nbsp;&nbsp; status=p.writeCString(stringp);<br />&nbsp;&nbsp;&nbsp; if (status==NO_ERROR)<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;write String type success!\n&quot;);<br />&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;write String type fail,the errno=%d\n&quot;,errno);<br /><br />//&nbsp;&nbsp;&nbsp; printf(&quot;2：Parcel包的大小是%d字节，Parcel结构体的大小是%d字节\n&quot;,sizeof(p),sizeof(Parcel));<br />//&nbsp;&nbsp;&nbsp; readParcel(&amp;p);<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; /*************将parcel读写位置置回原位***************/<br />&nbsp;&nbsp;&nbsp; p.setDataPosition(parcel_position);<br />&nbsp;&nbsp;&nbsp; printf(&quot;3：Parcel包的大小是%d字节，Parcel结构体的大小是%d字节\n&quot;,sizeof(p),sizeof(Parcel));<br />//&nbsp;&nbsp;&nbsp; readParcel(&amp;p);<br />&nbsp;&nbsp;&nbsp; /*************读出变量***************/<br />&nbsp;&nbsp;&nbsp; printf(&quot;读出的int类型变量为：%d\n&quot;,p.readInt32());<br />&nbsp;&nbsp;&nbsp; printf(&quot;读出的char类型变量为：%c\n&quot;,(char)p.readInt32());<br />&nbsp;&nbsp;&nbsp; printf(&quot;读出的Float类型变量为：%f\n&quot;,(float)p.readFloat());<br />&nbsp;&nbsp;&nbsp; printf(&quot;读出的Double类型变量为：%f\n&quot;,(double)p.readDouble());<br />&nbsp;&nbsp;&nbsp; printf(&quot;读出的long类型变量为：%ld\n&quot;,(long)p.readInt64());<br />&nbsp;&nbsp;&nbsp; printf(&quot;读出的字符串为：%s\n&quot;,p.readCString());<br />&nbsp;&nbsp;&nbsp; printf(&quot;4：Parcel包的大小是%d字节，Parcel结构体的大小是%d字节\n&quot;,sizeof(p),sizeof(Parcel));<br />//&nbsp;&nbsp;&nbsp; readParcel(&amp;p);<br />}<br /></font><br /><br /><font color="#0000ff">/****************** client program （client.cpp）*****************/<br />#include &lt;stdio.h&gt;<br />#include &lt;sys/types.h&gt;<br />#include &lt;sys/socket.h&gt;<br />#include &lt;string.h&gt;<br />#include &lt;stdlib.h&gt;<br />#include &lt;sys/un.h&gt;<br />#include &lt;unistd.h&gt;<br />#include &lt;arpa/inet.h&gt;<br />#include &lt;utils/Parcel.h&gt;<br />using namespace android;<br />Parcel p;<br />int main()<br />{<br />&nbsp;&nbsp;&nbsp; int sockfd,ret,recv_num,recv_num_total=0;<br />&nbsp;&nbsp;&nbsp; char buf[<font color="#ff0000"><strong>124</strong></font>];<br />&nbsp;&nbsp;&nbsp; struct sockaddr_in server_addr;<br />//&nbsp;&nbsp;&nbsp; memset(&amp;server_addr,0,sizeof(server_addr));<br />&nbsp;&nbsp;&nbsp; server_addr.sin_family=AF_INET;<br />//&nbsp;&nbsp;&nbsp; strcpy(server_addr.sin_path,&quot;/data/server.socket&quot;);<br />&nbsp;&nbsp;&nbsp; server_addr.sin_addr.s_addr=INADDR_ANY;<br />&nbsp;&nbsp;&nbsp; server_addr.sin_port=htons(5678);<br />&nbsp;&nbsp;&nbsp; sockfd=socket(AF_INET,SOCK_STREAM,0);<br />&nbsp;&nbsp;&nbsp; printf(&quot;this is the socket_client *TCP* mode.\n&quot;);<br />&nbsp;&nbsp;&nbsp; if (sockfd&lt;0)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;调用socket函数建立socket描述符出错！\n&quot;);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit(1);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; printf(&quot;调用socket函数建立socket描述符成功！\n&quot;);<br />&nbsp;&nbsp;&nbsp; ret=connect(sockfd,(struct sockaddr *)(&amp;server_addr),sizeof(server_addr));<br />&nbsp;&nbsp;&nbsp; if (ret&lt;0)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;调用connect函数失败，客户端连接服务器失败!\n &quot;);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit(2);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; printf(&quot;调用connect函数成功，客户端连接服务器成功！\n&quot;);<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; while (1)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; recv_num=recv(sockfd,buf,sizeof(buf),0);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; p.setData((unsigned char *) buf, sizeof(buf));<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (recv_num&lt;0)<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;调用recv接收失败！\n&quot;);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if(recv_num&gt;0)<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; recv_num_total+=recv_num;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;调用recv函数成功，本次接收到%d个字节。共收到%d个字节的数据。\n&quot;,recv_num,recv_num_total);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;服务器端：调用recv接收成功！本次接收到%d个字节，共收到%d个字节的数据。\n&quot;,recv_num,recv_num_total);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;读出的int类型变量为：%d\n&quot;,p.readInt32());<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;读出的char类型变量为：%c\n&quot;,(char)p.readInt32());<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;读出的Float类型变量为：%f\n&quot;,(float)p.readFloat());<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;读出的Double类型变量为：%f\n&quot;,(double)p.readDouble());<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;读出的long类型变量为：%ld\n&quot;,(long)p.readInt64());<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;读出的字符串为：%s\n&quot;,p.readCString());<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />//&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else/*收到数据为0，表明服务器与客户端的连接已经中断*/<br />//&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {<br />//&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;与客户端的连接已中断，当前共收到%d个字节的数据。服务器将再次等待客户端的连接。\n&quot;,recv_num_total);<br />//&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; newfd=accept(sockfd,NULL,NULL);/*当客户端退出后，再次开始接收客户端的连接*/<br />//&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sleep(2);<br />&nbsp;&nbsp;&nbsp; }<br />}<br /></font><br /><br /><font color="#339966">/****************** Android Makefile文件 （Android.mk）*****************/<br />LOCAL_PATH:= $(call my-dir)<br />include $(CLEAR_VARS)<br /><br />LOCAL_SRC_FILES:= \<br />&nbsp;&nbsp;&nbsp; server.cpp<br />LOCAL_SHARED_LIBRARIES := \<br />&nbsp;&nbsp;&nbsp; libutils \<br />&nbsp;&nbsp;&nbsp; libcutils<br />LOCAL_PRELINK_MODULE := false<br />LOCAL_MODULE:= socket_server_s<br />include $(BUILD_EXECUTABLE)<br /><br /><br />include $(CLEAR_VARS)<br /><br />LOCAL_SRC_FILES:= \<br />&nbsp;&nbsp;&nbsp; client.cpp<br />LOCAL_SHARED_LIBRARIES := \<br />&nbsp;&nbsp;&nbsp; libutils \<br />&nbsp;&nbsp;&nbsp; libcutils<br />LOCAL_PRELINK_MODULE := false<br />LOCAL_MODULE:= socket_client_s<br />include $(BUILD_EXECUTABLE)</font><br /><br /><br />将这三个文件放在一个文件夹下，我给这个文件夹起了个名字叫parcel_send，其实叫什么都无所谓。然后把parcel_send放到android源代码根目录下的/development目录下面。<br /><br />用emulator命令启动模拟器后，再另打开一个linux终端，用cd命令进入android源代码根目录下，su取得root权限后，先后执行&ldquo;make socket_server_s&rdquo;和&ldquo;make socket_client_s&rdquo;对程序进行编译。<br /><br />编译通过后，将生成的可执行文件送入android环境的/data目录下：<br />adb push (android源代码根目录)/out/target/product/generic/system/bin/socket_server_s /data<br />adb push (android源代码根目录)/out/target/product/generic/system/bin/socket_client_s /data<br /><br />分别再开两个linux终端，用adb shell命令进入模拟器终端，cd /data，先后执行&quot;./socket_server_s&quot;和&ldquo;./socket_client_s&rdquo;，即可看到程序运行。<br /><br /><br /><font color="#993300">/////////////////////////////////////////////服务器端程序运行结果/////////////////////////////////////////////<br /># ./socket_server_s&nbsp;&nbsp;&nbsp; <br />this is the socket_server *TCP* mode.<br />@调用socket函数建立socket描述符成功！<br />调用bind函数绑定套接字与地址成功！<br />调用listen函数成功，宣告服务器已经可以接受连接请求！<br />调用accept函数成功，服务器与客户端建立连接成功！<br />write int type success!<br />write char type success!<br />write Float type success!<br />write Double type success!<br />write long type success!<br />write String type success!<br />3：Parcel包的大小是48字节，Parcel结构体的大小是48字节<br />读出的int类型变量为：987654<br />读出的char类型变量为：g<br />读出的Float类型变量为：3.141590<br />读出的Double类型变量为：12345.678901<br />读出的long类型变量为：1234567890<br />读出的字符串为：this is my parcel test! this is my parcel test! this is my parcel test! this is my parcel test!<br />4：Parcel包的大小是48字节，Parcel结构体的大小是48字节<br />调用send函数成功，本次发送124个字节。目前共发送了124个字节的数据。<br />调用send函数成功，本次发送124个字节。目前共发送了248个字节的数据。<br />调用send函数成功，本次发送124个字节。目前共发送了372个字节的数据。<br />调用send函数成功，本次发送124个字节。目前共发送了496个字节的数据。<br />调用send函数成功，本次发送124个字节。目前共发送了620个字节的数据。<br />调用send函数成功，本次发送124个字节。目前共发送了744个字节的数据。<br />调用send函数成功，本次发送124个字节。目前共发送了868个字节的数据。<br />&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;<br /></font><br /><br /><font color="#000080">/////////////////////////////////////////////客户端程序运行结果/////////////////////////////////////////////<br /># ./socket_client_s<br />this is the socket_client *TCP* mode.<br />调用socket函数建立socket描述符成功！<br />调用connect函数成功，客户端连接服务器成功！<br />调用recv函数成功，本次接收到124个字节。共收到124个字节的数据。<br />服务器端：调用recv接收成功！本次接收到124个字节，共收到124个字节的数据。<br />读出的int类型变量为：987654<br />读出的char类型变量为：g<br />读出的Float类型变量为：3.141590<br />读出的Double类型变量为：12345.678901<br />读出的long类型变量为：1234567890<br />读出的字符串为：this is my parcel test! this is my parcel test! this is my parcel test! this is my parcel test!<br />调用recv函数成功，本次接收到124个字节。共收到248个字节的数据。<br />服务器端：调用recv接收成功！本次接收到124个字节，共收到248个字节的数据。<br />读出的int类型变量为：987654<br />读出的char类型变量为：g<br />读出的Float类型变量为：3.141590<br />读出的Double类型变量为：12345.678901<br />读出的long类型变量为：1234567890<br />读出的字符串为：this is my parcel test! this is my parcel test! this is my parcel test! this is my parcel test!<br />调用recv函数成功，本次接收到124个字节。共收到372个字节的数据。<br />服务器端：调用recv接收成功！本次接收到124个字节，共收到372个字节的数据。<br />读出的int类型变量为：987654<br />读出的char类型变量为：g<br />读出的Float类型变量为：3.141590<br />读出的Double类型变量为：12345.678901<br />读出的long类型变量为：1234567890<br />读出的字符串为：this is my parcel test! this is my parcel test! this is my parcel test! this is my parcel test!<br />调用recv函数成功，本次接收到124个字节。共收到496个字节的数据。<br />服务器端：调用recv接收成功！本次接收到124个字节，共收到496个字节的数据。<br />读出的int类型变量为：987654<br />读出的char类型变量为：g<br />读出的Float类型变量为：3.141590<br />读出的Double类型变量为：12345.678901<br />读出的long类型变量为：1234567890<br />读出的字符串为：this is my parcel test! this is my parcel test! this is my parcel test! this is my parcel test!<br />调用recv函数成功，本次接收到124个字节。共收到620个字节的数据。<br />服务器端：调用recv接收成功！本次接收到124个字节，共收到620个字节的数据。<br />读出的int类型变量为：987654<br />读出的char类型变量为：g<br />读出的Float类型变量为：3.141590<br />读出的Double类型变量为：12345.678901<br />读出的long类型变量为：1234567890<br />读出的字符串为：this is my parcel test! this is my parcel test! this is my parcel test! this is my parcel test!<br />调用recv函数成功，本次接收到124个字节。共收到744个字节的数据。<br />服务器端：调用recv接收成功！本次接收到124个字节，共收到744个字节的数据。<br />读出的int类型变量为：987654<br />读出的char类型变量为：g<br />读出的Float类型变量为：3.141590<br />读出的Double类型变量为：12345.678901<br />读出的long类型变量为：1234567890<br />读出的字符串为：this is my parcel test! this is my parcel test! this is my parcel test! this is my parcel test!<br />调用recv函数成功，本次接收到124个字节。共收到868个字节的数据。<br />服务器端：调用recv接收成功！本次接收到124个字节，共收到868个字节的数据。<br />读出的int类型变量为：987654<br />读出的char类型变量为：g<br />读出的Float类型变量为：3.141590<br />读出的Double类型变量为：12345.678901<br />读出的long类型变量为：1234567890<br />读出的字符串为：this is my parcel test! this is my parcel test! this is my parcel test! this is my parcel test!<br />&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;&hellip;</font><br /><br /><br />＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝<br />可以看到，例子程序成功实现了将数据封装入parcel、发送到socket、从socket接收、从接收到的parcel中解出数据的过程。<br /><br /><strong>存在的问题：</strong>在客户端程序中，有一句<font color="#0000ff">char buf[<font color="#ff0000"><strong>124</strong></font>];</font>，这个buf是用来接收socket传过来的parcel包的，但问题是，客户端无法确定parcel包的大小。在实验中，最开始并不是用的<strong><font color="#ff0000">124</font></strong>这个数据，而是一个小的多的数，结果解出的数据就出现了混乱和丢失。而使用sizeof(p)和sizeof(Parcel)均无法得出正确的parcel包大小（这一点可以从服务器端运行结果中看出，在parcel包大小为124的情况下，仍然显示&ldquo;<font color="#993300">Parcel包的大小是48字节，Parcel结构体的大小是48字节<font color="#000000">&ldquo;</font></font>）。因此无奈之下，只能通过查看服务端程序的send函数的返回值，才得知过程中发送了124个字节，因此再修改客户端程序，也才有了这句的设定：<font color="#0000ff">char buf[<font color="#ff0000"><strong>124</strong></font>];。<br /><font color="#000000"><br />当然，如果在实际应用中，接收和发送端程序都是自己编写，自己心里有数的话，那么也无所谓。只要发送多少字节，然后接收端就相应接多少字节就可以了。但是如果不能满足这个条件，也就是说发送端发送的字节数不确定或者不知道的话，就有一定麻烦了。对于这个问题我的解决思路有三种（但未经严格实验验证）：<br />1、把</font></font><font color="#0000ff">char buf[<font color="#ff0000"><strong>124</strong></font>];</font><font color="#0000ff"><font color="#000000">中的124换为发送端可能发送的最大数值，这样就都可以接收到了，而不会出现丢失数据。<br />2、发送端在传送parcel数据之前，先把数据包的大小发过来。接收端根据这个信息再做适当调整。<br />3、参考android源代码的解决方法，</font></font><font color="#0000ff"><font color="#000000">android源代码的&ldquo;/system/core/libcutils/record_stream.c&rdquo;中有这方面的较好的解决方法，可以直接调用它里面提供的函数，或根据自己的需要在它的基础上加以修改。</font></font></div><p>Copyright © 2008 www.spridu.cn</p><p><a href="http://www.spridu.cn/article/android-dev/2011/12/07/AndroidKuaJinCongChuanDiParcelYuanLiJieXi.shtml" target="_blank">继续阅读《Android跨进程传递Parcel原理解析》的全文内容...</a></p><p>分类: <a href="http://www.spridu.cn/android-dev.shtml">Android</a> | Tags: <a href="http://www.spridu.cn/catalog.asp?tags=Android">Android</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=aidl">aidl</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=Parcel">Parcel</a>&nbsp;&nbsp; | <a href="http://www.spridu.cn/article/android-dev/2011/12/07/AndroidKuaJinCongChuanDiParcelYuanLiJieXi.shtml#comment" target="_blank">添加评论</a>(1)</p><h3>相关文章:</h3><ul><li><a href="http://www.spridu.cn/article/javaweb/2012/01/10/jvm-c++-android-dalvik-call.shtml">如何使用c++来操作jvm并调取java类</a> (2012-1-10 15:53:54)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/12/07/androidZhongZiDingYi-soDongTaiKuDeWeiZhi.shtml">android中自定义.so动态库的位置</a> (2011-12-7 11:28:32)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/11/24/androidDeIntentServiceYuanMaFenXi.shtml">android的IntentService源码分析</a> (2011-11-24 11:29:26)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/11/15/RuHeZaiandroidDedataWenJianXiTongZhongChuangJianWenJianYiJiMuLu.shtml">如何在android的data文件系统中创建文件以及目录</a> (2011-11-15 15:15:34)  </li><li><a href="http://www.spridu.cn/article/j2me/2011/11/14/J2meHeAndroidDeChaBie.shtml">J2me和Android的差别</a> (2011-11-14 10:36:29)  </li></ul><hr /> <h3>最新评论:</h3><ul><li><a href="http://www.spridu.cn/article/android-dev/2011/12/07/AndroidKuaJinCongChuanDiParcelYuanLiJieXi.shtml#cmt901">2011-12-8 22:39:15</a>，<a href="http://www.geweigroup.com">博洋家纺怎么样</a> ： nd7jz7明天你还会更新的吧  明天我在来</li>, <li><a href="%article_url%">%article_title%</a> (%article_time%)</li></ul>]]></description><category>Android</category><comments>http://www.spridu.cn/article/android-dev/2011/12/07/AndroidKuaJinCongChuanDiParcelYuanLiJieXi.shtml#comment</comments><wfw:comment>http://www.spridu.cn/</wfw:comment><wfw:commentRss>http://www.spridu.cn/feed.asp?cmt=352</wfw:commentRss><trackback:ping>http://www.spridu.cn/cmd.asp?act=tb&amp;id=352&amp;key=473f50e4</trackback:ping></item><item><title>android中自定义.so动态库的位置</title><author>admin@spridu.cn (spridu)</author><link>http://www.spridu.cn/article/android-dev/2011/12/07/androidZhongZiDingYi-soDongTaiKuDeWeiZhi.shtml</link><pubDate>Wed, 07 Dec 2011 11:28:32 +0800</pubDate><guid>http://www.spridu.cn/article/android-dev/2011/12/07/androidZhongZiDingYi-soDongTaiKuDeWeiZhi.shtml</guid><description><![CDATA[<p>我们在做android开发的时候可能会遇到过这样的问题,动态的加载.so库文件，而在api中只提供给我们System.LoadLibrary();这样一个接口。我们只能加载/data/data/xxx.xxx.xxx/lib/下面的.so库，不能加载sdcard上面的.so库。这样给动态加载.so带来了许多的麻烦。但是我们可以通过dlopen(&quot;.system/lib/xxx.so&quot;,RTLD_NOW);来调用系统的lib,你只需要写个.so放到工程的/libs/arm-eabi/xxxx下面，然后让.so去调用你系统里面某个位置对.so，从而达到动态安装的.so的功能。</p><p>&nbsp;参考下面的例子:</p><p>实现了在UBUNTU LINUX环境下使用dlopen函数动态调用.so链接库。但是也提到了在Android下未能成功。由于Android也是使用linux内核，因此估计程序本身可能并没有什么错误，问题应该是出现在Android.mk文件中。今天早上试着修改了一下Android.mk，终于将这个问题解决了。<br /><br />好在两个C程序和一个.mk文件并不是太长，现将它们贴一遍<br /><br /><font color="#993300">/*************************** dl1.c *******************************/<br />#include&lt;stdio.h&gt;<br />#include&lt;stdlib.h&gt;<br />#include&lt;dlfcn.h&gt;<br />int main()<br />{<br />&nbsp;&nbsp;&nbsp; int a,b;<br />&nbsp;&nbsp;&nbsp; void *p;<br />&nbsp;&nbsp;&nbsp; int (*func)(int,int);<br />&nbsp;&nbsp;&nbsp; scanf(&quot;%d%d&quot;,&amp;a,&amp;b);<br />&nbsp;&nbsp;&nbsp; p=dlopen(&quot;./dl2.so&quot;,RTLD_NOW);<br />&nbsp;&nbsp;&nbsp; if(p==NULL)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;dlopen error!\n&quot;);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; exit(0);<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf(&quot;dlopen ok!\n&quot;);<br />&nbsp;&nbsp;&nbsp; func=dlsym(p,&quot;max&quot;);<br />&nbsp;&nbsp;&nbsp; printf(&quot;%d与%d相比，%d为大数。\n&quot;,a,b,(*func)(a,b));<br />&nbsp;&nbsp;&nbsp; dlclose(p);<br />}<br />/*************************** dl1.c *******************************/</font><br /><br /><br /><font color="#993366">/*************************** dl2.c *******************************/<br />#include&lt;stdio.h&gt;<br />int max(int x,int y)<br />{<br />&nbsp;&nbsp;&nbsp; return x&gt;y?x:y;<br />}<br />/*************************** dl2.c *******************************/</font><br /><br /><br /><font color="#339966">/*************************** Android.mk *******************************/<br />LOCAL_PATH:= $(call my-dir)<br />include $(CLEAR_VARS)<br /><br />LOCAL_SRC_FILES:= \<br />&nbsp;&nbsp;&nbsp; dl2.c<br />LOCAL_PRELINK_MODULE := true<br />#LOCAL_CFLAGS=-fPIC<br />LOCAL_MODULE:= dl2<br />include $(BUILD_SHARED_LIBRARY)<br /><br />include $(CLEAR_VARS)<br />LOCAL_SRC_FILES:= \<br />&nbsp;&nbsp;&nbsp; dl1.c<br /></font><font color="#339966"><font color="#0000ff">LOCAL_SHARED_LIBRARIES := \<br />&nbsp;&nbsp;&nbsp; libdl</font><br /></font><font color="#339966"><font color="#ff0000">#LOCAL_CFLAGS=-ldl</font><br />LOCAL_PRELINK_MODULE := true<br />LOCAL_MODULE:= dl1<br />include $(BUILD_EXECUTABLE)<br />/*************************** Android.mk *******************************/</font><br /><br />上一次之所以失败，原因似乎是使用了红色字体的那一句，因为我将其更换为蓝色字体的那一句，问题就解决了。看来这样写在链接时才能正确找到libdl.so，而包含该.so文件是使用dlopen函数的保证。<br /><br />将这三个文件放在Android源码目录下的development目录下的dl文件夹中（dl文件夹是新建的），然后在终端中使用root权限进入到Android源码目录下，执行 make dl1。成功后将会在android源码目录/out/target/product/generic/system/lib/中生成dl2.so动态链接库文件，在android源码目录/out/target/product/generic/system/bin/中生成dl1可执行文件。<br /><br />使用以下命令将它们放入Android模拟器，注意要先启动emulator<br /><br />adb push Android源码目录/out/target/product/generic/system/lib/dl2.so /data<br />adb push Android源码目录/out/target/product/generic/system/bin/dl1 /data<br /><br />进入data文件夹执行<br />adb shell<br /># cd data<br /># ./dl1<br /><br />87 9（这里随便输入两个数）<br />dlopen ok!<br />87与9相比，87为大数。</p><p>Copyright © 2008 www.spridu.cn</p><p><a href="http://www.spridu.cn/article/android-dev/2011/12/07/androidZhongZiDingYi-soDongTaiKuDeWeiZhi.shtml" target="_blank">继续阅读《android中自定义.so动态库的位置》的全文内容...</a></p><p>分类: <a href="http://www.spridu.cn/android-dev.shtml">Android</a> | Tags: <a href="http://www.spridu.cn/catalog.asp?tags=Android">Android</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=Native">Native</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=ndk">ndk</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=%E5%8A%A8%E6%80%81%E5%8A%A0%E8%BD%BD%2Eso">动态加载.so</a>&nbsp;&nbsp; | <a href="http://www.spridu.cn/article/android-dev/2011/12/07/androidZhongZiDingYi-soDongTaiKuDeWeiZhi.shtml#comment" target="_blank">添加评论</a>(0)</p><h3>相关文章:</h3><ul><li><a href="http://www.spridu.cn/article/javaweb/2012/01/10/jvm-c++-android-dalvik-call.shtml">如何使用c++来操作jvm并调取java类</a> (2012-1-10 15:53:54)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/12/16/toolchain-ndk-c-c++-native-tools-serises.shtml">定制自己的toolchain环境搭建教程(1)</a> (2011-12-16 16:19:24)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/12/07/AndroidKuaJinCongChuanDiParcelYuanLiJieXi.shtml">Android跨进程传递Parcel原理解析</a> (2011-12-7 11:53:55)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/11/24/androidDeIntentServiceYuanMaFenXi.shtml">android的IntentService源码分析</a> (2011-11-24 11:29:26)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/11/15/RuHeZaiandroidDedataWenJianXiTongZhongChuangJianWenJianYiJiMuLu.shtml">如何在android的data文件系统中创建文件以及目录</a> (2011-11-15 15:15:34)  </li></ul>]]></description><category>Android</category><comments>http://www.spridu.cn/article/android-dev/2011/12/07/androidZhongZiDingYi-soDongTaiKuDeWeiZhi.shtml#comment</comments><wfw:comment>http://www.spridu.cn/</wfw:comment><wfw:commentRss>http://www.spridu.cn/feed.asp?cmt=351</wfw:commentRss><trackback:ping>http://www.spridu.cn/cmd.asp?act=tb&amp;id=351&amp;key=008d5507</trackback:ping></item><item><title>android的IntentService源码分析</title><author>admin@spridu.cn (spridu)</author><link>http://www.spridu.cn/article/android-dev/2011/11/24/androidDeIntentServiceYuanMaFenXi.shtml</link><pubDate>Thu, 24 Nov 2011 11:29:26 +0800</pubDate><guid>http://www.spridu.cn/article/android-dev/2011/11/24/androidDeIntentServiceYuanMaFenXi.shtml</guid><description><![CDATA[<p>IntentService的出现主要是在于解决了多次startService()调用出现的资源同步问题，初次之外还可以解决UI阻塞的问题，因为他使用了HandlerThread 将MessageQueue和Looper放到了单独的</p><p>线程中，从而维护了对此startService()的环境队列，在者又可以在HandlerThread 中区执行Handler.target的细节。所以就相当于你在service中开了线程并将该线程加入MessageQueue和Looper，用于维护队列和处理事件。</p><p>IntentService是一个通过<span style="color: #0000ff">Context.startService(Intent)</span>启动可以处理异步请求的Service,使用时你只需要继承IntentService和重写其中的<span style="color: #0000ff">onHandleIntent(Intent)</span>方法接收一个Intent对象,在适当的时候会停止自己(一般在工作完成的时候). 所有的请求的处理都在一个工作线程中完成,它们会交替执行(但不会阻塞主线程的执行),一次只能执行一个请求.(**本人修改了原文的一些翻译)</p><div>下面是要分析的源码:<br />&nbsp;</div><div><div><div><span style="color: #0000ff">public</span>&nbsp;<span style="color: #0000ff">abstract</span>&nbsp;<span style="color: #0000ff">class</span>&nbsp;IntentService&nbsp;<span style="color: #0000ff">extends</span>&nbsp;Service {&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff">private</span>&nbsp;<span style="color: #0000ff">volatile</span>&nbsp;Looper mServiceLooper;&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="color: #0000ff">private</span>&nbsp;<span style="color: #0000ff">volatile</span>&nbsp;ServiceHandler mServiceHandler;&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff">private</span>&nbsp;String mName;&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="color: #0000ff">private</span>&nbsp;<span style="color: #0000ff">boolean</span>&nbsp;mRedelivery;&nbsp;<br />&nbsp; &nbsp;&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff">private</span>&nbsp;<span style="color: #0000ff">final</span>&nbsp;<span style="color: #0000ff">class</span>&nbsp;ServiceHandler&nbsp;<span style="color: #0000ff">extends</span>&nbsp;Handler {&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff">public</span>&nbsp;ServiceHandler(Looper looper) {&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="color: #0000ff">super</span>(looper);&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp;<br />&nbsp; &nbsp;&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span style="color: #0000ff">public</span>&nbsp;<span style="color: #0000ff">void</span>&nbsp;handleMessage(Message msg) {&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onHandleIntent((Intent)msg.obj);&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; stopSelf(msg.arg1);&nbsp;<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div></div>从源码可以分析出:<br />IntentService 实际上是Looper,Handler,Service 的集合体,他不仅有服务的功能,还有处理和循环消息的功能.<br /><br />下面是onCreate()的源码:<br />&nbsp;</div><div><div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff">public</span>&nbsp;<span style="color: #0000ff">void</span>&nbsp;onCreate() {&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff">super</span>.onCreate();&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HandlerThread thread =&nbsp;<span style="color: #0000ff">new</span>&nbsp;HandlerThread(<span style="color: #800000">&quot;IntentService[&quot;</span>&nbsp;+ mName +&nbsp;<span style="color: #800000">&quot;]&quot;</span>);&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;thread.start();&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mServiceLooper = thread.getLooper();&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mServiceHandler =&nbsp;<span style="color: #0000ff">new</span>&nbsp;ServiceHandler(mServiceLooper);&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div></div>分析:IntentService创建时就会创建Handler线程(HandlerThread)并且启动,然后再得到当前线程的Looper对象来初始化IntentService的mServiceLooper,接着创建mServicehandler对象.<br />&nbsp;</div><div><br />&nbsp;</div><div>下面是onStart()的源码:</div><div><div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff">public</span>&nbsp;<span style="color: #0000ff">void</span>&nbsp;onStart(Intent intent,&nbsp;<span style="color: #0000ff">int</span>&nbsp;startId) {&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Message msg = mServiceHandler.obtainMessage();&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg.arg1 = startId;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;msg.obj = intent;&nbsp;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mServiceHandler.sendMessage(msg);&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div></div>分析:当你启动IntentService的时候,就会产生一条附带startId和Intent的Message并发送到MessageQueue中,接下来Looper发现MessageQueue中有Message的时候,就会停止Handler处理消息,接下来处理的代码如下:</div><div><div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff">public</span>&nbsp;<span style="color: #0000ff">void</span>&nbsp;handleMessage(Message msg) {&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;onHandleIntent((Intent)msg.obj);&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stopSelf(msg.arg1);&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div></div>接着调用 onHandleIntent((Intent)msg.obj),这是一个抽象的方法,其实就是我们要重写实现的方法,我们可以在这个方法里面处理我们的工作.当任务完成时就会调用stopSelf(msg.arg1)这个方法来结束指定的工作.</div><div><br />当所有的工作执行完后:就会执行onDestroy方法,源码如下:<div><div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@Override&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000ff">public</span>&nbsp;<span style="color: #0000ff">void</span>&nbsp;onDestroy() {&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mServiceLooper.quit();&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</div></div>服务结束后调用这个方法 mServiceLooper.quit()使looper停下来.<br /><br /><br />通过对源码的分析得出:<br />&nbsp; &nbsp; 这是一个基于消息的服务,每次启动该服务并不是马上处理你的工作,而是首先会创建对应的Looper,Handler并且在MessageQueue中添加的附带客户Intent的Message对象,当Looper发现有Message的时候接着得到Intent对象通过在onHandleIntent((Intent)msg.obj)中调用你的处理程序.处理完后即会停止自己的服务.意思是Intent的生命周期跟你的处理的任务是一致的.所以这个类用下载任务中非常好,下载任务结束后服务自身就会结束退出</div><p>Copyright © 2008 www.spridu.cn</p><p><a href="http://www.spridu.cn/article/android-dev/2011/11/24/androidDeIntentServiceYuanMaFenXi.shtml" target="_blank">继续阅读《android的IntentService源码分析》的全文内容...</a></p><p>分类: <a href="http://www.spridu.cn/android-dev.shtml">Android</a> | Tags: <a href="http://www.spridu.cn/catalog.asp?tags=Android">Android</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=IntentService%E5%86%85%E9%83%A8%E5%8E%9F%E7%90%86">IntentService内部原理</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=IntentService%E8%BF%90%E8%A1%8C%E6%9C%BA%E5%88%B6">IntentService运行机制</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=IntentService%E6%BA%90%E7%A0%81%E7%A0%94%E7%A9%B6">IntentService源码研究</a>&nbsp;&nbsp; | <a href="http://www.spridu.cn/article/android-dev/2011/11/24/androidDeIntentServiceYuanMaFenXi.shtml#comment" target="_blank">添加评论</a>(2)</p><h3>相关文章:</h3><ul><li><a href="http://www.spridu.cn/article/javaweb/2012/01/10/jvm-c++-android-dalvik-call.shtml">如何使用c++来操作jvm并调取java类</a> (2012-1-10 15:53:54)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/12/07/AndroidKuaJinCongChuanDiParcelYuanLiJieXi.shtml">Android跨进程传递Parcel原理解析</a> (2011-12-7 11:53:55)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/12/07/androidZhongZiDingYi-soDongTaiKuDeWeiZhi.shtml">android中自定义.so动态库的位置</a> (2011-12-7 11:28:32)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/11/15/RuHeZaiandroidDedataWenJianXiTongZhongChuangJianWenJianYiJiMuLu.shtml">如何在android的data文件系统中创建文件以及目录</a> (2011-11-15 15:15:34)  </li><li><a href="http://www.spridu.cn/article/j2me/2011/11/14/J2meHeAndroidDeChaBie.shtml">J2me和Android的差别</a> (2011-11-14 10:36:29)  </li></ul><hr /> <h3>最新评论:</h3><ul><li><a href="http://www.spridu.cn/article/android-dev/2011/11/24/androidDeIntentServiceYuanMaFenXi.shtml#cmt891">2011-11-28 14:22:6</a>，<a href="http://www.mbaow.com">女士包包</a> ： 熟悉源代码，才能开发好软件！</li>, <li><a href="%article_url%">%article_title%</a> (%article_time%)</li><li><a href="http://www.spridu.cn/article/android-dev/2011/11/24/androidDeIntentServiceYuanMaFenXi.shtml#cmt890">2011-11-28 13:54:47</a>，<a href="http://www.xitoo.cn">厨房电器</a> ： 学习了，这个源码不是很懂！</li>, <li><a href="%article_url%">%article_title%</a> (%article_time%)</li></ul>]]></description><category>Android</category><comments>http://www.spridu.cn/article/android-dev/2011/11/24/androidDeIntentServiceYuanMaFenXi.shtml#comment</comments><wfw:comment>http://www.spridu.cn/</wfw:comment><wfw:commentRss>http://www.spridu.cn/feed.asp?cmt=350</wfw:commentRss><trackback:ping>http://www.spridu.cn/cmd.asp?act=tb&amp;id=350&amp;key=457e842f</trackback:ping></item><item><title>解决JEM2-Errors running builder 'Preverification' on project</title><author>admin@spridu.cn (spridu)</author><link>http://www.spridu.cn/article/j2me/2011/11/16/JieJueJEM2-Errors-running-builder-Preverification-on-project.shtml</link><pubDate>Wed, 16 Nov 2011 11:39:00 +0800</pubDate><guid>http://www.spridu.cn/article/j2me/2011/11/16/JieJueJEM2-Errors-running-builder-Preverification-on-project.shtml</guid><description><![CDATA[<p>&nbsp;其实这个错误已经提示出来了，根据错误的提示修改下就行了，但是我看了下网上的说要重装eclipse，感觉没那么严重吧。</p><p><span class="Apple-style-span" style="font-family: simsun; font-size: 14px; line-height: 23px; ">Errors occurred during the build.</span><br style="font-family: simsun; font-size: 14px; line-height: 23px; text-align: left; " /><span class="Apple-style-span" style="font-family: simsun; font-size: 14px; line-height: 23px; text-align: left; ">&nbsp; Errors running builder 'Preverification' on project 'M'.</span><br style="font-family: simsun; font-size: 14px; line-height: 23px; text-align: left; " /><span class="Apple-style-span" style="font-family: simsun; font-size: 14px; line-height: 23px; text-align: left; ">&nbsp; Illegal Manifest Entry Key or Value &quot;E:\eclipseWorkSpace\M\.eclipseme.tmp\emulation\M.jar (系统找不到指定的路径。)&quot;</span><br style="font-family: simsun; font-size: 14px; line-height: 23px; text-align: left; " /><span class="Apple-style-span" style="font-family: simsun; font-size: 14px; line-height: 23px; text-align: left; ">&nbsp; E:\eclipseWorkSpace\M\.eclipseme.tmp\emulation\M.jar (系统找不到指定的路径。)</span><br style="font-family: simsun; font-size: 14px; line-height: 23px; text-align: left; " /><span class="Apple-style-span" style="font-family: simsun; font-size: 14px; line-height: 23px; text-align: left; ">&nbsp; Illegal Manifest Entry Key or Value &quot;E:\eclipseWorkSpace\M\.eclipseme.tmp\emulation\M.jar (系统找不到指定的路径。)&quot;</span><br style="font-family: simsun; font-size: 14px; line-height: 23px; text-align: left; " /><span class="Apple-style-span" style="font-family: simsun; font-size: 14px; line-height: 23px; text-align: left; ">&nbsp; E:\eclipseWorkSpace\M\.eclipseme.tmp\emulation\M.jar (系统找不到指定的路径。)</span></p><p>解决方法: 打开&nbsp;<span class="Apple-style-span" style="font-family: simsun; font-size: 14px; line-height: 23px; ">E:\eclipseWorkSpace\M\.eclipseme.tmp\ 创建</span><span class="Apple-style-span" style="font-family: simsun; font-size: 14px; line-height: 23px; ">emulation文件夹 就行了。这个是eclipseMe的Bug.</span></p><p>Copyright © 2008 www.spridu.cn</p><p><a href="http://www.spridu.cn/article/j2me/2011/11/16/JieJueJEM2-Errors-running-builder-Preverification-on-project.shtml" target="_blank">继续阅读《解决JEM2-Errors running builder 'Preverification' on project》的全文内容...</a></p><p>分类: <a href="http://www.spridu.cn/j2me.shtml">J2me</a> | Tags: <a href="http://www.spridu.cn/catalog.asp?tags=Preverification">Preverification</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=J2ME">J2ME</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=errors">errors</a>&nbsp;&nbsp; | <a href="http://www.spridu.cn/article/j2me/2011/11/16/JieJueJEM2-Errors-running-builder-Preverification-on-project.shtml#comment" target="_blank">添加评论</a>(1)</p><h3>相关文章:</h3><ul><li><a href="http://www.spridu.cn/article/j2me/2011/11/14/J2meHeAndroidDeChaBie.shtml">J2me和Android的差别</a> (2011-11-14 10:36:29)  </li><li><a href="http://www.spridu.cn/article/j2me/2011/10/21/Connection-Already-Open-j2me.shtml">解决J2ME中的ConnectionAlreadyOpen现象</a> (2011-10-21 9:59:27)  </li><li><a href="http://www.spridu.cn/article/j2me/2010/05/10/20100510516.shtml">java手机短信软件开发以及源码分析</a> (2010-5-10 16:50:23)  </li></ul><hr /> <h3>最新评论:</h3><ul><li><a href="http://www.spridu.cn/article/j2me/2011/11/16/JieJueJEM2-Errors-running-builder-Preverification-on-project.shtml#cmt887">2011-11-18 21:8:15</a>，<a href="http://www.bai-yun.net">gxg官网</a> ： 1dt1zp明天你还会更新的吧  明天我在来</li>, <li><a href="%article_url%">%article_title%</a> (%article_time%)</li></ul>]]></description><category>J2me</category><comments>http://www.spridu.cn/article/j2me/2011/11/16/JieJueJEM2-Errors-running-builder-Preverification-on-project.shtml#comment</comments><wfw:comment>http://www.spridu.cn/</wfw:comment><wfw:commentRss>http://www.spridu.cn/feed.asp?cmt=349</wfw:commentRss><trackback:ping>http://www.spridu.cn/cmd.asp?act=tb&amp;id=349&amp;key=88248936</trackback:ping></item><item><title>如何在android的data文件系统中创建文件以及目录</title><author>admin@spridu.cn (spridu)</author><link>http://www.spridu.cn/article/android-dev/2011/11/15/RuHeZaiandroidDedataWenJianXiTongZhongChuangJianWenJianYiJiMuLu.shtml</link><pubDate>Tue, 15 Nov 2011 15:15:34 +0800</pubDate><guid>http://www.spridu.cn/article/android-dev/2011/11/15/RuHeZaiandroidDedataWenJianXiTongZhongChuangJianWenJianYiJiMuLu.shtml</guid><description><![CDATA[<p>&nbsp;&nbsp;/data/data/&lt;package name&gt; 是当前应用程序私有的，可以供当前的应用程序操作。/data/data/&lt;package name&gt;目录的权限为rwxr-xr-x，拆解:</p><div style="padding-top: 5px; padding-right: 5px; padding-bottom: 5px; padding-left: 5px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; line-height: 160%; "><p>本应用程序:rwx</p><p>具有sharedUserId的应用程序:r-x</p><p>其他的应用程序:r-x&nbsp;</p><p>这样一来说明自己可以执行任何操作，初次之外其他的应用程序可以查看和执行里面的文件夹内容，android系统给我们自带了一些特殊意义的文件夹比如caches files lib sharepreference等。</p><p>不过我们可以像操作sdcard一样操作&nbsp;/data/data/&lt;package name&gt;下面的内容，因为对于现在的应用程序来说这个目录已经是自己可以操作的一小部分私有可控权限的文件系统，代码如下：</p><p>&nbsp;</p><p>&nbsp; &nbsp; &nbsp; &nbsp;File file = new File(getFilesDir()+&quot;/test/a&quot;);</p><p>&nbsp; &nbsp; &nbsp; &nbsp; if(!file.exists()){</p><p>&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<span class="Apple-tab-span" style="white-space: pre; ">	</span>file.mkdirs();</p><p>&nbsp; &nbsp; &nbsp; &nbsp; }</p><p>这样就在&nbsp;/data/data/&lt;package name&gt;/files/test/a创建了。初次之外还可以创建&nbsp;/data/data/&lt;package name&gt;/hello/a/等 还可以写文件，只需要把他当做sdcard用。</p><p>&nbsp;</p></div><p>Copyright © 2008 www.spridu.cn</p><p><a href="http://www.spridu.cn/article/android-dev/2011/11/15/RuHeZaiandroidDedataWenJianXiTongZhongChuangJianWenJianYiJiMuLu.shtml" target="_blank">继续阅读《如何在android的data文件系统中创建文件以及目录》的全文内容...</a></p><p>分类: <a href="http://www.spridu.cn/android-dev.shtml">Android</a> | Tags: <a href="http://www.spridu.cn/catalog.asp?tags=Android">Android</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=%2Fdata%2Fdata%2F">/data/data/</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=%E5%88%9B%E5%BB%BA%E7%9B%AE%E5%BD%95">创建目录</a>&nbsp;&nbsp; | <a href="http://www.spridu.cn/article/android-dev/2011/11/15/RuHeZaiandroidDedataWenJianXiTongZhongChuangJianWenJianYiJiMuLu.shtml#comment" target="_blank">添加评论</a>(0)</p><h3>相关文章:</h3><ul><li><a href="http://www.spridu.cn/article/javaweb/2012/01/10/jvm-c++-android-dalvik-call.shtml">如何使用c++来操作jvm并调取java类</a> (2012-1-10 15:53:54)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/12/07/AndroidKuaJinCongChuanDiParcelYuanLiJieXi.shtml">Android跨进程传递Parcel原理解析</a> (2011-12-7 11:53:55)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/12/07/androidZhongZiDingYi-soDongTaiKuDeWeiZhi.shtml">android中自定义.so动态库的位置</a> (2011-12-7 11:28:32)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/11/24/androidDeIntentServiceYuanMaFenXi.shtml">android的IntentService源码分析</a> (2011-11-24 11:29:26)  </li><li><a href="http://www.spridu.cn/article/j2me/2011/11/14/J2meHeAndroidDeChaBie.shtml">J2me和Android的差别</a> (2011-11-14 10:36:29)  </li></ul>]]></description><category>Android</category><comments>http://www.spridu.cn/article/android-dev/2011/11/15/RuHeZaiandroidDedataWenJianXiTongZhongChuangJianWenJianYiJiMuLu.shtml#comment</comments><wfw:comment>http://www.spridu.cn/</wfw:comment><wfw:commentRss>http://www.spridu.cn/feed.asp?cmt=348</wfw:commentRss><trackback:ping>http://www.spridu.cn/cmd.asp?act=tb&amp;id=348&amp;key=77eb0bde</trackback:ping></item><item><title>J2me和Android的差别</title><author>admin@spridu.cn (spridu)</author><link>http://www.spridu.cn/article/j2me/2011/11/14/J2meHeAndroidDeChaBie.shtml</link><pubDate>Mon, 14 Nov 2011 10:36:29 +0800</pubDate><guid>http://www.spridu.cn/article/j2me/2011/11/14/J2meHeAndroidDeChaBie.shtml</guid><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Android深度抄袭并改造了J2ME,先来说下J2ME,在J2ME里面，控件分为高级控件和低级的画布,原因在于什么地方？在于应用的两个方向，高级的控件主要应用于常规的软件开发一些实用性的软件，对于这样的软件对UI的要求比较有规则，不像游戏。对于这些规则性的软件，J2ME就需要提供一些规则性的API来方便开发者的调用，但又不能过于简单，要有很强的可塑性。对于游戏这类的界面，常规的组件反而会成为一种瓶颈，原因在于游戏的画面更新的太快，不仅如此样式变化的也很快，所以对于这类组件就必须用画布来解决，将组件的具体展示交给程序，让程序去控制。在实现方面，高级的组件内部是使用</p><div>画布来实现的，只不过这类组件是静态的(和游戏比)，所以说游戏的画布更底层，也就是更难控制，但是更容易满足需求。android也是如此，我们平时使用的TextView还有ImageView等都是高级组件，这些组件内部上使用画布来做的，也称为&quot;静态组件&quot;,如果想用在android上则必须使用Canvas来做。腾讯的自己UI有两种可能，一是修改高级控件(android的高级控件可塑性很强)，二是使用Canvas自己画静态组件。但是通过反编译源代码来看主要是使用Canvas来做。</div><div>&nbsp; &nbsp; &nbsp; &nbsp; 除此之外，在处理图片资源上面,J2ME生成的.res的文件，而android上则是.arsc(android resource) 。Android抓住了J2ME的漏洞Midlet的限制 制作出了Activity。</div><p>Copyright © 2008 www.spridu.cn</p><p><a href="http://www.spridu.cn/article/j2me/2011/11/14/J2meHeAndroidDeChaBie.shtml" target="_blank">继续阅读《J2me和Android的差别》的全文内容...</a></p><p>分类: <a href="http://www.spridu.cn/j2me.shtml">J2me</a> | Tags: <a href="http://www.spridu.cn/catalog.asp?tags=Android">Android</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=J2ME">J2ME</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=%E7%BB%84%E4%BB%B6%E4%BB%A5%E5%8F%8A%E9%AB%98%E7%BA%A7%E7%94%BB%E5%B8%83">组件以及高级画布</a>&nbsp;&nbsp; | <a href="http://www.spridu.cn/article/j2me/2011/11/14/J2meHeAndroidDeChaBie.shtml#comment" target="_blank">添加评论</a>(0)</p><h3>相关文章:</h3><ul><li><a href="http://www.spridu.cn/article/javaweb/2012/01/10/jvm-c++-android-dalvik-call.shtml">如何使用c++来操作jvm并调取java类</a> (2012-1-10 15:53:54)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/12/07/AndroidKuaJinCongChuanDiParcelYuanLiJieXi.shtml">Android跨进程传递Parcel原理解析</a> (2011-12-7 11:53:55)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/12/07/androidZhongZiDingYi-soDongTaiKuDeWeiZhi.shtml">android中自定义.so动态库的位置</a> (2011-12-7 11:28:32)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/11/24/androidDeIntentServiceYuanMaFenXi.shtml">android的IntentService源码分析</a> (2011-11-24 11:29:26)  </li><li><a href="http://www.spridu.cn/article/j2me/2011/11/16/JieJueJEM2-Errors-running-builder-Preverification-on-project.shtml">解决JEM2-Errors running builder 'Preverification' on project</a> (2011-11-16 11:39:0)  </li></ul>]]></description><category>J2me</category><comments>http://www.spridu.cn/article/j2me/2011/11/14/J2meHeAndroidDeChaBie.shtml#comment</comments><wfw:comment>http://www.spridu.cn/</wfw:comment><wfw:commentRss>http://www.spridu.cn/feed.asp?cmt=347</wfw:commentRss><trackback:ping>http://www.spridu.cn/cmd.asp?act=tb&amp;id=347&amp;key=a122f78a</trackback:ping></item><item><title>解决Android中使用Handler发生的异常</title><author>admin@spridu.cn (spridu)</author><link>http://www.spridu.cn/article/android-dev/2011/11/14/JieJueAndroidZhongShiYongHandlerFaShengDeYiChang.shtml</link><pubDate>Mon, 14 Nov 2011 10:28:26 +0800</pubDate><guid>http://www.spridu.cn/article/android-dev/2011/11/14/JieJueAndroidZhongShiYongHandlerFaShengDeYiChang.shtml</guid><description><![CDATA[<p>&nbsp;在开发android的时候会发生这样的异常,异常信息显示如下:</p><p><span class="Apple-style-span" style="color: rgb(68, 68, 68); font-family: ΢; font-size: 14px; line-height: 21px; ">&rdquo;This message is already in use&ldquo;</span></p><p>发生的原因: 使用Message的时候发生了多次使用，也就是Message对象是线程安全的，当我们再次使用Message的时候，Message已经处在队列中了</p><p>而队列中存放的是Message的一个引用，所以我们使用了和队列中一样的Message.</p><p>解决办法:</p><p>&nbsp; &nbsp; &nbsp; &nbsp; mhandler.obtainMessage(); //Exception:This message is already in use</p><p>在使用Message前重新从Message缓冲池中取得一个不重复的Message。</p><p>Copyright © 2008 www.spridu.cn</p><p><a href="http://www.spridu.cn/article/android-dev/2011/11/14/JieJueAndroidZhongShiYongHandlerFaShengDeYiChang.shtml" target="_blank">继续阅读《解决Android中使用Handler发生的异常》的全文内容...</a></p><p>分类: <a href="http://www.spridu.cn/android-dev.shtml">Android</a> | Tags: <a href="http://www.spridu.cn/catalog.asp?tags=Android">Android</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=handler">handler</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=Exception">Exception</a>&nbsp;&nbsp;<a href="http://www.spridu.cn/catalog.asp?tags=This+message+is+already+in+use">This message is already in use</a>&nbsp;&nbsp; | <a href="http://www.spridu.cn/article/android-dev/2011/11/14/JieJueAndroidZhongShiYongHandlerFaShengDeYiChang.shtml#comment" target="_blank">添加评论</a>(0)</p><h3>相关文章:</h3><ul><li><a href="http://www.spridu.cn/article/javaweb/2012/01/10/jvm-c++-android-dalvik-call.shtml">如何使用c++来操作jvm并调取java类</a> (2012-1-10 15:53:54)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/12/07/AndroidKuaJinCongChuanDiParcelYuanLiJieXi.shtml">Android跨进程传递Parcel原理解析</a> (2011-12-7 11:53:55)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/12/07/androidZhongZiDingYi-soDongTaiKuDeWeiZhi.shtml">android中自定义.so动态库的位置</a> (2011-12-7 11:28:32)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/11/24/androidDeIntentServiceYuanMaFenXi.shtml">android的IntentService源码分析</a> (2011-11-24 11:29:26)  </li><li><a href="http://www.spridu.cn/article/android-dev/2011/11/15/RuHeZaiandroidDedataWenJianXiTongZhongChuangJianWenJianYiJiMuLu.shtml">如何在android的data文件系统中创建文件以及目录</a> (2011-11-15 15:15:34)  </li></ul>]]></description><category>Android</category><comments>http://www.spridu.cn/article/android-dev/2011/11/14/JieJueAndroidZhongShiYongHandlerFaShengDeYiChang.shtml#comment</comments><wfw:comment>http://www.spridu.cn/</wfw:comment><wfw:commentRss>http://www.spridu.cn/feed.asp?cmt=346</wfw:commentRss><trackback:ping>http://www.spridu.cn/cmd.asp?act=tb&amp;id=346&amp;key=254f6bbb</trackback:ping></item></channel></rss>

