Android Bluetooth 学习(2)应用层实现蓝牙设备查找、tcp_ip通信
来源:互联网 发布:java 实现onvif 编辑:程序博客网 时间:2024/06/05 02:20
Bluetooth结构
1、JAVA层
frameworks/base/core/java/android/bluetooth/
包含了bluetooth的JAVA类。
2、JNI层
frameworks/base/core/jni/android_bluetooth_开头的文件
定义了bluez通过JNI到上层的接口。
frameworks/base/core/jni/android_server_bluetoothservice.cpp
调用硬件适配层的接口system/bluetooth/bluedroid/bluetooth.c
3、bluez库
external/bluez/
这是bluez用户空间的库,开源的bluetooth代码,包括很多协议,生成libbluetooth.so。
4、硬件适配层
system/bluetooth/bluedroid/bluetooth.c
包含了对硬件操作的接口
system/bluetooth/data/*
一些配置文件,复制到/etc/bluetooth/。
还有其他一些测试代码和工具。
一、简略介绍Bluetooth开发使用到的类
1、BluetoothAdapter,蓝牙适配器,可判断蓝牙设备是否可用等功能。
常用方法列举如下:
cancelDiscovery() ,取消搜索过程,在进行蓝牙设备搜索时,如果调用该方法会停止搜索。(搜索过程会持续12秒)
disable()关闭蓝牙,也就是我们常说的禁用蓝牙。
enable()打开蓝牙,这个方法打开蓝牙但不会弹出提示,正常流程操作下,我们会让系统提示用户是否打开蓝牙设备。如下两行代码可轻松搞定。
Intent enabler=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enabler,reCode);//同startActivity(enabler);(在主Activity启动一个二级Activity,reCode一般等于3,一定记得要在AndroidManifest.xml里面添加蓝牙权限)
getAddress()获取本地蓝牙地址
getDefaultAdapter()获取默认BluetoothAdapter,实际上,也只有这一种方法获取BluetoothAdapter
getName()获取本地蓝牙名称
getRemoteDevice(String address)根据蓝牙地址获取远程蓝牙设备
getState()获取本地蓝牙适配器当前状态(感觉可能调试的时候更需要)
isDiscovering()判断当前是否正在查找设备,是返回true
isEnabled()判断蓝牙是否打开,已打开返回true,否则,返回false
listenUsingRfcommWithServiceRecord(String name,UUID uuid)根据名称,UUID创建并返回
BluetoothServerSocket,这是创建BluetoothSocket服务器端的第一步
startDiscovery()开始搜索,这是搜索的第一步
2.BluetoothDevice看名字就知道,这个类描述了一个蓝牙设备
createRfcommSocketToServiceRecord(UUIDuuid)根据UUID创建并返回一个BluetoothSocket
这个方法也是我们获取BluetoothDevice的目的——创建BluetoothSocket
这个类其他的方法,如getAddress(),getName(),同BluetoothAdapter
这个类有几个隐藏方法,涉及到蓝牙的自动配对,setPin,createBond,cancelPairingUserInput,等方法(需要通过java的反射,调用这几个隐藏方法)
3.BluetoothServerSocket如果去除了Bluetooth相信大家一定再熟悉不过了,既然是Socket,方法就应该都差不多,
这个类一种只有三个方法
两个重载的accept(),accept(inttimeout)两者的区别在于后面的方法指定了过时时间,需要注意的是,执行这两个方法的时候,直到接收到了客户端的请求(或是过期之后),都会阻塞线程,应该放在新线程里运行!
还有一点需要注意的是,这两个方法都返回一个BluetoothSocket,最后的连接也是服务器端与客户端的两个BluetoothSocket的连接
close()关闭!
4.BluetoothSocket,跟BluetoothServerSocket相对,是客户端
一共5个方法,不出意外,都会用到
close(),关闭
connect()连接
getInptuStream()获取输入流
getOutputStream()获取输出流
getRemoteDevice()获取远程设备,这里指的是获取bluetoothSocket指定连接的那个远程蓝牙设备
二、蓝牙设备的发现、查找。
1.基于安全性考虑,设置开启可被搜索后,Android系统会默认给出120秒的时间,其他设备能在这120秒内搜索到它。Intent enable = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
startActivityForResult(enalbe,REQUEST_DISCOVERABLE);
2.搜索蓝牙设备
BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter();
_bluetooth.startDiscovery();
3.关闭蓝牙设备
BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter();
_bluetooth.disable();
4.创建蓝牙客户端
BluetoothSocket socket = device.createRfcommSocketToServiceRecord(UUID.fromString(UUID号));
socket.connect();
4.创建蓝牙服务端
BluetoothServerSocket _serverSocket = _bluetooth.listenUsingRfcommWithServiceRecord(服务端名称,UUID.fromeString(UUID号));
BluetoothSocket socket = _serverSocket.accept();
InputStream inputStream = socket.getInputStream();
三、相关代码实现
注:tcp_ip模块需要在系统setting模块中,完成蓝牙的配对,只有配对成功的,才能进行socket通信(具体如何配对和如何自动配对,将在bluetoot3或者4中进行讲解)
AndridManifest.xml
<
manifest
xmlns:android
=
"http://schemas.android.com/apk/res/android"
package
=
"com.example.thecaseforbluetooth"
android:versionCode
=
"1"
android:versionName
=
"1.0"
>
<
uses-sdk
android:minSdkVersion
=
"8"
android:targetSdkVersion
=
"15"
/>
<
uses-permission
android:name
=
"android.permission.BLUETOOTH_ADMIN"
/>
<
uses-permission
android:name
=
"android.permission.BLUETOOTH"
/>
<
application
android:icon
=
"@drawable/ic_launcher"
android:label
=
"@string/app_name"
android:theme
=
"@style/AppTheme"
>
<
activity
android:name
=
".BluetoothActivity"
android:label
=
"@string/title_activity_bluetooth"
>
<
intent-filter
>
<
action
android:name
=
"android.intent.action.MAIN"
/>
<
category
android:name
=
"android.intent.category.LAUNCHER"
/>
</
intent-filter
>
</
activity
>
</
application
>
</
manifest
>
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
xmlns:tools
=
"http://schemas.android.com/tools"
android:id
=
"@+id/LinearLayout1"
android:layout_width
=
"match_parent"
android:layout_height
=
"match_parent"
android:orientation
=
"vertical"
>
<
Button
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:id
=
"@+id/btnSearch"
android:text
=
"查找设备"
/>
<
Button
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:id
=
"@+id/btnExit"
android:text
=
"退出应用"
/>
<
Button
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:id
=
"@+id/btnDis"
android:text
=
"设置可被发现"
/>
<
Button
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:id
=
"@+id/btnserver"
android:text
=
"启动服务端"
/>
<
ToggleButton
android:layout_width
=
"wrap_content"
android:layout_height
=
"wrap_content"
android:id
=
"@+id/tbtnSwitch"
android:text
=
"开/关 蓝牙设备"
/>
<
ListView
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
android:id
=
"@+id/lvDevices"
/>
</
LinearLayout
>
package
com.example.thecaseforbluetooth;
import
java.util.ArrayList;
import
java.util.Set;
import
android.app.Activity;
import
android.bluetooth.BluetoothAdapter;
import
android.bluetooth.BluetoothDevice;
import
android.content.BroadcastReceiver;
import
android.content.Context;
import
android.content.Intent;
import
android.content.IntentFilter;
import
android.os.Bundle;
import
android.view.Menu;
import
android.view.View;
import
android.view.View.OnClickListener;
import
android.widget.AdapterView;
import
android.widget.AdapterView.OnItemClickListener;
import
android.widget.ArrayAdapter;
import
android.widget.Button;
import
android.widget.ListView;
import
android.widget.Toast;
import
android.widget.ToggleButton;
public
class
BluetoothActivity
extends
Activity {
public
Button searchBtn;
//搜索蓝牙设备
public
Button exitBtn;
//退出应用
public
Button discoverBtn;
//设置可被发现
public
ToggleButton openBtn;
//开关蓝牙设备
public
Button serverbtn;
public
ListView listView;
//蓝牙设备清单
public
ArrayAdapter<String> adapter;
public
ArrayList<String> list =
new
ArrayList<String>();
private
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> bondDevices ;
public
Context context ;
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
searchBtn = (Button)findViewById(R.id.btnSearch);
exitBtn = (Button)findViewById(R.id.btnExit);
discoverBtn = (Button)findViewById(R.id.btnDis);
openBtn = (ToggleButton)findViewById(R.id.tbtnSwitch);
serverbtn = (Button)findViewById(R.id.btnserver);
listView = (ListView)findViewById(R.id.lvDevices);
context = getApplicationContext();
adapter =
new
ArrayAdapter<String>(
this
, android.R.layout.simple_list_item_1,list);
listView.setAdapter(adapter);
openBtn.setChecked(
false
);
//注册广播接收信号
IntentFilter intent =
new
IntentFilter();
intent.addAction(BluetoothDevice.ACTION_FOUND);
// 用BroadcastReceiver来取得搜索结果
intent.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
//每当扫描模式变化的时候,应用程序可以为通过ACTION_SCAN_MODE_CHANGED值来监听全局的消息通知。比如,当设备停止被搜寻以后,该消息可以被系统通知給应用程序。
intent.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
//每当蓝牙模块被打开或者关闭,应用程序可以为通过ACTION_STATE_CHANGED值来监听全局的消息通知。
registerReceiver(searchReceiver, intent);
//显示已配对设备以及搜索未配对设备
searchBtn.setOnClickListener(
new
OnClickListener() {
@Override
public
void
onClick(View v) {
// TODO Auto-generated method stub
if
(bluetoothAdapter.isDiscovering()){
bluetoothAdapter.cancelDiscovery();
}
list.clear();
bondDevices = bluetoothAdapter.getBondedDevices();
for
(BluetoothDevice device : bondDevices) {
String str =
" 已配对完成 "
+ device.getName() +
" "
+ device.getAddress();
list.add(str);
adapter.notifyDataSetChanged();
}
bluetoothAdapter.startDiscovery();
}
});
//退出应用
exitBtn.setOnClickListener(
new
OnClickListener() {
@Override
public
void
onClick(View v) {
// TODO Auto-generated method stub
BluetoothActivity.
this
.finish();
}
});
//设置蓝牙设备可发现
discoverBtn.setOnClickListener(
new
OnClickListener() {
@Override
public
void
onClick(View v) {
// TODO Auto-generated method stub
Intent discoverIntent =
new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,
300
);
startActivity(discoverIntent);
}
});
//开关蓝牙设备
openBtn.setOnClickListener(
new
OnClickListener() {
@Override
public
void
onClick(View v) {
// TODO Auto-generated method stub
if
(openBtn.isChecked() ==
true
){
bluetoothAdapter.disable();
}
else
if
(openBtn.isChecked() ==
false
){
bluetoothAdapter.enable();
}
}
});
//作为服务端开启
serverbtn.setOnClickListener(
new
OnClickListener() {
@Override
public
void
onClick(View v) {
// TODO Auto-generated method stub
ServerThread serverThread =
new
ServerThread(bluetoothAdapter, context);
Toast.makeText(context,
"server 端启动"
,
5000
).show();
serverThread.start();
}
});
listView.setOnItemClickListener(
new
ItemClickListener());
}
@Override
public
void
onStart() {
super
.onStart();
// If BT is not on, request that it be enabled.
if
(bluetoothAdapter ==
null
){
Toast.makeText(context,
"蓝牙设备不可用"
,
5000
).show();
}
if
(!bluetoothAdapter.isEnabled()) {
Intent enableIntent =
new
Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableIntent,
3
);
}
}
@Override
public
boolean
onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return
true
;
}
private
final
BroadcastReceiver searchReceiver =
new
BroadcastReceiver() {
@Override
public
void
onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
String action = intent.getAction();
BluetoothDevice device =
null
;
if
(BluetoothDevice.ACTION_FOUND.equals(action)){
device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if
(device.getBondState() == BluetoothDevice.BOND_NONE) {
Toast.makeText(context, device.getName()+
""
,
5000
).show();
String str =
" 未配对完成 "
+ device.getName() +
" "
+ device.getAddress();
if
(list.indexOf(str) == -
1
)
// 防止重复添加
list.add(str);
}
adapter.notifyDataSetChanged();
}
}
};
public
class
ItemClickListener
implements
OnItemClickListener {
@Override
public
void
onItemClick(AdapterView<?> arg0, View arg1,
int
arg2,
long
arg3) {
// TODO Auto-generated method stub
if
(bluetoothAdapter.isDiscovering())
bluetoothAdapter.cancelDiscovery();
String str = list.get(arg2);
String address = str.substring(str.length() -
17
);
BluetoothDevice btDev = bluetoothAdapter.getRemoteDevice(address);
ClientThread clientThread =
new
ClientThread(btDev, context);
clientThread.start();
}}
}
package
com.example.thecaseforbluetooth;
public
interface
Bluetoothprotocol {
public
static
final
String PROTOCOL_SCHEME_L2CAP =
"btl2cap"
;
public
static
final
String PROTOCOL_SCHEME_RFCOMM =
"btspp"
;
public
static
final
String PROTOCOL_SCHEME_BT_OBEX =
"btgoep"
;
public
static
final
String PROTOCOL_SCHEME_TCP_OBEX =
"tcpobex"
;
}
package
com.example.thecaseforbluetooth;
import
java.io.IOException;
import
java.io.InputStream;
import
java.io.OutputStream;
import
java.util.UUID;
import
android.bluetooth.BluetoothAdapter;
import
android.bluetooth.BluetoothServerSocket;
import
android.bluetooth.BluetoothSocket;
import
android.content.Context;
import
android.os.Message;
import
android.util.Log;
import
android.widget.Toast;
public
class
ServerThread
extends
Thread {
public
BluetoothServerSocket mserverSocket;
public
BluetoothAdapter bluetoothAdapter;
public
BluetoothSocket socket;
public
Context context;
public
ServerThread(BluetoothAdapter bluetoothAdapter,Context context) {
this
.bluetoothAdapter = bluetoothAdapter;
this
.context = context;
}
public
void
run() {
try
{
/* 创建一个蓝牙服务器
* 参数分别:服务器名称、UUID */
mserverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(Bluetoothprotocol.PROTOCOL_SCHEME_RFCOMM,
UUID.fromString(
"00001101-0000-1000-8000-00805F9B34FB"
));
// /* 接受客户端的连接请求 */
socket = mserverSocket.accept();
//下面代码作者偷懒,读写另外起一个线程最好
//接收数据
byte
[] buffer =
new
byte
[
1024
];
int
bytes;
InputStream mmInStream =
null
;
try
{
mmInStream = socket.getInputStream();
}
catch
(IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.out.println(
"zhoulc server"
);
while
(
true
){
if
( (bytes = mmInStream.read(buffer)) >
0
)
{
byte
[] buf_data =
new
byte
[bytes];
for
(
int
i=
0
; i<bytes; i++)
{
buf_data[i] = buffer[i];
}
String s =
new
String(buf_data);
System.out.println(s+
"zhoulc server is in"
);
}
}
}
catch
(Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
package
com.example.thecaseforbluetooth;
import
java.io.IOException;
import
java.io.OutputStream;
import
java.util.UUID;
import
android.bluetooth.BluetoothDevice;
import
android.bluetooth.BluetoothSocket;
import
android.content.Context;
import
android.widget.Toast;
public
class
ClientThread
extends
Thread {
public
BluetoothSocket socket;
public
BluetoothDevice device;
public
Context context;
public
ClientThread(BluetoothDevice device,Context context){
this
.device = device;
this
.context = context;
}
public
void
run() {
try
{
//创建一个Socket连接:只需要服务器在注册时的UUID号
socket = device.createRfcommSocketToServiceRecord(UUID.fromString(
"00001101-0000-1000-8000-00805F9B34FB"
));
//连接
socket.connect();
//下面代码作者偷懒,读写另外起一个线程最好
//发送数据
if
(socket ==
null
)
{
Toast.makeText(context,
"链接失败"
,
5000
).show();
return
;
}
System.out.println(
"zhoulc client"
);
while
(
true
){
try
{
System.out.println(
"zhoulc client is in"
);
String msg =
"hello everybody I am client"
;
OutputStream os = socket.getOutputStream();
os.write(msg.getBytes());
}
catch
(IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
catch
(IOException e)
{
e.printStackTrace();
}
}
}
- Android Bluetooth 学习(2)应用层实现蓝牙设备查找、tcp_ip通信
- Android Bluetooth蓝牙开发:Bluetooth蓝牙设备配对Paired Bluetooth Devices(2)
- Android Bluetooth蓝牙开发:发现Bluetooth蓝牙设备(1)
- Android Bluetooth 学习(3)蓝牙设备之间自动配对
- Android BlueTooth蓝牙通信
- android 蓝牙 通信 bluetooth
- android 蓝牙 通信 bluetooth
- 蓝牙(Bluetooth)设备查找、蓝牙VC源代码
- Android Bluetooth 蓝牙通信(一)
- Android Bluetooth 蓝牙通信(二)
- Android 蓝牙Bluetooth搜索设备。
- Bluetooth--- android 蓝牙通信编程
- Android移动开发-蓝牙(BlueTooth)设备检测连接的实现
- Android Bluetooth蓝牙开发:Bluetooth蓝牙设备之间的连接建立(3)
- Android Bluetooth蓝牙开发:Bluetooth蓝牙设备之间数据传输(4)
- Android BLE与终端通信(二)——Android Bluetooth基础科普以及搜索蓝牙设备显示列表
- Android BLE与终端通信(二)——Android Bluetooth基础搜索蓝牙设备显示列表
- android 蓝牙Bluetooth 4.2.2打开蓝牙实现
- JSP中文乱码
- UDL使用
- 使用vertical-align实现input和img对齐
- Map集合
- reserve函数
- Android Bluetooth 学习(2)应用层实现蓝牙设备查找、tcp_ip通信
- 小白带你玩VMware(二)Linux系统的安装(以Linux-Mint为例)
- 数据库范式的理解
- C语言进阶
- iOS工作遇到的困难以及解决方案
- IO流
- Robotium对象识别
- mactex自动更新tex live utilities错误
- Java GC的工作原理