Android4.3 蓝牙BLE初步

一、关键概念: **Generic Attribute Profile (GATT)** 通过BLE连接,读写属性类小数据的Profile通用规范。现在所有的BLE应用Profile都是基于GATT的。 **Attribute Protocol (ATT)** GATT是基于ATT Protocol的。ATT针对BLE设备做了专门的优化,具体就是在传输过程中使用尽量少的数据。每个属性都有一个唯一的UUID,属性将以characteristics and services的形式传输。 **Characteristic** Characteristic可以理解为一个数据类型,它包括一个value和0至多个对次value的描述(Descriptor)。 **Descriptor** 对Characteristic的描述,例如范围、计量单位等。 **Service** Characteristic的集合。例如一个service叫做“Heart Rate Monitor”,它可能包含多个Characteristics,其中可能包含一个叫做“heart rate measurement”的Characteristic。 二、角色和职责: Android设备与BLE设备交互有两组角色: 中心设备和外围设备(Central vs. peripheral); GATT server vs. GATT client. Central vs. peripheral: 中心设备和外围设备的概念针对的是BLE连接本身。Central角色负责scan advertisement。而peripheral角色负责make advertisement。 GATT server vs. GATT client: 这两种角色取决于BLE连接成功后,两个设备间通信的方式。 举例说明: 现有一个活动追踪的BLE设备和一个支持BLE的Android设备。Android设备支持Central角色,而BLE设备支持peripheral角色。创建一个BLE连接需要这两个角色都存在,都仅支持Central角色或者都仅支持peripheral角色则无法建立连接。 当连接建立后,它们之间就需要传输GATT数据。谁做server,谁做client,则取决于具体数据传输的情况。例如,如果活动追踪的BLE设备需要向Android设备传输sensor数据,则活动追踪器自然成为了server端;而如果活动追踪器需要从Android设备获取更新信息,则Android设备作为server端可能更合适。 三、权限及feature: 和经典蓝牙一样,应用使用蓝牙,需要声明BLUETOOTH权限,如果需要扫描设备或者操作蓝牙设置,则还需要BLUETOOTH_ADMIN权限: 除了蓝牙权限外,如果需要BLE feature则还需要声明uses-feature: 按时required为true时,则应用只能在支持BLE的Android设备上安装运行;required为false时,Android设备均可正常安装运行,需要在代码运行时判断设备是否支持BLE feature: // Use this check to determine whether BLE is supported on the device. Then // you can selectively disable BLE-related features. if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show(); finish(); } 四、启动蓝牙: 在使用蓝牙BLE之前,需要确认Android设备是否支持BLE feature(required为false时),另外要需要确认蓝牙是否打开。 如果发现不支持BLE,则不能使用BLE相关的功能。如果支持BLE,但是蓝牙没打开,则需要打开蓝牙。 打开蓝牙的步骤: 1、获取BluetoothAdapter BluetoothAdapter是Android系统中所有蓝牙操作都需要的,它对应本地Android设备的蓝牙模块,在整个系统中BluetoothAdapter是单例的。当你获取到它的示例之后,就能进行相关的蓝牙操作了。 获取BluetoothAdapter代码示例如下: // Initializes Bluetooth adapter. final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); 注:这里通过getSystemService获取BluetoothManager,再通过BluetoothManager获取BluetoothAdapter。BluetoothManager在Android4.3以上支持(API level 18)。 2、判断是否支持蓝牙,并打开蓝牙 获取到BluetoothAdapter之后,还需要判断是否支持蓝牙,以及蓝牙是否打开。 如果没打开,需要让用户打开蓝牙: private BluetoothAdapter mBluetoothAdapter; … // Ensures Bluetooth is available on the device and it is enabled. If not, // displays a dialog requesting user permission to enable Bluetooth. if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); } 五、搜索BLE设备: 通过调用BluetoothAdapter的[startLeScan()](http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html#startLeScan(android.bluetooth.BluetoothAdapter.LeScanCallback))搜索BLE设备。调用此方法时需要传入 `<a href="http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.LeScanCallback.html">BluetoothAdapter.LeScanCallback</a>`参数。 因此你需要实现 `<a href="http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.LeScanCallback.html">BluetoothAdapter.LeScanCallback</a>`接口,BLE设备的搜索结果将通过这个callback返回。 由于搜索需要尽量减少功耗,因此在实际使用时需要注意: 1、当找到对应的设备后,立即停止扫描; 2、不要循环搜索设备,为每次搜索设置适合的时间限制。避免设备不在可用范围的时候持续不停扫描,消耗电量。 搜索的示例代码如下: /** * Activity for scanning and displaying available BLE devices. */ public class DeviceScanActivity extends ListActivity { private BluetoothAdapter mBluetoothAdapter; private boolean mScanning; private Handler mHandler; ...

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

android 蓝牙

android平台包含了蓝牙网络协议栈的支持,允许android设备与其他蓝牙设备相互传输数据。应用层框架提供了API函数来访问蓝牙模块。使用这些API可以让应用程序连接其他蓝牙设备,实现点对点或多点无线传输。 运用蓝牙API,可以实现以下功能: 搜索其他蓝牙设备 查询本地蓝牙适配器中已经配对好的设备 建立RFCOMM协议通道 通过服务端搜索连接到其他设备 与其他设备互相传输数据 管理多个连接 快速阅读 Android蓝牙API可以让应用程序与其他设备传输无线数据。 关键类 BluetoothAdapter BluetoothDevice BluetoothSocket BluetoothServerSocket 相关用例 蓝牙对讲 http://developer.android.com/resources/samples/BluetoothChat/index.html 蓝牙医疗设备(Health Device Profile),比如心率监视器,血压计,温度计等。http://developer.android.com/resources/samples/BluetoothHDP/index.html 目录 [隐藏] 1 基本原理 2 蓝牙权限 3 配置蓝牙 4 获取蓝牙设备 4.1 查询已配对设备 4.2 搜索设备 4.3 开启蓝牙可检测性 5 设备连接 5.1 作为服务端连接 5.2 作为客户端连接 6 连接管理 7 在蓝牙规范协议下工作 7.1 Vendor-specific AT commands 7.2 Health Device Profile 基本原理 本文档描述了如何使用蓝牙API来完成蓝牙通讯的四项必要任务:配置蓝牙、搜索附件未配对或可用的蓝牙设备、连接设备、设备间传输数据。 所有蓝牙API都包含在android.bluetooth包中。以下是建立蓝牙连接需要用到的类和接口的概要: BluetoothAdapter (蓝牙适配器) 表示本地蓝牙适配器(蓝牙收发器). BluetoothAdapter是所有蓝牙活动的起始类. 可用于搜索其他蓝牙设备, 查询已配对设备的列表, 使用MAC地址实例化一个BluetoothDevice对象, 创建BluetoothServerSocket侦听其他设备的连接. BluetoothDevice (蓝牙设备) 表示远程蓝牙设备。可以通过一个BluetoothSocket向它描述的远程设备发起连接,或者该设备的名称、地址、类、连接状态等信息。 BluetoothSocket (蓝牙套接字) 表示一个蓝牙套接字(与TCP Socket类似). 它是设备间的连接点,允许应用程序通过InputStream和OutputStream与其他设备进行数据传输。 BluetoothServerSocket (蓝牙服务端套接字) 表示一个开放的蓝牙服务器, 用于侦听其他设备发过来的连接请求(与TCP ServerSocket类似). 要将两台设备连接起来, 其中一台必须使用这个类开启一个server socket. 当远程蓝牙设备发起对server的连接请求, 如果连接被接受,BluetoothServerSocket将返回一个连接成功的BluetoothSocket对象. BluetoothClass (蓝牙类型) 描述一个蓝牙设备的规格参数和功能。这是一个只读的属性集,定义了该设备的主要和次要设备种类和服务。它不能完全描述该设备的所有特性和服务,常用于判断设备的类型。 BluetoothProfile (蓝牙规范协议) 表示Bluetooth profile的接口. Bluetooth profile是设备间基于蓝牙通讯的接口规范协议。比如Hands-Free(非手持设备) profile。更多关于profiles的说明, 请查看Working with Profiles(在蓝牙规范协议下工作)。 BluetoothHeadset (蓝牙耳机) 提供手机使用蓝牙耳机的支持。同时包含了蓝牙耳机和Hands-Free(v1.5)的profiles. BluetoothA2dp (蓝牙A2dp) 定义高质量音频流如何通过蓝牙连接传输到其他设备。”A2DP”是”Advanced Audio Distribution Profile”的缩写,表示高级音频分发规范协议。 BluetoothHealth (蓝牙医疗设备) 表示为医疗设备提供蓝牙服务的代理类。 BluetoothHealthCallback 这是一个抽象类,用于实现BluetoothHealth的callbacks方法。需要继承此类并实现callback方法才能接收应用程序状态和蓝牙频道状态的变化。 BluetoothHealthAppConfiguration 表示蓝牙医疗第三方应用与远程蓝牙医疗设备连接的配置参数。 BluetoothProfile.ServiceListener (蓝牙规范协议服务侦听) 一个接口类,当服务连接或断开的时候通知BluetoothProfile IPC 客户端。(这是内部服务运行的一个特殊模式)。 蓝牙权限 ...

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

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 分钟 · 天边的星星