藍牙
是一種無線技術標準,可實現固定設備、移動設備和樓宇個人域網之間的短距離數據交換
關於藍牙的權限主要涉及到下面四個:
BLUETOOTH:允許配對的設備進行連接
BLUETOOTH_ADMIN:允許搜索和配對設備
ACCESS_COARSE_LOCATION:廣播接收器接收BluetoothDevice.ACTION_FOUND廣播需要改權限
ACCESS_FINE_LOCATION
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
一些介紹
BluetoothManager 藍牙管理類,管理BluetoothAdapter。主要負責管理藍牙的本地連接。
BluetoothAdapter 藍牙適配器類:代表本藍牙設備
BluetoothDevice 藍牙設備,配對後的遠程藍牙設備.
BluetoothServiceSocket 服務端連接類
BluetoothSocket:客戶端連接類
UUID(universal unique identifier , 全局唯一標識符)
格式如下:UUID格式一般是”xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”,可到http://www.uuidgenerator.com 申請。UUID分爲5段,是一個8-4-4-4-12的字符串,這個字符串要求永不重複。藍牙建立連接時雙方必須使用固定的UUID
例如:文件傳輸服務
OBEXFileTransferServiceClass_UUID = ‘{00001106-0000-1000-8000-00805F9B34FB}’
真機測試效果
代碼案例
xml佈局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".client.BlueClient">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:id="@+id/open"
android:text="打開藍牙"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/close"
android:text="關閉藍牙"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/search"
android:text="掃描藍牙"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:id="@+id/pair"
android:text="已配對的藍牙"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="wrap_content">
<Button
android:id="@+id/server"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="服務器收到消息"
/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@+id/nearblue"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"></ListView>
<ListView
android:id="@+id/alerady"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"></ListView>
</LinearLayout>
</LinearLayout>
適配器xml佈局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/blueid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
/>
</LinearLayout>
適配器中的代碼
package com.example.bluetooth.client;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import com.example.bluetooth.R;
import java.util.ArrayList;
public class Mybondedadpater extends BaseAdapter {
private Context context;
private ArrayList<BluetoothDevice> list;
public Mybondedadpater(Context context, ArrayList<BluetoothDevice> list) {
this.context = context;
this.list = list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Viewholder viewholder;
if (convertView==null){
convertView = LayoutInflater.from(context).inflate(R.layout.bonded_item, null);
viewholder = new Viewholder();
viewholder.blue = convertView.findViewById(R.id.blueid);
convertView.setTag(viewholder);
}else {
viewholder = (Viewholder) convertView.getTag();
}
viewholder.blue.setText(list.get(position).getName());
return convertView;
}
class Viewholder{
TextView blue;
}
}
activity代碼
package com.example.bluetooth.client;
import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import com.example.bluetooth.R;
import com.example.bluetooth.Server.BlueSever;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Set;
import java.util.UUID;
public class BlueClient extends AppCompatActivity {
private Button open;
private Button close;
private Button search;
private Button pair;
private ListView nearblue;
private ListView alerady;
private BluetoothAdapter adapter;
private ArrayList<BluetoothDevice> list = new ArrayList<>();
private Mybondedadpater mybondedadpater;
private Mybondedadpater mysearchadpater;
private BluetoothDevice bluetoothDevice;
private ArrayList<BluetoothDevice> devices = new ArrayList<>();
private Mybroad mybroad;
private Button server;
private Handler handler =new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what==101){
Toast.makeText(BlueClient.this, msg.obj.toString()+"連接成功", Toast.LENGTH_SHORT).show();
Log.i("連接成功", "handleMessage: "+msg.obj.toString());
}else if (msg.what==102){
Toast.makeText(BlueClient.this, "接收到數據"+msg.obj.toString(), Toast.LENGTH_SHORT).show();
Log.i("接收到數據", "handleMessage: "+msg.obj.toString());
}
}
};
private UUID uuid = UUID.fromString("00001106-0000-1000-8000-00805F9B34FB");
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_blue_client);
open = (Button) findViewById(R.id.open);
close = (Button) findViewById(R.id.close);
search = (Button) findViewById(R.id.search);
pair = (Button) findViewById(R.id.pair);
nearblue = (ListView) findViewById(R.id.nearblue);
alerady = (ListView) findViewById(R.id.alerady);
server = (Button) findViewById(R.id.server);
String[] s={Manifest.permission.BLUETOOTH,Manifest.permission.BLUETOOTH_ADMIN,Manifest.permission.ACCESS_FINE_LOCATION,Manifest.permission.ACCESS_COARSE_LOCATION};
if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
requestPermissions(s,101);
}
BluetoothManager manager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
adapter = manager.getAdapter();
//已經配對的藍牙的適配器
mybondedadpater = new Mybondedadpater(this, list);
alerady.setAdapter(mybondedadpater);
//搜索的藍牙
mysearchadpater = new Mybondedadpater(this,devices);
nearblue.setAdapter(mysearchadpater);
//註冊廣播
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
mybroad = new Mybroad();
registerReceiver(mybroad,intentFilter);
//打開藍牙
open.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(BluetoothAdapter.ACTION_REQUEST_ENABLE);
intent.setAction(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
startActivity(intent);
}
});
//關閉藍牙
close.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
adapter.disable();
}
});
//搜索藍牙
search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
devices.clear();
adapter.startDiscovery();
}
});
//接收他人消息
server.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(BluetoothAdapter.ACTION_REQUEST_ENABLE);
intent.setAction(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
startActivity(intent);
new Thread(new Runnable() {
@Override
public void run() {
try {
BluetoothServerSocket serverSocket = adapter.listenUsingInsecureRfcommWithServiceRecord(adapter.getName(), uuid);
while (true){
BluetoothSocket socket = serverSocket.accept();
Message message = new Message();
message.what=101;
message.obj=socket.getRemoteDevice().getName();
handler.sendMessage(message);
new MyServerThread(socket,handler).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
});
//已經配對的藍牙
pair.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
list.clear();
Set<BluetoothDevice> bondedDevices = adapter.getBondedDevices();
list.addAll(bondedDevices);
mybondedadpater.notifyDataSetChanged();
}
});
//進行配對
nearblue.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
devices.get(position).createBond();
}
});
//已經配對的開啓線程發送數據
alerady.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
BluetoothDevice device = list.get(position);
try {
BluetoothSocket socket = device.createInsecureRfcommSocketToServiceRecord(uuid);
new MyClientThread(socket,"hello!").start();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
class Mybroad extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (intent.getAction().equals(BluetoothDevice.ACTION_FOUND)){
if (device!=null){
devices.add(device);
mysearchadpater.notifyDataSetChanged();
}
}
}
}
class MyClientThread extends Thread{
private BluetoothSocket socket;
private String message;
public MyClientThread(BluetoothSocket socket, String message) {
this.socket = socket;
this.message = message;
}
@Override
public void run() {
super.run();
try {
socket.connect();
if (socket.isConnected()){
socket.getOutputStream().write(message.getBytes());
}else {
Log.i("xxx", "run: 連接失敗");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class MyServerThread extends Thread{
BluetoothSocket socket;
Handler handler;
public MyServerThread(BluetoothSocket socket, Handler handler) {
this.socket = socket;
this.handler = handler;
}
@Override
public void run() {
super.run();
try {
InputStream inputStream = socket.getInputStream();
byte[] b = new byte[1024];
int read = inputStream.read(b);
String s = new String(b, 0, read);
Message message = new Message();
message.what=102;
message.obj=s;
handler.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}