蓝牙通过obex发送文件的思路

1、实现原理
1、1OBEX 协议说明
在层次结构的蓝牙协议栈中,对象交换协议OBEX(Object Exchange)是一种面向应用的会话层协议(图1),它运行于蓝牙协议栈的顶部,支持文件传输(File Transfer),对象“推”操作(Object Push Profile),同步(Synchronization)等多种应用,提供了设备间简单易行的对象交换手段。可交换的对象可是文件、图像,也可是应用支持的任何数据单位。对象交换采用了基于查询—应答方式的Client/Server 模式,任意两台蓝牙设备间都可组成主从关系,主动发起方是主设备(Client),被找到者是从设备(Server)。


图1
与OBEX相关的过程包括:连接建立(Connect)、连接断开(Disconnect)、发文件(Put)、接收文件(Get)、操作放弃(Abort)、设置路径(Set Path)。对象交换包括文件和目录的交换。Client 端能初始化各种请求,如发送和接收文件,浏览Server 端对象,因此具备解释OBEX 文件夹及其中文件的格式的能力;Server 端与之相对应,作为一种远程目标设备,提供了对象交换的服务以及使用OBEX 文件夹格式的浏览功能,Server 端的只读文件夹以及只读文件,可以限制对象的发出及文件/目录的删除与建立。
OBEX 协议为不同原因产生不同事件,如:何时建立连接,何时接受OBEX 命令,何时完成API 请求。这些事件由底层协议栈产生的其它事件触发,该事件在其线程执行中无时间占用,所以该事件将被尽快执行。
由于初始化事件不同,Client 和Server 端的执行过程是不相同的。Server 端的应用经常是空闲的,等待着连接的建立和Client 端发出的操作请求。在两次发出请求之间,Client 端将等待Server 的应答。
下图简单阐述了Client 端的执行流程:

图2Client执行流程
1、通过用户界面发出PUT / GET 请求;
2、应用程序通过调用 OBEX 层API 请求一个传输层连接,OBEX 协议接口层执行设备恢复功能,该设备与其它设备建立Transport 层连接,当连接完成后,OBEX 层将执行的状态(Success/Failure)通过事件的句柄(Callback 回调函数)通知给应用程序;
3、当传输层连接建立后,应用程序又通知OBEX 层API 建立OBEX 层的连接,操作完成后,事件句柄又将返回结果通知给应用程序;
4、应用程序通过调用 OBEX 层API 来执行(GET/PUT/SETPATH)命令来交换文件。OBEX命令解释器依次呼叫包分析器,将数据交给栈接口层打包,再交给蓝牙协议栈下层传输;
5、贯穿整个交换过程,对象库负责存储或取出对象数据,而该数据通过命令解释器传递,然后,栈接口层通过包分析器来查询命令解释器,看还有没有数据要发送(通过读对象库),直到没有数据发送为止(对象被全部传完);
6、对象交换完成后,执行结果被通知给应用程序;
7、应用程序能够通过OBEX 层API 交换更多的对象,交换完成后,通知OBEX 断开连接。



Server 端执行流程:
1、Server 端通过栈接口层获得从底层协议栈(embedded stack)中得到的连接信息,栈接口层通过事件回调函数将连接信息告知应用;
2、当OBEX 包开始到达栈接口层,便被送到包分析器,包分析器将OBEX 包和其它有效信息一并加入到命令解释器中,命令解释器通过事件回调通知应用执行相应的操作,应用再通知OBEX 层API 接收和丢弃该操作。同样,通过OBEX 层API 可以获得信息包头的信息,帮助决定操作将被接收或丢弃;
3、如果是接收操作,命令解释器就通知对象库执行读或写操作,命令解释器再呼叫包分析器进行打包,通过下层传递到对方设备。Server 端应用并不负责对象数据的交换;
4、有更多的数据包到达时,执行的流程同前。当数据包通过蓝牙协议栈到达OBEX 栈接口层时,OBEX 栈接口层通过包分析器到命令解释器获取更多数据。命令解释器依次访问对象库读这些数据,该过程知道对象传完后才结束;
5、完成后,命令解释器通知应用事件句柄交换的状态,同时,Server 端返回空闲状态,等待更多的OBEX 请求或Client 端的断开请求。

1、2 基于OBEX文件传输过程
OBEX 文件传输应用的实现过程主要包括初始化、建立连接、文件操作三个阶段。系统首先执行初始化,初始化过程包括Client、Server、对象库的初始化。用户在界面上输入PUT/GET 对象操作请求,系统查询连接是否建立,如未建立,首先进行传输层的连接,成功后再进行OBEX 层连接,直到系统返回连接成功标志后便可进行文件的操作。

建立连接的过程如图3。蓝牙设备通过寻呼消息来建立连接,查询(Inquiry)到指定范围内设备的地址码列表信息,选定某个设备进行连接,客户端查询SDP,在获得了与OBEX Server 应用的对应点后,即建立了传输层的连接。通知应用建立OBEX 层的连接。客户端的文件操作包括两部分,第一步是初始化对象库入口(Object Store Entry),因为OBEX 对交换对象的管理正是通过该入口实现的,因此首先通过初始化入口可以获得目标对象的句柄。 第二步是建立OBEX 信息包的头部(OBEX header),信息包头是用来传递交换的对象属性,如交换对象的数目等,OBEX 定义了多种类型的信息头,不同的操作(如PUT, Abort)建立不同的信息头,向下层发出的连接请求以及回应也是通过读写信息包头的指定域实现的,最后,OBEX 在回调函数中,根据接收到的事件,调用相应的函数完成其功能。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
简单j2me蓝牙OBEX文件代码 http://blog.csdn.net/xiaoxiao108/archive/2011/03/10/6237233.aspx 最近想写一手机程序实现以下功能,在蓝牙的有效距离内,如果有其他手机的蓝牙设置为可见状态,自己的手机自动向其他手机发送指定的图片。查了下j2me的api发现通过obex对象交换协议比较容易实现实现代码很简单 写个程序 弄个死循环让手机一直搜索周围蓝牙设备,如果发现到周围有蓝牙设备,发送图片。 步骤如下 1.初始化蓝牙代码 LocalDevice local_device = LocalDevice.getLocalDevice(); DiscoveryAgent disc_agent = local_device.getDiscoveryAgent(); local_device.setDiscoverable(DiscoveryAgent.LIAC); 2.搜索周围的蓝牙设备 InquiryListener inq_listener = new InquiryListener(); disc_agent.startInquiry(DiscoveryAgent.LIAC, inq_listener); synchronized(inq_listener) { inq_listener.wait(); } 3.遍历所有蓝牙设备,查找每一个蓝牙设备的服务 while( devices.hasMoreElements() ) { synchronized(serv_listener) { RemoteDevice rd= (RemoteDevice)devices.nextElement(); t.setString(rd.getBluetoothAddress()); Thread.sleep(5000); t.setString(rd.getFriendlyName(true)); Thread.sleep(5000); disc_agent.searchServices(null, u,rd, serv_listener); serv_listener.wait(); } 4.从搜索到的ServiceRecord 中取出连接字符串进行连接 if (serv_listener.service!=null){ String url; url = serv_listener.service.getConnectionURL(0, false); Connection conn = Connector.open(url); ClientSession cs=(ClientSession)conn; cs.connect(null); 5.从资源中取出图片发送 byte filebytes[]=getImageData("/images/leaf.png"); HeaderSet hs=cs.createHeaderSet(); hs.setHeader(HeaderSet.NAME,"leaf.png"); hs.setHeader(HeaderSet.TYPE, "text/plain"); hs.setHeader(HeaderSet.LENGTH,new Long(filebytes.length)); Operation putOperation=cs.put(hs); OutputStream outputStream=putOperation.openOutputStream(); outputStream.write(filebytes); outputStream.close(); putOperation.close(); conn.close(); 6.设备查询类InquiryListener的代码 class InquiryListener implements DiscoveryListener{ public Vector cached_devices; public InquiryListener() { cached_devices = new Vector(); } public void deviceDiscovered( RemoteDevice btDevice, DeviceClass cod ) { if( ! cached_devices.contains( btDevice ) ) { cached_devices.addElement( btDevice ); } } public void inquiryCompleted( int discType ) { synchronized(this){ this.notify(); } } public void servicesDiscovered( int transID, ServiceRecord[] servRecord ) {} public void serviceSearchCompleted( int transID, int respCode ) {} } 7.服务查询类ServiceListener的代码 class ServiceListener implements DiscoveryListener{ public ServiceRecord service; public ServiceListener() { } public void servicesDiscovered( int transID, ServiceRecord[] servRecord ) { service = servRecord[0]; } public void serviceSearchCompleted( int transID, int respCode ) { synchronized( this ){ this.notify();} } public void deviceDiscovered( RemoteDevice btDevice, DeviceClass cod ){} public void inquiryCompleted( int discType ){} } 如果你发现有什么不合理的,需要改进的地方,联系328452421@qq.com 朱晓 (泰山学院)。相互交流 谢谢
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值