赞
踩
1.蓝牙的基本操作
蓝牙权限
android.permission.BLUETOOTH
//允许程序连接到已配对的蓝牙设备,请求连接/接收连接/传输数据需要改权限, 主要用于对配对后进行操作.
android.permission.BLUETOOTH_ADMIN
//允许程序发现和配对蓝牙设备, 该权限用来管理蓝牙设备, 有了这个权限, 应用才能使用本机的蓝牙设备.
BluetoothAdapter
BluetoothAdapter代表了移动设备的本地的蓝牙适配器, 通过该蓝牙适配器可以对蓝牙进行基本操作
//获取蓝牙适配器对象.
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
开关蓝牙(推荐请求用户打开)
//直接打开
mBluetoothAdapter.enable();
//请求用户打开蓝牙
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivity(intent);
//关闭蓝牙
mBluetoothAdapter.disable();
蓝牙是否可用
//蓝牙是否可用,返回boolean值 true可用 false不可用
mBluetoothAdapter.isEnabled();
蓝牙可被发现及时间设置
//可被发现
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 600);
//默认120秒
startActivity(intent);
搜索蓝牙
蓝牙搜索在android6.0以后需要加上一个模糊定位的权限,并动态申请,虽然有些手机不加权限也能搜索到蓝牙设备,
但是大多会出现蓝牙一直等待搜索,蓝牙列表无法弹出。
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
//扫描蓝牙的方法,返回boolean值
//开始扫描
mBluetoothAdapter.startDiscovery();
//是否正在扫描
mBluetoothAdapter.isDiscovering();
//停止扫描
mBluetoothAdapter.cancelDiscovery();
startDiscovery()是一个异步方法,在搜索蓝牙设备的过程中,系统可能会发送以下三个广播:
ACTION_DISCOVERY_START(开始搜索)
ACTION_DISCOVERY_FINISHED(搜索结束)
ACTION_FOUND(找到设备)。
蓝牙地址
//获取本地蓝牙地址 返回String
mBluetoothAdapter.getAddress();
//检查蓝牙地址 蓝牙地址字母必须大写, 例如 : "00:43:A8:23:10:F0";
mBluetoothAdapter.checkBluetoothAddress(String address);
获取远程蓝牙设备
BluetoothDevice 代表了一个远程的蓝牙设备, 通过这个类可以查询远程设备的物理地址, 名称, 连接状态等信息;
//作用 : 根据蓝牙的物理地址获取远程的蓝牙设备, 如果地址不合法, 就会产生异常;
//返回值 : 获取到的BluetoothDevice对象;
public BluetoothDevice getRemoteDevice(String address);
蓝牙名字
//设置名字
mBluetoothAdapter.setName();
//得到名字
mBluetoothAdapter.getName();
创建监听
//创建一个监听Rfcommon端口的蓝牙监听, 使用accept()方法监听, 并获取BluetoothSocket对象;
// 该系统会根据一个服务名称(name)和唯一的识别码(uuid)来创建一个SDP服务,
// 远程蓝牙设备可以根据唯一的UUID来连接这个SDP服务器;
public BluetoothServerSocket listenUsingRfcommonWithServiceRecord(String name, UUID uuid);
// 参数 : name : SDP服务器名称, UUID, SDP记录下的UUID;
// 返回值 : 正在监听蓝牙端口;
UUID
在蓝牙中,每个服务和服务属性都唯一地由全局唯一标识符,Universally Unique Identifier(UUID)来校验。UUID相当于Socket的端口,
而蓝牙地址相当于Socket的IP。两个蓝牙设备进行连接时需要使用同一个UUID, 这是一个服务的唯一标识。
于普通蓝牙适配器和android手机蓝牙模块连接的UUID
//手机连接的UUID
//设备连接的UUID由厂商决定。
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
其他UUID可看http://blog.csdn.net/spmno/article/details/6931941
蓝牙连接
蓝牙客户端 BluetoothSocket,蓝牙服务端 BluetoothServerSocket 匹配成功然后使用connect()方法连接
2.具体代码(扫描蓝牙)没有其他蓝牙设备,使用两部手机替代。
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:onClick="startBluetooth"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="开启蓝牙"/>
<Button
android:onClick="searchBluetooth"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="搜索蓝牙"/>
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
两个按钮,一个ListView显示蓝牙设备名字
初始画数据,设置适配器
ListView mListView;
BluetoothAdapter mBluetoothAdapter;
ArrayAdapter<String> mAdapter;
//存储蓝牙设备名字
List<String> deviceNames = new ArrayList<>();
//存储蓝牙设备
List<BluetoothDevice> devices = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
mListView = (ListView) findViewById(R.id.listview);
mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, deviceNames);
mListView.setAdapter(mAdapter);
}
开启蓝牙
//按钮点击事件 开启蓝牙
public void startBluetooth(View view) {
//设置蓝牙可被发现
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
//设置可被发现的时间 1200秒
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,1200);
startActivity(intent);
}
搜索蓝牙 需要动态权限
//搜索蓝牙
public void searchBluetooth(View view) {
//蓝牙开启状态
if (mBluetoothAdapter.isEnabled()) {
//动态权限
if (Build.VERSION.SDK_INT > 23) {
int check = checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION);
if (check == PackageManager.PERMISSION_GRANTED) {
//开始扫描
startSearch();
} else {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION},1);
}
} else {
startSearch();
}
startSearch();
} else {
//如果蓝牙没开启
startBluetooth(view);
}
}
//开始搜索蓝牙
private void startSearch() {
//如果没在搜索
if (!mBluetoothAdapter.isDiscovering()) {
//搜索蓝牙设备
mBluetoothAdapter.startDiscovery();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode ==1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
startSearch();
} else {
Toast.makeText(this, "必须获取地理位置才能扫描蓝牙设备", Toast.LENGTH_SHORT).show();
}
}
记得在AndroidManifest文件中在加上模糊地理位置权限
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
扫描蓝牙时,系统会发送广播,通过广播接收者获得扫描到的蓝牙设备
//广播接收者
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//如果发现蓝牙设备
if (intent.getAction().equals(BluetoothDevice.ACTION_FOUND)) {
//BluetoothDevice 代表了一个远程的蓝牙设备, 通过这个类可以查询远程设备的状态信息;
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//取得蓝牙设备的名字(名字可能为空,空则设置名字为匿名) 以便显示到ListView
String name = device.getName() == null ? "匿名" : device.getName();
deviceNames.add(name);
mAdapter.notifyDataSetChanged();
devices.add(device);
}
}
};
注册广播接收者
@Override
protected void onResume() {
super.onResume();
//注册
registerReceiver(receiver, new IntentFilter(BluetoothDevice.ACTION_FOUND));
}
@Override
protected void onPause() {
super.onPause();
//解绑
unregisterReceiver(receiver);
}
暂时效果
3.具体代码(蓝牙连接)
两个蓝牙手机链接,需要有服务器客户端
UUID
//手机连接的UUID
//设备连接的UUID由厂商决定。
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
服务端
class BluetoothServer extends Thread {
@Override
public void run() {
super.run();
//服务
BluetoothServerSocket bluetoothServerSocket;
try {
bluetoothServerSocket = mBluetoothAdapter.listenUsingInsecureRfcommWithServiceRecord(
mBluetoothAdapter.getName(),uuid);
BluetoothSocket socket = bluetoothServerSocket.accept();
while (socket.isConnected()) {
InputStream inputStream = socket.getInputStream();
int len = 0;
byte[] buffer = new byte[1024];
while ((len = inputStream.read(buffer)) != -1) {
Log.e("TAG",new String(buffer,0,len,"utf-8"));
}
}
//将服务端关闭,不可能1对多,所以,只要获取了客户端,那么服务端就可以关闭了
bluetoothServerSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
然后在开启蓝牙后开启服务,即在searchBluetooh中调用startServer方法
BluetoothServer server;
public void startServer() {
if (server == null) {
server = new BluetoothServer();
server.start();
}
}
客户端
MainActivity 实现OnItemClickListener 然后重写方法
mListView.setOnItemClickListener(this);
//客户端 搜索出蓝牙后,ListView Item点击事件 链接服务端
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//点击列表,去请求服务器
final BluetoothDevice device = devices.get(position);
new Thread() {
@Override
public void run() {
super.run();
try {
BluetoothSocket socket = device.createInsecureRfcommSocketToServiceRecord(uuid);
//链接
socket.connect();
OutputStream os = socket.getOutputStream();
os.write("连接蓝牙服务器成功".getBytes());
os.flush();
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。