Android 中使用TCP、UDP协议

使用TCP通信服务器步骤 1、调用ServerSocket(int port) 创建一个ServerSocket,并绑定到指定端口上 2、调用accept(),监听连接请求,如果客户端请求连接,则接受连接,返回通信套接字 3、调用Socket的getInputStream()和getOutputStream()获得输入和输出流,开始网络数据的发送和接收。 4、关闭通信套接字。 例如: //创建一个ServerSocket ServerSocket serverSocket=null; try{ //TCP_SERVER_PORT为指定的绑定端口,为into类型 serverSocket=new ServerSocket(TCP_SERVER_PORT); //监听连接请求 Socket socket=serverSocket.accept(); //写入读Buffer中 BufferReader in=new BufferReader( //获得输入流 new InputStreamReader(socket.getInputStream()) ); //放到写Buffer中 BufferWriter out=new BufferWriter(new OutputStreamWriter(socket.getOutputStream())); //读取接收信息,转换为字符串 String incomingMsg=in.readerLine()+System.getProperty(“line.separator”); //生成发送字符串 String outGoingMsg=”goodbye from port “+TCP_SERVER+PORT+System.getProperty(“line.separator”); //将发送字符串写入上面定义的BufferWriter中 out.write(outGoingMsg); //刷新 发送 out.flush(); //关闭 socket.close(); }catch(InterruptedIOException e){ //超时错误 e.printStackTrace(); }catch(IOException e){//IO异常 e.printStackTrace(); }finally{//判定是否初始化ServerSocket对象,如果初始化则关闭ServerSocket if(serverSocket!=null){ try{ serverSocket.close(); }catch(IOExcetion e){ e.printStackTrace(); } } } 使用TCP通信客户端步骤 1、调用Socket()创建一个Socket(套接字),并绑定到指定服务端口上。 2、调用Socket的getInputStream()和getOutputStream()获得输入和输出流,开始网络数据的发送和接收。 3、关闭通信套接字。 例如: try{ //初始化Socket,TCP_SERVER_PORT为指定的服务器端口(int类型) Socket socket=new Socket(“Ip/website”,TCP_SERVER_PORT); //获得输入流 BufferReader in=new BufferReader(new InputStreamReader(socket.getInputStream())); //生成输出流 BufferWriter out=new BufferWriter(new OutputStreamWriter(socket.getOutputStream())); //生成发送字符串 String outGoingMsg=”goodbye from port “+TCP_SERVER+PORT+System.getProperty(“line.separator”); //将发送字符串写入上面定义的BufferWriter中 out.write(outGoingMsg); //刷新 发送 out.flush(); //读取接收信息,转换为字符串 String incomingMsg=in.readerLine()+System.getProperty(“line.separator”); //关闭 socket.close(); }catch(UnknownHostException e){ //超时错误 e.printStackTrace(); }catch(IOException e){//IO异常 e.printStackTrace(); } 使用UDP通信服务器步骤 1、调用DatagramSocket(int port) 创建一个数据报套接字,并绑定到指定端口上 2、调用DatagramPacket(byte[] buf,int length),建立一个字节数组以接收UDP包。 3、调用DatagramSocket的receive(),接受UDP包。 4、关闭数据报套接字。 例如: //接收的字节大小,客户端发送的数据不能超过MAX_UDP_DATAGRAM_LEN byte[] lMsg=new byte[MAX_UDP_DATAGRAM_LEN]; //实例化一个DatagramPacket DatagramPacket dp=new DatagramPacket(lMsg,lMsg.length); //创建一个DatagramSocket DatagramSocket ds=null; try{ //UDP_SERVER_PORT为指定的绑定端口,为into类型 ds=new DatagramSocket(UDP_SERVER_PORT); //准备接收数据 ds.receive(dp); }catch(SocketException e){ //超时错误 e.printStackTrace(); }catch(IOException e){//IO异常 e.printStackTrace(); }finally{//如果ds对象不为空,则关闭ds对象 if(ds!=null){ ds.close(); } ...

2015年1月26日 · 1 分钟 · 天边的星星

微信公众平台开发(71)OAuth2.0网页授权

微信公众平台开发 OAuth2.0网页授权认证 网页授权获取用户基本信息 作者:方倍工作室 微信公众平台最近新推出微信认证,认证后可以获得高级接口权限,其中一个是OAuth2.0网页授权,很多朋友在使用这个的时候失败了或者无法理解其内容,希望我出个教程详细讲解一下,于是便有了这篇文章。 一、什么是OAuth2.0 官方网站:http://oauth.net/ http://oauth.net/2/ 权威定义:OAuth is An open protocol to allow secure authorization in a simple and standard method from web, mobile and desktop applications. OAuth是一个开放协议,允许用户让第三方应用以安全且标准的方式获取该用户在某一网站、移动或桌面应用上存储的私密的资源(如用户个人信息、照片、视频、联系人列表),而无需将用户名和密码提供给第三方应用。 OAuth 2.0是OAuth协议的下一版本,但不向后兼容OAuth 1.0。 OAuth 2.0关注客户端开发者的简易性,同时为Web应用,桌面应用和手机,和起居室设备提供专门的认证流程。 OAuth允许用户提供一个令牌,而不是用户名和密码来访问他们存放在特定服务提供者的数据。每一个令牌授权一个特定的网站(例如,视频编辑网站)在特定的时段(例如,接下来的2小时内)内访问特定的资源(例如仅仅是某一相册中的视频)。这样,OAuth允许用户授权第三方网站访问他们存储在另外的服务提供者上的信息,而不需要分享他们的访问许可或他们数据的所有内容。 新浪微博API目前也使用OAuth 2.0。 原文:http://www.cnblogs.com/txw1958/p/weixin71-oauth20.html 二、微信公众平台OAuth2.0授权 微信公众平台OAuth2.0授权详细步骤如下: 用户关注微信公众账号。 微信公众账号提供用户请求授权页面URL。 用户点击授权页面URL,将向服务器发起请求 服务器询问用户是否同意授权给微信公众账号(scope为snsapi_base时无此步骤) 用户同意(scope为snsapi_base时无此步骤) 服务器将CODE通过回调传给微信公众账号 微信公众账号获得CODE 微信公众账号通过CODE向服务器请求Access Token 服务器返回Access Token和OpenID给微信公众账号 微信公众账号通过Access Token向服务器请求用户信息(scope为snsapi_base时无此步骤) 服务器将用户信息回送给微信公众账号(scope为snsapi_base时无此步骤) 使用的AppId和AppSecret在开发者中心-开发者ID中,可以找到。 1. 配置授权回调页面域名 进入微信公众平台后台后,依次进入开发者中心-权限表,找到网页授权获取用户基本信息, 点击右侧的修改。原文:http://www.cnblogs.com/txw1958/p/weixin71-oauth20.html 授权回调域名配置规范为全域名并且不带http,比如需要网页授权的域名为:www.qq.com,配置以后此域名下面的页面http://www.qq.com/music.html 、 http://www.qq.com/login.html 都可以进行OAuth2.0鉴权。但http://pay.qq.com 、 http://music.qq.com 、 http://qq.com无法进行OAuth2.0鉴权。 这里我们填写方倍工作室的一个百度应用二级域名为 mascot.duapp.com ...

2015年1月22日 · 2 分钟 · 天边的星星

Android 使用开源库StickyGridHeaders来实现带sections和headers的GridView显示本地图片效果

转载请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/20481185),请尊重他人的辛勤劳动成果,谢谢! 大家好!过完年回来到现在差不多一个月没写文章了,一是觉得不知道写哪些方面的文章,没有好的题材来写,二是因为自己的一些私事给耽误了,所以过完年的第一篇文章到现在才发表出来,2014年我还是会继续在CSDN上面更新我的博客,欢迎大家关注一下,今天这篇文章主要的是介绍下开源库StickyGridHeaders的使用,StickyGridHeaders是一个自定义GridView带sections和headers的Android库,sections就是GridView item之间的分隔,headers就是固定在GridView顶部的标题,类似一些Android手机联系人的效果,StickyGridHeaders的介绍在https://github.com/TonicArtos/StickyGridHeaders,与此对应也有一个相同效果的自定义ListView带sections和headers的开源库https://github.com/emilsjolander/StickyListHeaders,大家有兴趣的可以去看下,我这里介绍的是StickyGridHeaders的使用,我在Android应用方面看到使用StickyGridHeaders的不是很多,而是在Iphone上看到相册采用的是这种效果,于是我就使用StickyGridHeaders来仿照Iphone按照日期分隔显示本地图片 我们先新建一个Android项目StickyHeaderGridView,去https://github.com/TonicArtos/StickyGridHeaders下载开源库,为了方便浏览源码我直接将源码拷到我的工程中了 com.tonicartos.widget.stickygridheaders这个包就是我放StickyGridHeaders开源库的源码,com.example.stickyheadergridview这个包是我实现此功能的代码,类看起来还蛮多的,下面我就一一来介绍了 GridItem用来封装StickyGridHeadersGridView 每个Item的数据,里面有本地图片的路径,图片加入手机系统的时间和headerId **[java]** [view plain](http://blog.csdn.net/xiaanming/article/details/20481185#)[copy](http://blog.csdn.net/xiaanming/article/details/20481185#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/220204)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/220204/fork) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="keyword">package</span> com.example.stickyheadergridview; - <span class="comment">/**</span> - <span class="comment"> * @blog http://blog.csdn.net/xiaanming</span> - <span class="comment"> * </span> - <span class="comment"> * @author xiaanming</span> - <span class="comment"> *</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">class</span> GridItem { - <span class="comment">/**</span> - <span class="comment"> * 图片的路径</span> - <span class="comment"> */</span> - <span class="keyword">private</span> String path; - <span class="comment">/**</span> - <span class="comment"> * 图片加入手机中的时间,只取了年月日</span> - <span class="comment"> */</span> - <span class="keyword">private</span> String time; - <span class="comment">/**</span> - <span class="comment"> * 每个Item对应的HeaderId</span> - <span class="comment"> */</span> - <span class="keyword">private</span> <span class="keyword">int</span> headerId; - - <span class="keyword">public</span> GridItem(String path, String time) { - <span class="keyword">super</span>(); - <span class="keyword">this</span>.path = path; - <span class="keyword">this</span>.time = time; - } - - <span class="keyword">public</span> String getPath() { - <span class="keyword">return</span> path; - } - <span class="keyword">public</span> <span class="keyword">void</span> setPath(String path) { - <span class="keyword">this</span>.path = path; - } - <span class="keyword">public</span> String getTime() { - <span class="keyword">return</span> time; - } - <span class="keyword">public</span> <span class="keyword">void</span> setTime(String time) { - <span class="keyword">this</span>.time = time; - } - - <span class="keyword">public</span> <span class="keyword">int</span> getHeaderId() { - <span class="keyword">return</span> headerId; - } - - <span class="keyword">public</span> <span class="keyword">void</span> setHeaderId(<span class="keyword">int</span> headerId) { - <span class="keyword">this</span>.headerId = headerId; - } - - - } 图片的路径path和图片加入的时间time 我们直接可以通过ContentProvider获取,但是headerId需要我们根据逻辑来生成。 ...

2015年1月20日 · 13 分钟 · 天边的星星

Android学习小Demo(23)Aidl实现进程间通信

我们知道,Android是靠Binder机制来实现进程间的通信,而上一篇文章中,我们利用AIDL,简单地从代码方面的角度讲解了在服务端中的Binder的存在形式,是以服务的实现存在的,而在客户端,则是以代理的形式,实现存在的只是一个关于服务端的Binder实现的引用。 理论上的东西我们要去学习掌握,但是也不能忽略了实际的动手能力,对吧。 今天,我们就一步一步地利用我们所了解地关于AIDL的知识来实现一个跨进程通信的例子。 在Android的上层应用中,每一个App都是一个单独的进程,所以,要实现跨进程通信,我们需要至少有2个进程,一个代表服务端,一个代表客户端,所以我们会创建2个项目,来分别代表服务端和客户端。 服务端是提供服务的,得先提供服务,才能让客户端来享受服务,对吧。 服务端 我们创建一个服务端的项目,然后创建我们的aidl文件,毕竟只是一个Demo,所以我先从简单入手,方法不要太多,就叫IDemoService.aidl, 如下: **[java]** [view plain](http://blog.csdn.net/linmiansheng/article/details/42835229#)[copy](http://blog.csdn.net/linmiansheng/article/details/42835229#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/582805)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/582805/fork) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="keyword">package</span> com.lms.service; - - <span class="keyword">interface</span> IDemoService { - <span class="keyword">void</span> invoke(); - } 我们将其放在com.lms.service的包名目录下,表明其是提供服务的,当我们编译一下项目之后,就会发现在gen目录下面同样的包名下,生成了一个IDemoService.java的文件,如下: 而其生成的IDemoService.java文件内容如下,跟上一篇文章中所展现的其实一样,就是一个Stub类和一个Proxy类,如下: **[java]** [view plain](http://blog.csdn.net/linmiansheng/article/details/42835229#)[copy](http://blog.csdn.net/linmiansheng/article/details/42835229#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/582805)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/582805/fork) <div> <embed id="ZeroClipboardMovie_2" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_2"> </embed> </div> </div> - <span class="comment">/*</span> - <span class="comment"> * This file is auto-generated. DO NOT MODIFY.</span> - <span class="comment"> * Original file: F:\\workspace_android\\AidlDemoClient\\src\\com\\lms\\service\\IDemoService.aidl</span> - <span class="comment"> */</span> - <span class="keyword">package</span> com.lms.service; - - <span class="keyword">public</span> <span class="keyword">interface</span> IDemoService <span class="keyword">extends</span> android.os.IInterface { - <span class="comment">/** Local-side IPC implementation stub class. */</span> - <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">abstract</span> <span class="keyword">class</span> Stub <span class="keyword">extends</span> android.os.Binder <span class="keyword">implements</span> - com.lms.service.IDemoService { - <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> java.lang.String DESCRIPTOR = <span class="string">&#8220;com.lms.service.IDemoService&#8221;</span>; - - <span class="comment">/** Construct the stub at attach it to the interface. */</span> - <span class="keyword">public</span> Stub() { - <span class="keyword">this</span>.attachInterface(<span class="keyword">this</span>, DESCRIPTOR); - } - - <span class="comment">/**</span> - <span class="comment"> * Cast an IBinder object into an com.lms.service.IDemoService</span> - <span class="comment"> * interface, generating a proxy if needed.</span> - <span class="comment"> */</span> - <span class="keyword">public</span> <span class="keyword">static</span> com.lms.service.IDemoService asInterface( - android.os.IBinder obj) { - <span class="keyword">if</span> ((obj == <span class="keyword">null</span>)) { - <span class="keyword">return</span> <span class="keyword">null</span>; - } - android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR); - <span class="keyword">if</span> (((iin != <span class="keyword">null</span>) && (iin <span class="keyword">instanceof</span> com.lms.service.IDemoService))) { - <span class="keyword">return</span> ((com.lms.service.IDemoService) iin); - } - <span class="keyword">return</span> <span class="keyword">new</span> com.lms.service.IDemoService.Stub.Proxy(obj); - } - - <span class="annotation">@Override</span> - <span class="keyword">public</span> android.os.IBinder asBinder() { - <span class="keyword">return</span> <span class="keyword">this</span>; - } - - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">boolean</span> onTransact(<span class="keyword">int</span> code, android.os.Parcel data, - android.os.Parcel reply, <span class="keyword">int</span> flags) - <span class="keyword">throws</span> android.os.RemoteException { - <span class="keyword">switch</span> (code) { - <span class="keyword">case</span> INTERFACE_TRANSACTION: { - reply.writeString(DESCRIPTOR); - <span class="keyword">return</span> <span class="keyword">true</span>; - } - <span class="keyword">case</span> TRANSACTION_invoke: { - data.enforceInterface(DESCRIPTOR); - <span class="keyword">this</span>.invoke(); - reply.writeNoException(); - <span class="keyword">return</span> <span class="keyword">true</span>; - } - } - <span class="keyword">return</span> <span class="keyword">super</span>.onTransact(code, data, reply, flags); - } - - <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">class</span> Proxy <span class="keyword">implements</span> com.lms.service.IDemoService { - <span class="keyword">private</span> android.os.IBinder mRemote; - - Proxy(android.os.IBinder remote) { - mRemote = remote; - } - - <span class="annotation">@Override</span> - <span class="keyword">public</span> android.os.IBinder asBinder() { - <span class="keyword">return</span> mRemote; - } - - <span class="keyword">public</span> java.lang.String getInterfaceDescriptor() { - <span class="keyword">return</span> DESCRIPTOR; - } - - <span class="annotation">@Override</span> - <span class="keyword">public</span> <span class="keyword">void</span> invoke() <span class="keyword">throws</span> android.os.RemoteException { - android.os.Parcel _data = android.os.Parcel.obtain(); - android.os.Parcel _reply = android.os.Parcel.obtain(); - <span class="keyword">try</span> { - _data.writeInterfaceToken(DESCRIPTOR); - mRemote.transact(Stub.TRANSACTION_invoke, _data, _reply, <span class="number"></span>); - _reply.readException(); - } <span class="keyword">finally</span> { - _reply.recycle(); - _data.recycle(); - } - } - } - - <span class="keyword">static</span> <span class="keyword">final</span> <span class="keyword">int</span> TRANSACTION_invoke = (android.os.IBinder.FIRST_CALL_TRANSACTION + <span class="number"></span>); - } - - <span class="keyword">public</span> <span class="keyword">void</span> invoke() <span class="keyword">throws</span> android.os.RemoteException; - } 既然已经通过aidl生成了这份接口文件,那么根据上一篇文章所讲的,我们接下来就要来实现服务端这边提供的服务了。 ...

2015年1月20日 · 8 分钟 · 天边的星星

Android学习小Demo(12)TodoList实现ListView的分组实现

 很多情况下, 我们想要ListView上面展示的东西是可以分组的,比如联系人列表,国家列表啊,这样看起来数据的展现比较有层次感,而且也有助于我们快速定位到某一个具体的条目上,具体效果请看下图: 这是前面TodoList小demo的MainActivity,主要是来展现用户添加的任务的,在原来的基础上添加了分组的效果。 接下来我们具体来讲一下这个效果是怎么实现的。 这是利用开源库StickyListHeaders(传送门:https://github.com/emilsjolander/StickyListHeaders)来实现的,这个实现的效果是基于ListView的,而其实也有关于GridView而实现的分组的效果,大家可以参考一下xiaanming的博客(他的文章名字都很长。。。): Android 使用开源库StickyGridHeaders来实现带sections和headers的GridView显示本地图片效果 0)关于如何导进开源库,大家请参考:如何导进开源库StickyListHeaders 1)然后,我们要想清楚一件事情,即分组的ListView,是包含两部分:Header 和 Item,所以相对应的我们也要为其定义两个Layout,如下: 1.1)task_header.xml **[html]** [view plain](http://blog.csdn.net/linmiansheng/article/details/20747775#)[copy](http://blog.csdn.net/linmiansheng/article/details/20747775#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/224769)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/224769/fork) <div> <embed id="ZeroClipboardMovie_1" src="http://static.blog.csdn.net/scripts/ZeroClipboard/ZeroClipboard.swf" type="application/x-shockwave-flash" width="18" height="18" align="middle" name="ZeroClipboardMovie_1"> </embed> </div> </div> - <span class="tag"><?</span><span class="tag-name">xml</span> <span class="attribute">version</span>=<span class="attribute-value">&#8220;1.0&#8221;</span> <span class="attribute">encoding</span>=<span class="attribute-value">&#8220;utf-8&#8221;</span><span class="tag">?></span> - <span class="tag"><</span><span class="tag-name">RelativeLayout</span> <span class="attribute">xmlns:android</span>=<span class="attribute-value">&#8220;http://schemas.android.com/apk/res/android&#8221;</span> - <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span> - <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span> - <span class="attribute">android:background</span>=<span class="attribute-value">&#8220;@drawable/header_selector&#8221;</span> <span class="tag">></span> - - <span class="tag"><</span><span class="tag-name">TextView</span> - <span class="attribute">android:id</span>=<span class="attribute-value">&#8220;@+id/tvHeader&#8221;</span> - <span class="attribute">android:layout_width</span>=<span class="attribute-value">&#8220;wrap_content&#8221;</span> - <span class="attribute">android:layout_height</span>=<span class="attribute-value">&#8220;match_parent&#8221;</span> - <span class="attribute">android:layout_gravity</span>=<span class="attribute-value">&#8220;start|left&#8221;</span> - <span class="attribute">android:padding</span>=<span class="attribute-value">&#8220;5dp&#8221;</span> - <span class="attribute">android:textColor</span>=<span class="attribute-value">&#8220;@android:color/white&#8221;</span> - <span class="attribute">android:textSize</span>=<span class="attribute-value">&#8220;17sp&#8221;</span> - <span class="attribute">android:textStyle</span>=<span class="attribute-value">&#8220;bold&#8221;</span> <span class="tag">/></span> - - <span class="tag"></</span><span class="tag-name">RelativeLayout</span><span class="tag">></span> 因为我们在Header上面只是展现一个日期,所以我们只需要一个TextView即可。 ...

2015年1月20日 · 7 分钟 · 天边的星星

AndroidNDK开发环境介绍

AndroidNDK开发环境介绍 一.系统和软件需求 1.AndroidSDK 一个完整的Android SDK安装(包括所有附件)是必需的 Android 1.5 以上SDK 2.支持的操作系统 Windows XP (32-bit) or Vista (32- or 64-bit) Mac OS X 10.4.8 or later (x86 only) Linux (32 or 64-bit; Ubuntu 8.04, or other Linux distributions using GLibc 2.7 or later) 3.需要的开发工具 所有开发平台都需要GNU Make3.81以上版本 需要最新版本的AWK( GNU Awk 或者Nawk) 对于Windows,需要Cygwin 1.7以上的版本(注意:Cygwin1.5是不行的) 4.Android平台兼容性 创建的本地库Android NDK只能运行特定的最低设备使用Android平台版本,平台所需的最低版本取决于您的目标设备的CPU架构。 下面的表细节的Android平台版本兼容本地代码开发特定的CPU架构。 CPU架构 兼容的平台 ARM, ARM-NEON Android 1.5 以上 x86 Android 2.3 以上 MIPS Android 2.3 以上 为了保证平台兼容性需要设置的android:minSdkVersion 例如 NDK使用OpenGL ES APIs,为了确保平台的兼容性,需要设置的android:minSdkVersion 下面给出对应关系 OpenGL ES 版本 兼容平台 需要的最小SDK OpenGL ES 1.1 Android 1.6 以上 android:minSdkVersion=”4″ OpenGL ES 2.0 Android 2.0 以上 android:minSdkVersion=”5″ 另外一个应用使用OpenGL ES,在manifest文件中应该声明的 android:glEsVersion(OpenGL的最小版本) 例如 NDK中使用API访问Bitmap相关操作,需要设置Android的最小SDK为8. 英文原文 If you use this NDK to create a native library that uses the API to access Android Bitmap pixel buffers or utilizes native activities, the application containing the library can be deployed only to devices running Android 2.2 (API level 8) or higher. To ensure compatibility, make sure that your application declares attribute value in its manifest. ...

2015年1月8日 · 2 分钟 · 天边的星星

Android 开发 之 JNI入门 – NDK从入门到精通

NDK项目源码地址 : — 第一个JNI示例程序下载 : GitHub – https://github.com/han1202012/NDKHelloworld.git — Java传递参数给C语言实例程序 : GitHub – https://github.com/han1202012/NDKParameterPassing.git —C语言回调Java方法示例程序 : GitHub – https://github.com/han1202012/NDK_Callback.git —分析Log框架层JNI源码所需的Android底层文件 : CSDN – http://download.csdn.net/detail/han1202012/6905507 开发环境介绍 : — eclipse : adt-bundle-windows-x86-20130917 — sdk : 版本 2.3.3 — ndk : android-ndk-r9c-windows-x86.zip — cygwin : 所需组件 binutils , gcc , gcc-mingw , gdb , make; — javah : jdk6.0自带工具 — javap : jdk6.0自带工具 **JNI 总结 : ** Java 调用 C 流程 : — a. 定义 Native 方法 : 在 shuliang.han.ndkparameterpassing.DataProvider.java 类中定义 Native 方法 public native int add(int x, int y); ...

2015年1月8日 · 62 分钟 · 天边的星星

Android NDK开发(一)——环境搭建

Android下的NDK开发是Android开发中不可或缺的一部分,通过Google提供的NDK套件,我们可以使用JNI这座桥梁在Java和C/C++之间建立联系(互相调用)。那么,为什么在Android开发中需要了解NDK开发呢?诚然,这些原因有很多说法,在我总结来是这样的。C/C++是比Java还要古老的编程语言,由于其古老的特性,导致早期有很多优秀的类库出现,譬如处理视频编解码的FFMPEG类库,这些复杂的类库早就被C/C++编写过,我们在处理视频编解码的时候没必要重复“造轮子”,所以能直接拿来用的就直接拿来用,但是这个直接法很难做到,因为Java的编译环境的原理跟C/C++的不同,所以就必须找个中间者为Java和C/C++代码建立关系,这个中间者就是JNI。还有一个重要的原因就是效率问题,Java是跨平台的语言,在不同的平台有不同的JVM实现,Java源码需要首先编译成.class文件,然后让.class文件运行在不同的JVM解释执行上,这样的步骤造成了效率的浪费,而不同的是C/C++,可以直接编译成特定平台的二进制文件,直接运行在特定平台上,效率比Java高效很多,所以在某些特定的环境下,还是需要使用C/C++来解决效率问题,Java只负责处理C/C++返回来的结果就可以,这样的话Java和C/C++互调就显得相当重要了。 做NDK开发前最好需要了解一下C/C++的语法,通常这部分的代码不需要Android程序员编写,但是Android程序员最好能看懂C/C++源码,这样做会事半功倍一点,关于C/C++语法的学习不是这里的重点,大家感兴趣的话可以直接找资料学习,请从柜底抽出大学教材《C语言程序设计——谭浩强》,拍拍上面的灰尘,随便过一遍^.^ 一、明确一些基本概念 1,JNI Java Native Interface Java 本地开发的接口。JNI 是一个协议,这个协议用来沟通java代码和外部的本地代码(c/c++)。通过这个协议,java代码就可以调用外部的c/c++代码,外部的c/c++代码也可以调用java代码。 2,CDT C/C++ Develop tools,C/C++开发工具。是Eclipse上的一个插件,主要是让C/C++代码能够高亮显示。这个组件不是必要的,除非你是C/C++高手,喜欢在记事本上写代码,对于一般的程序员还是装一下吧,高亮显示很重要的。 3,NDK Native Develop Kits,本地开发套件。这个套件是非常重要的,是Google提供给我们的一个在Android上开发JNI程序的工具集,有了它会使得开发高效的多。 4,cygwin Windows下的Linux模拟器。大家知道Android是基于Linux内核的操作系统,所以在编译C/C++源码的使用得使用Linux环境,将其编译成Linux特定平台的文件.so或者.a。好消息是,NDK高版本中提供了Windows下开发套件的支持,cygwin可以不使用,直接在Windows下平台编译也是可行的,但是为了显示学习,最好还是需要了解一点的。 二、NDK环境搭建 1,安装CDT 如果是使用的是从Android Develop官网上下载的集成了ADT一整套的IDE的话,请跳过这一步,因为ADT中已经集成好了CDT插件,直接使用就可以了。如果使用的是传统的Eclipse自装插件的方式的话,有两种方式可供安装CDT。 (1)下载CDT插件进行安装。在Eclipse社区官网可以找到下载链接[https://eclipse.org/cdt/](https://eclipse.org/cdt/)。 (2)在线安装。步骤如下: ![](http://img.blog.csdn.net/20141208123341295?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWxsZW4zMTU0MTA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 选择 Helios- http://download.eclipse.org/release/helios ,等待展开,选择Programing language![](http://img.blog.csdn.net/20141208123356255?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWxsZW4zMTU0MTA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 选择c/c++ 开发工具 ![](http://img.blog.csdn.net/20141208123530245?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWxsZW4zMTU0MTA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 一路next下去,同意licenses。 安装成功会提示是不是确认重启eclipse,重启就完成安装。 2,安装cygwin NDK需要运行在linux环境下,cygwin是windows下模拟linux的一个工具。Cygwin是一个程序,支持很多插件。可以去cygwin的官网上下载[http://www.cygwin.com/](http://www.cygwin.com/)双击安装,也可以从CSDN资源页上下载我上传的资料包,里面包含cygwin的安装程序和安装包,地址是:[**http://download.csdn.net/detail/lee_tianya/8235323**](http://download.csdn.net/detail/lee_tianya/8235323) ![](http://img.blog.csdn.net/20141208123919847?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWxsZW4zMTU0MTA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 选择安装方式请注意了,一般可以选择从Internet上在线安装,不过速度很慢,而且中途不能断开,如果网速不好中途断开了,那么就必须从头开始下载,非常不舒服。第二种方式是本地安装,先下载好安装所需要的文件放在本地磁盘上,然后选择安装目录即可,我这里是本地安装。 ![](http://img.blog.csdn.net/20141208124337699?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWxsZW4zMTU0MTA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 选择安装目录的时候请注意:安装目录不可以出现空格,最好不要出现中文等非英文字符。 ![](http://img.blog.csdn.net/20141208124346984?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWxsZW4zMTU0MTA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) ![](http://img.blog.csdn.net/20141208125609296?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWxsZW4zMTU0MTA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) ![](http://img.blog.csdn.net/20141208124405530?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWxsZW4zMTU0MTA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) ![](http://img.blog.csdn.net/20141208124412300?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWxsZW4zMTU0MTA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 安装完毕后 ,桌面会出现一个快捷图标,双击快捷小图标,打开cygwin。 首先程序会初始化 ![](http://img.blog.csdn.net/20141208130726968?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWxsZW4zMTU0MTA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 敲入命令 Make –v ![](http://img.blog.csdn.net/20141208130742387?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWxsZW4zMTU0MTA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 显示出来 GNU Make 的版本 ,说明我们的cygwin模拟的linux编译环境 模拟成功了. 3,安装NDK 首先翻墙上Google Android Develop的官网去下载NDK,地址是**[http://developer.android.com/tools/sdk/ndk/index.html](http://developer.android.com/tools/sdk/ndk/index.html)** **![](http://img.blog.csdn.net/20141208131837421?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWxsZW4zMTU0MTA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) ** ...

2015年1月8日 · 1 分钟 · 天边的星星

圆形进度(ProgressWheel)

This is a custom component for Android intended for use instead of a progress bar. {#user-content-a-complete-walkthrough-of-how-to-use-this-component-in-your-app.anchor}A complete walkthrough of how to use this component in your app XML: To implement the view in your xml layout do the following: Add the following to your attrs.xml file (in res/values): ``` <declare-styleable name="ProgressWheel"> <attr name="text" format="string" /> <attr name="textColor" format="color" /> <attr name="textSize" format="dimension" /> <attr name="barColor" format="color" /> <attr name="rimColor" format="color" /> <attr name="rimWidth" format="dimension" /> <attr name="spinSpeed" format="integer" /> <attr name="circleColor" format="color" /> <attr name="radius" format="dimension" /> <attr name="barWidth" format="dimension" /> <attr name="barLength" format="dimension" /> <attr name="delayMillis" format="dimension"/> <attr name="contourColor" format="color"/> <attr name="contourSize" format="float"/> </declare-styleable> ``` Add the following code to the root view of your layout:xmlns:ProgressWheel="http://schemas.android.com/apk/res/com.visualdenim.schooltraq" ...

2015年1月6日 · 2 分钟 · 天边的星星

Android应用如何监听自己是否被卸载及卸载反馈功能的实现

一个应用被用户卸载肯定是有理由的,而开发者却未必能得知这一重要的理由,毕竟用户很少会主动反馈建议,多半就是用得不爽就卸,如果能在被卸载后获取到用户的一些反馈,那对开发者进一步改进应用是非常有利的。目前据我所知,国内的Android应用中实现这一功能的只有360手机卫士、360平板卫士,那么如何实现这一功能的? 我们可以把实现卸载反馈的问题转化为监听自己是否被卸载,只有得知自己被卸载,才可以设计相应的反馈处理流程。以下的列表是我在研究这一问题的思路: 1,注册BroadcastReceiver,监听&#8221;android.intent.action.PACKAGE_REMOVED&#8221;系统广播 结果:NO。未写代码,直接分析,卸载的第一步就是退出当前应用的主进程,而此广播是在已经卸载完成后才发出的,此时主进程都没有了,去哪onReceive()呢? 2,若能收到&#8221;将要卸载XX包&#8221;的系统广播,在主进程被退出之前就抢先进行反馈处理就好了,可惜没有这样的系统广播,不过经过调研,倒是发现了一个办法,读取系统log,当日志中包含&#8221;android.intent.action.DELETE&#8221;和自己的包名时,意味着自己将要被卸载。 结果:NO。调试时发现此方法有两个缺陷,(1)点击设置中的卸载按钮即发出此Intent,此时用户尚未在弹框中确认卸载;(2)pm命令卸载不出发此Intent,意味着被诸如手机安全管家,豌豆荚等软件卸载时,无法提前得知卸载意图。 3,由于时间点不容易把控,所以干脆不依赖系统广播或log,考虑到卸载过程会删除&#8221;/data/data/包名&#8221;目录,我们可以用线程直接轮询这个目录是否存在,以此为依据判断自己是否被卸载。 结果:NO。同方法1,主进程退出,相应的线程必定退出,线程还没等到判断目录是否存在就已经被销毁了。 4,改用C端进程轮询&#8221;/data/data/包名&#8221;目录是否存在 结果:YES。借助Java端进程fork出来的C端进程在应用被卸载后不会被销毁。 OK,上代码! Activity启动时fork出C端进程轮询目录: ![复制代码](http://common.cnblogs.com/images/copycode.gif) ``` 1 package main.activity; 2 3 import pym.test.uninstalledmoniter.R; 4 import android.app.Activity; 5 import android.os.Bundle; 6 import android.util.Log; 7 8 /** 9 * @author pengyiming 10 * @note 监听此应用是否被卸载,若被卸载则弹出卸载反馈 11 * 12 / 13 14 public class UninstalledMoniterActivity extends Activity 15 { 16 / 数据段begin / 17 private static final String TAG = “UninstalledMoniterActivity”; 18 / 数据段end / 19 20 / 函数段begin / 21 private native void init(); 22 static 23 { 24 Log.d(TAG, “load libuninstalled_moniter”); 25 System.loadLibrary(“uninstalled_moniter”); 26 } 27 28 @Override 29 public void onCreate(Bundle savedInstanceState) 30 { 31 super.onCreate(savedInstanceState); 32 Log.d(TAG, “onCreate”); 33 34 setContentView(R.layout.uninstalled_moniter_layout); 35 36 init(); 37 } 38 / 函数段end */ 39 } ...

2015年1月6日 · 7 分钟 · 天边的星星