先描述一下我的这个应用,用一根蓝牙笔点击特制的杂志上印刷的电影名称,比如:点击片名为《金龙鱼葵花籽油5L》的视频,蓝牙笔读取到视频名称背后的杂志码比如是234567,因为蓝牙笔只能读到指令不可能直接读取到234567这个杂志码,比如234567这个杂志码对应的指令是qwerty,然后我把这个qwerty解析成234567,然后去数据库里查询这个234567所对应的播放地址比如是:
http://www.youku.com/movie/fengsheng.ram,然后用WebView去打开这个网址,就可以实现蓝牙笔点击电影名称,在手机上播放的效果了。
应用实现步骤
1:先把蓝牙笔和手机配对
只有蓝牙配对的两个具有蓝牙适配器的设备才具有通讯的功能
2:首先在AndroidManifest.xml里面配置权限
//打开蓝牙权限
<uses-permission android:name="android.permission.BLUETOOTH" />
//蓝牙管理权限
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
//访问互联网权限
<uses-permission android:name="android.permission.INTERNET" />
3:阅读深圳生产蓝牙笔的厂商提供的参考文档
从文档来看,蓝牙笔接收到请求后会给我们客户端发送的数据包的大小是10个字节
4:假设场景
我们假设在这个场景中,蓝牙笔是服务端,我的手机应用是客户端,蓝牙笔内置的程序已经被厂商写好了,内置程序一直在等待请求连接,如果连接上了蓝牙笔就把它里面的数据返给我。这只是假设。我这个假设被深圳厂商确定了,所以我们只需要编写客户端的BlueSocket就行了。
5:布局文件
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="请求远程蓝牙笔"
android:id="@+id/btn_request"
/>
</LinearLayout>
main2.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="读取数据"
android:id="@+id/btn_read"
/>
<WebView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
6:代码文件BluetoothRequest.java
package com.menglin.bluetoothrequest;
import java.io.IOException;
import java.util.Iterator;
import java.util.Set;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.bluetooth.BluetoothSocket;
public class MminActivity extends Activity
{
private BluetoothSocket bluetoothSocket = null;
private Button btn_request = null;
private Button btn_read = null;
private Boolean connect_result = false;
private WebView webview;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//得到连接按钮
btn_request = (Button)findViewById(R.id.btn_request);
//绑定连接监听器事件
btn_request.setOnClickListener(new ButtonListener());
}
//绑定连接按钮的监听器
private class ButtonListener implements OnClickListener
{
@Override
public void onClick(View v)
{
//得到BluetoothAdapter对象
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
//判断BluetoothAdapter对象是否为空,如果为空,则表明本机没有蓝牙设备
if(adapter != null)
{
Log.d("mytag","手机拥有蓝牙设备");
//调用isEnabled()方法判断当前蓝牙设备是否可用
if(!adapter.isEnabled())
{
//如果蓝牙设备不可用的话,创建一个intent对象,该对象用于启动一个Activity,提示用户启动蓝牙适配器
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivity(intent);
}
//得到所有已经配对的远程蓝牙适配器对象
Set<BluetoothDevice> devices = adapter.getBondedDevices();
if(devices.size()>0)
{
//用迭代
for(Iterator iterator = devices.iterator();iterator.hasNext();)
{
//得到BluetoothDevice对象,也就是说得到配对的蓝牙适配器
BluetoothDevice device = (BluetoothDevice)iterator.next();
//输出远程蓝牙设备的地址和名称进行测试用
Log.d("mytag",device.getAddress());
Log.d("mytag",device.getName());
//翻译Android的SDK得到这些信息“创建一个RFCOMM BluetoothSocket准备开始一个安全装置连接到这个偏僻的外向利用SDP uuid查找的。提示:如果你是连接到一个蓝牙系列板然后试着用著名的仕达屋优先计划UUID 0000 - 00001101 - 1000 - 8000 - 00805 F9B34FB。然而如果你是连接到一个机器人同伴那么请产生你自己独特的UUID。”
//所以我们就就要用到规定好的蓝牙串口服务唯一标识
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
try
{
bluetoothSocket = device.createRfcommSocketToServiceRecord(uuid);
bluetoothSocket.connect();
//能输出这句话证明连接上远程的蓝牙笔了
Log.d("mytag","我连接上了远程的蓝牙笔了");
connect_result = true;
//表示连接上了远程的蓝牙笔
if(connect_result == true)
{
//加载第二个布局文件
setContentView(R.layout.main2);
webview = (WebView) findViewById(R.id.webview);
webview.getSettings().setJavaScriptEnabled(true);
//得到读取蓝牙笔数据按钮
btn_read = (Button)findViewById(R.id.btn_read);
//绑定读取蓝牙笔数据的按钮监听事件
btn_read.setOnClickListener(new ButtonReadListener());
}
else
{
Log.d("mytag","没有连接上蓝牙笔");
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
else
{
System.out.println("这个手机没有蓝牙设备");
}
}
}
//绑定读取蓝牙笔数据按钮的监听器
private class ButtonReadListener implements OnClickListener
{
@Override
public void onClick(View v)
{
if(connect_result)
{
try
{
InputStream inputStream = bluetoothSocket.getInputStream();
//从深圳生产蓝牙笔的厂商提供的参考文档来看,蓝牙笔接收到请求后会给我们客户端发送的数据包的大小是10个字节,所以我们正好用10个字节去接收数据包。
byte data[] = new byte[10];
int i = 0;
//从InputStream对象中读取服务端蓝牙笔所发送的数据
while((i = inputStream.read(data)) !=1 )
{
long codeid = GetCodeID(data);
//此处用来通过公司接口得到codeid对应的url
webview.loadUrl("url");
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
else
{
Log.d("mytag","没有连接上蓝牙笔");
}
}
}
//得到最终的杂志码
//我这段代码比较麻烦了,貌似可以转化成DWord,在统一转化为十六进制格式
private long GetCodeID(byte data[])
{
String result = "";
String str = "";
for (int i = 0; i < data.length; i++)
{
//阅读深圳生产蓝牙笔的厂商提供的参考文档,我们发现’+‘,它已经定义好了占一个字节,我们不管这个”+“是什么意思,“I”和“D”也已经被厂商定义好了,共占2个字节,我们依然不管是什么意思,序号占一个字节,\r和\n各占一个字节,所以我们需要的数据其实只是数组下标为4,5,6,7的value
//注意从蓝牙笔里面读取出来的数据是十进制的,我们要把它最终转化为十六进制
//只要数组下标为4,5,6,7的value
if(i == 4 || i == 5 || i == 6 || i == 7)
{
//如果是正数
if(data[i]>0)
{
str = Integer.toHexString(data[i]);//将value转化为十六进制字符
}
else
{
str = Integer.toHexString(data[i]);//将value转化为十六进制字符
str = str.replace("ffffff", ""); //替换负数转化中出现的补位字符
}
result += str;
}
}
int codeid = Integer.parseInt(result,16);//将最终的字符串按十六进制转换为数字
return codeid;
}
}
7:调试截图
我们看到代码已经运行到Log.d()说明已经连接上远程的蓝牙笔了。
我们从Debug模式中监视变量的值,这个字节数组中看到data[0]=43,而43的ASCII码值是“+”,正好是深圳厂商给的文档里的第一个字符,data[1]=73而73的ASCII码值是“I”,正好是深圳厂商给的文档里的第二个字符,data[3]=68而73的ASCII码值是“D”,data[8]=13,而13的ASCII码值是“\r”,正好是深圳厂商给的文档里的倒数第二个字符,data[9]=10而10的ASCII码值是“\n”,正好是深圳厂商给的文档里的最后一个字符。所以我们需要的数据其实只是数组下标为4,5,6,7的value,那么是data[4]=0,而0的十六进制还是0,data[5]=2,而2的十六进制还是2,那么是data[6]=38,而38的十六进制是26,data[7]=-54,而-54的十六进制是ffffffca,那么这个数据包就是0226ca,而0226ca的十进制是141002。
8:去数据库里查询看读到的这个141002对不对
注意看,我们通过蓝牙笔得到的141002和我们数据库里查询的一样吧
最终我们找到《金龙鱼葵花籽油5L》的视频的播放地址了,我们只需要把这个地址给WebView的loadUrl()方法,就能实现蓝牙笔点击杂志,手机播放被点击的视频了
9:运行流程
蓝牙笔开机的时候指示灯是红绿交替显示,当单击“请求远程蓝牙笔”按钮后,如果连接上了,蓝牙笔的指示灯是绿色不停的显示同时手机屏幕会切换到布局文件为main2.xml的界面,然后我们把蓝牙笔头触放到杂志的视频名称或者图片上,点击“读取数据”按钮后,就能在手机上打开你所点的视频了。
10:扩展场景
假设以后地铁站或者公交站有麦当劳的大的电子Logo,我们用蓝牙笔(当然不是我现在做这个应用的蓝牙笔了它太大了),也许就是个手机挂链,点击这个Logo,就把麦当劳的优惠劵下载到手机上了。
分享到:
相关推荐
手机通过蓝牙连接智能跑步机的协议
基于Android的BlueTooth开发手机蓝牙和蓝牙模块通讯,
手机上通过蓝牙串口协议读取GPS接收仪的GPS数据
蓝牙无线通讯协议,1.1,如果你先看看蓝牙相关协议,这是不错的参考资料。
CPCL协议蓝牙连接打印机通讯例子
安卓手机蓝牙通讯示例程序,该程序可以实现安卓手机连接外部蓝牙模块并进行数据交换,可应用到工业安卓机上和一些专利工具上。
逻辑链路控制与适应协议(L2CAP)位于基带协议层上,属于数据链路层,是一个为高层传输和应用层协议屏蔽基带协议的适配协议。 1、扫描其他蓝牙设备 2、为可配对的蓝牙设备查询蓝牙适配器 3、建立RFCOMM通道(其实...
android 蓝牙hid协议开发,实现手机连接蓝牙鼠标、键盘、扫描枪.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
百捷(BeneCheck)家用多功能分析仪,尿酸测试仪,血糖检测仪,总胆固醇检测血糖仪,蓝牙通讯协议,为即测即传版,协议定义了完整的数据格式,并且标明了血糖 总胆固醇 尿酸的数据格式
C++实现蓝牙bluetooth通讯功能,基础功能实现,源代码,
蓝牙协议分析及其在蓝牙耳机中的应用,以及蓝牙通讯机制
口应用程序和协议可以不加更改地运行在蓝牙设备上,例如 通过点对点协议 PPP 可实现基于 TCP/IP 协议簇的所有网络 应用。BNEP 层实现了蓝牙的以太网仿真,TCP/IP 可以直接 运行于其上。 USB设备驱动 (hci_usb.o) L2...
蓝牙协议栈的详细文档,硬件工程师和嵌入式软件工程师必读的文档
各种蓝牙剖面协议,开发蓝牙应用的必备资料。
:蓝牙技术是当前国内外科技界和产业界研究开发的热点技术,其应用范围包括手机、PDA、 信息家电设备等领域,蓝牙技术在嵌入式系统上必将得到广泛的应用。而要在嵌入式系统上提 供蓝牙开发支持,蓝牙协议栈的移植是...
通过修改,实现了手机蓝牙和计算机蓝牙模块之间的信息交换,示例。环境:vs2008 WM6.1等,参考资料
1. 使用真机测试 2. 测试前请蓝牙配对好手机与PC机蓝牙适配器(所以你需要一个蓝牙适配器插入PC USB口) demo测试效果: 当手机左右摇摆时将数据传递到PC端,打印出来。(android重力感应)
BEL 蓝牙内核协议说明,蓝牙协议版本为4.2
使用AT89C51RC单片机,即 51单片机,HC-06 蓝牙模块,用户在手机端下载一个蓝牙串口助手,单片机和手机端通过蓝牙通讯;烧写好程序到单片机后,手机连接HC-06 蓝牙,然后就可以在手机显示温湿度了。