Android 蓝牙编程控制机器人
暑假的缘故,博客很久没更新了。开学这一个星期以来,接触了一些新的东西,就是通过蓝牙连接控制机器人,确实很多东西都比较陌生,在网上花费了大量的时间来找资料,好在到今天已经实现了初步的功能。
所需的知识:
蓝牙是一种支持设备短距离传输数据的无线技术。android在2.0以后提供了这方面的支持。在蓝牙编程里面主要用到的有以下几个类:
(1)BluetoothAdapter类:代表了一个本地的蓝牙适配器。它是所有蓝牙交互的的入口点。利用它你可以发现其他蓝牙设备,查询绑定了的设备,使用已知的MAC地址实例化一个蓝牙设备和建立一个BluetoothServerSocket(作为服务器端)来监听来自其他设备的连接。
(2)BluetoothDevice类:代表了一个远端的蓝牙设备,使用它请求远端蓝牙设备连接或者获取远端蓝牙设备的名称、地址、种类和绑定状态。(其信息是封装在bluetoothsocket中)。
(3)Bluetoothsocket类:代表了一个蓝牙套接字的接口(类似于tcp中的套接字),它是应用程序通过输入、输出流与其他蓝牙设备通信的连接点。
(4)Blueboothserversocket类:代表打开服务连接来监听可能到来的连接请求(属于server端),为了连接两个蓝牙设备必须有一个设备作为服务器打开一个服务套接字。当远端设备发起连接连接请求的时候,并且已经连接到了的时候,Blueboothserversocket类将会返回一个bluetoothsocket。
(5)Bluetoothclass类:描述了一个蓝牙设备的一般特点和能力。它的只读属性集定义了设备的主、次设备类和一些相关服务。然而,它并没有准确地描述所有该设备所支持的蓝牙文件和服务,而是作为对设备种类来说的一个小小暗示。
一:Android的Activity的创建。
这个相信接触Android的人都懂的怎么创建一个自己喜欢的Activity,怎么使自己的界面美观。代码方面主要是XML文件的编写,创建一些组件,并且给每个组件添加相应的ID号,以便添加监听。
二:添加权限,蓝牙编程需添加两个权限。
在manifest中配置
Xml代码
<uses-permissionandroid:name="android.permission.BLUETOOTH"/>
<uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN"/>
三:启动蓝牙\关闭蓝牙。
//创建蓝牙适配器对象在这里为了在另外的Activity中使用,我设为了静态
staticBluetoothAdapteradapter=BluetoothAdapter.getDefaultAdapter();
//等于10表示蓝牙处于关闭状态
if(adapter.getState()=10)
adapter.enable();//开启蓝牙
}
if(adapter.getState()==12){//等于12表示蓝牙处于开启状态
adapter.disable();//关闭蓝牙
}
启动蓝牙与关闭蓝牙各自在开启\关闭按钮里的OnclickListener监听中操作。
四:搜索蓝牙设备。
这里可以分为几个小方面:
(1)使本机蓝牙处于可见(即处于易被搜索到状态),便于其他设备发现本机蓝牙
//使本机蓝牙在300秒内可被搜索发现蓝牙设备
//使本机蓝牙在300秒内可被搜索发现蓝牙设备
privatevoidensureDiscoverable(){
if(MainActivity.adapter.getScanMode()!=
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE){
//使自己设备能被发现
[align=center]
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);
startActivity(discoverableIntent);
}
}}[/align]
在点击搜索按钮时调用此方法,此时系统会弹出询问框。
(2)查找设备
//搜索设备
privateBroadcastReceivermReceiver=newBroadcastReceiver(){
privateListViewbluetooth_list;
@Override
publicvoidonReceive(Contextcontext,Intentintent){
//搜索新设备
System.out.println("onReceive..........")mNewDevicesArrayAdapter=newArrayAdapter<String>(context,0);
Stringaction=intent.getAction();
if(BluetoothDevice.ACTION_FOUND.equals(action)){
device=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
System.out.println("name="+device.getName()+"address="+device.getAddress());
//将设备名添加到list中,以便之后显示在列表上
list.add(device.getName());
//已经配对的则跳过
if(device.getBondState()!=BluetoothDevice.BOND_BONDED){
//保存设备地址与名字
mNewDevicesArrayAdapter.add(device.getName()+"\n"+device.getAddress());
}
}elseif(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
//搜索结束
if(mNewDevicesArrayAdapter.getCount()==0){
mNewDevicesArrayAdapter.add("没有搜索到设备");
}
}
通过Adapter.startDiscovery();搜索设备,要获得此搜索的结果需要注册一个BroadcastReceiver来获取。先注册再获取信息,然后在OnReceive方法中处理
注册广播
//注册,当一个设备被发现时调用onReceive
IntentFilterfilter=newIntentFilt(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(mReceiver,filter);
//当搜索结束后调用onReceive
filter=newIntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(mReceiver,filter);
用完之后得注销广播,一般在OnCreat()中创建,在OnDestroy()中销毁
this.unregisterReceiver(mReceiver);//销毁广播
五:蓝牙配对
利用反射机制调用系统隐藏方法creatBond()配对
try{
//反射机制调用隐藏方法createBond
Methodmethod_bond=BluetoothDevice.class.getMethod("createBond");
booleanbool=(Boolean)method_bond.invoke(d);//返回bool值
Toast.makeText(BluetoothActivity.this,"bool="+bool,3).show();
}catch(Exceptione){
e.printStackTrace();
}
六:连接蓝牙
在广播OnReceive()中对蓝牙配对状态进行监听
//创建BluetoothDevice对象
device=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//获取配对状态
intstate=device.getBondState();
switch(state){
caseBluetoothDevice.BOND_NONE
break;
caseBluetoothDevice.BOND_BONDING:
break;
caseBluetoothDevice.BOND_BONDED:
}
当检测到配对状态为BOND_BONDED,即配对成功时,开始连接,连接代码
UUIDuuid=UUID.fromString(SPP_UUID);
//createRfcommSocketToServiceRecord创建一个socket对象
BluetoothSocketbs=device.createRfcommSocketToServiceRecord(uuid);Toast.makeText(BluetoothActivity.this,"正在连接..",3).show();
bs.connect();
}catch(IOExceptione){e.printStackTrace();
}
其中uuid我是在代码中直接给定的,uuid有很多种不同类型,可以查表得。[staticfinalStringSPP_UUid="00001101-0000-1000-800000805F9B34FB";给定全局静态此为文件传输型uuid
七:传输数据
privateclassConnectedThreadextendsThread{
privatefinalBluetoothSocketmmSocket;
privatefinalInputStreammmInStream;
privatefinalOutputStreammmOutStream;
publicConnectedThread(BluetoothSocketsocket){
mmSocket=socket;
InputStreamtmpIn=null;
OutputStreamtmpOut=null;
//Gettheinputandoutputstreams,usingtempobjectsbecause
//memberstreamsarefinal
try{
tmpIn=socket.getInputStream();
tmpOut=socket.getOutputStream();
}catch(IOExceptione){}
mmInStream=tmpIn;
mmOutStream=tmpOut;
}
publicvoidrun(){
byte[]buffer=newbyte[1024];//bufferstoreforthestream
intbytes;//bytesreturnedfromread()
//KeeplisteningtotheInputStreamuntilanexceptionoccurs
while(true){
try{
//ReadfromtheInputStream
bytes=mmInStream.read(buffer);
//SendtheobtainedbytestotheUIActivity
mHandler.obtainMessage(MESSAGE_READ,bytes,-1,buffer).sendToTarget();
}catch(IOExceptione){
break;
}
}
}
/*CallthisfromthemainActivitytosenddatatotheremotedevice*/
publicvoidwrite(byte[]bytes){
try{
mmOutStream.write(bytes);
}catch(IOExceptione){}}
/*CallthisfromthemainActivitytoshutdowntheconnection*/
publicvoidcancel(){
try{
mmSocket.close();
}catch(IOExceptione){}
}
}
传输数据主要涉及文件的读写,
tmpIn=socket.getInputStream();
tmpOut=socket.getOutputStream();
主要为这两行代码
到这里蓝牙的基本功能就完成了。
现在还有控制机器人的具体指令没有实现,需再接再厉,早日完成这个项目。