本文章經(jīng)典藍牙開發(fā)目錄:
1师郑、權(quán)限申請
2、開啟藍牙
3漫蛔、掃描藍牙
4嗜愈、配對藍牙
5、連接藍牙
6莽龟、通信(實現(xiàn)雙向通信)(我用的兩個手機通過藍牙進行通信的~)
7蠕嫁、關(guān)閉各種通信
Android 藍牙開發(fā) 經(jīng)典藍牙和低功耗藍牙(一)
Android 低功耗藍牙開發(fā)(三)
先看一串效果圖
小米LTE作為客戶端,小米5作為服務(wù)端
雙方配對
客戶端向服務(wù)端發(fā)送數(shù)據(jù)
服務(wù)端向客戶端回傳數(shù)據(jù)
==================開始正文==============
第一步毯盈,權(quán)限申請
1剃毒、Android6.0搜索周圍的藍牙設(shè)備,需要位置權(quán)限 ACCESS_COARSE_LOCATION 和ACCESS_FINE_LOCATION 其中的一個奶镶,并且將手機的位置服務(wù)(定位 GPS)打開迟赃。
清單文件:
<!-- 使用藍牙的權(quán)限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<!-- 掃描藍牙設(shè)備或者操作藍牙設(shè)置 -->
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!--模糊定位權(quán)限,僅作用于6.0+-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<!--精準定位權(quán)限厂镇,僅作用于6.0+-->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
權(quán)限申請工具類:LocalUtils.java
1、這個類用來檢查GPS和定位權(quán)限左刽,回調(diào)在Activity里面捺信。
public class LocalUtils {
//申請權(quán)限
public static final int permission_LocationCode = 101;
//打開gps定位
public static final int open_GPSCode = 102;
static String[] permissionsIndex;
/**
* 此方法用來檢查gps和定位權(quán)限,先檢查gps是否打開,在檢查是否有定位權(quán)限
* @param activity 上下文對象
* @param permissions 權(quán)限的名稱
* @return
*/
public static boolean checkLocalPermissiion(Activity activity, String[] permissions) {
permissionsIndex = permissions;
if (checkGPSIsOpen(activity)) {
return checkPermissions(activity);
} else {
Toast.makeText(activity, "需要打開GPS", Toast.LENGTH_SHORT).show();
goToOpenGPS(activity);
}
return false;
}
/**
* 檢查GPS是否打開
*
*/
public static boolean checkGPSIsOpen(Activity activity) {
LocationManager locationManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
if (locationManager == null)
return false;
return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
/**
* 檢查權(quán)限并申請權(quán)限
*/
public static boolean checkPermissions(final Activity activity) {
List<String> permissionDeniedList = new ArrayList<>();
for (String permission : permissionsIndex) {
int permissionCheck = ContextCompat.checkSelfPermission(activity, permission);
if (permissionCheck == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
permissionDeniedList.add(permission);
}
}
if (!permissionDeniedList.isEmpty()) {
String[] deniedPermissions = permissionDeniedList.toArray(new String[permissionDeniedList.size()]);
ActivityCompat.requestPermissions(activity, deniedPermissions, permission_LocationCode);
}
return false;
}
/**
* 去手機設(shè)置打開GPS
*
* @param activity
*/
public static void goToOpenGPS(Activity activity) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
activity.startActivityForResult(intent, open_GPSCode);
}
}
在Activity里面回調(diào):
//GPS
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case LocalUtils.open_GPSCode://檢查是否手機打開定位
if (LocalUtils.checkGPSIsOpen(this)) {
LocalUtils.checkLocalPermissiion(this, permissions);//檢查定位權(quán)限
} else {
LocalUtils.goToOpenGPS(this);//打開GPS
}
break;
}
}
/**
* 權(quán)限回調(diào)
*/
@Override
public final void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case LocalUtils.permission_LocationCode://是否打開允許定位權(quán)限
if (grantResults.length > 0) {
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
initClassica();//初始化經(jīng)典藍牙
}
}
}
break;
}
}
ps:第一步是比較簡單的哦~~看看就明白了
第二步迄靠,開啟藍牙
1秒咨、獲取BluetoothAdapter
獲取BluetoothAdapter兩種方式:
方式一:
BluetoothManager systemService = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
BluetoothAdapter bluetoothAdapter = systemService.getAdapter();
方式二:
BluetoothAdapter bluetoothAdapter =BluetoothAdapter.getDefaultAdapter();
2、判斷設(shè)備是否支持藍牙
如果 BluetoothAdapter.getDefaultAdapter()==null掌挚,不支持雨席,否則支持。
3吠式、開啟藍牙
/**
* 自動打開藍牙(同步)
* 這個方法打開藍牙會彈出提示
* 需要在onActivityResult 方法中判斷resultCode == RESULT_OK true為成功
*/
public void openBlueSync(Activity activity, int requestCode) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
activity.startActivityForResult(intent, requestCode);
}
ps:第二步陡厘,嗯嗯嗯....我就開始百度了~~~
第三步,掃描藍牙
1特占、掃描藍牙
/**
* 掃描的方法 返回true 掃描成功
* 通過接收廣播獲取掃描到的設(shè)備
* @return
*/
public boolean scanBlueTooth() {
//當前是否在掃描糙置,如果是就取消當前的掃描,重新掃描
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
//此方法是個異步操作是目,一般搜索12秒
return bluetoothAdapter.startDiscovery();
}
2谤饭、取消掃描
/**
* 取消掃描藍牙
* @return true 為取消成功
*/
public boolean cancelScanBule() {
return bluetoothAdapter.cancelDiscovery();
}
3、廣播接收掃描的結(jié)果
系統(tǒng)自動回發(fā)送廣播懊纳,告訴我們揉抵,掃描出來的藍牙設(shè)備。
先定義接口嗤疯,來回調(diào)廣播中的結(jié)果(在activity接收結(jié)果的哦~~~)
ClientCallBack.java
public interface ClientCallBack {
//開始掃描
void onScanStarted();
//掃描結(jié)束
void onScanFinished();
//掃描中
void onScanning(BluetoothDevice device);
//配對請求
void onBondRequest();
//配對成功
void onBondSuccess(BluetoothDevice device);
//正在配對
void onBonding(BluetoothDevice device);
//配對失敗
void onBondFail(BluetoothDevice device);
//連接成功
void onConnectSuccess();
//連接失敗
void onConnectFail(String errorMsg);
//連接關(guān)閉
void onConnectClose();
}
BlueReceiver.java
public class BlueReceiver extends BroadcastReceiver {
private String pin = "0000"; //此處為你要連接的藍牙設(shè)備的初始密鑰功舀,一般為1234或0000
private static final String TAG = "mcy_Receiver";
private ClientCallBack callBack;
public BlueReceiver(ClientCallBack callBack) {
this.callBack = callBack;
}
public void setCallBack(ClientCallBack callBack){
this.callBack=callBack;
}
//廣播接收器,當遠程藍牙設(shè)備被發(fā)現(xiàn)時身弊,回調(diào)函數(shù)onReceiver()會被執(zhí)行
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d(TAG, "action:" + action);
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(callBack==null){
return;
}
switch (action) {
case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
callBack.onScanStarted();
break;
case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
callBack.onScanFinished();
break;
case BluetoothDevice.ACTION_FOUND:
callBack.onScanning(device);
break;
case BluetoothDevice.ACTION_PAIRING_REQUEST:
callBack.onBondRequest();
break;
case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
switch (device.getBondState()) {
case BluetoothDevice.BOND_NONE:
callBack.onBondFail(device);
break;
case BluetoothDevice.BOND_BONDING:
callBack.onBonding(device);
break;
case BluetoothDevice.BOND_BONDED:
callBack.onBondSuccess(device);
break;
}
break;
}
}
}
為了方便統(tǒng)一管理辟汰,把藍牙的操作寫在服務(wù)里面,ClassicsBlueToothService.java阱佛,因此帖汞,把廣播注冊在服務(wù)里面,生命周期跟著服務(wù)走~~
public class ClassicsBlueToothService extends Service {
private IntentFilter filter;
private BlueReceiver pinBlueReceiver;
@Override
public void onCreate() {
super.onCreate();
//獲取藍牙適配器
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//注冊廣播
//藍牙廣播,系統(tǒng)自動發(fā)送廣播,只要設(shè)置制定的 action 即可
filter = new IntentFilter();
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//開始掃描
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//結(jié)束掃描
filter.addAction(BluetoothDevice.ACTION_FOUND);//發(fā)現(xiàn)設(shè)備
filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);//發(fā)起配對請求
filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//配對狀態(tài)
pinBlueReceiver = new BlueReceiver(blueCallBack);
registerReceiver(pinBlueReceiver, filter);//注冊廣播
}
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(pinBlueReceiver);
}
........還有很多代碼凑术,就不全部拿出來了翩蘸,去github上看吧
}
ps:第三步的廣播和服務(wù)的結(jié)合使用搬出來了,好久沒用了淮逊,又從頭過一遍催首,才寫出來的~~~
第四步,配對藍牙
配對:
/**
* 配對(配對成功與失敗通過廣播返回)
* P古簟@扇巍!彈出配對框
*
* @param device
*/
public void pinBlueTooth(BluetoothDevice device) {
if (device == null) {
Log.e("mcy", "設(shè)備不可以為空");
return;
}
//配對之前把掃描關(guān)閉
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
//判斷設(shè)備是否配對备籽,沒有配對在配舶治,配對了就不需要配了
if (device.getBondState() == BluetoothDevice.BOND_NONE) {//BOND_NONE 沒有配對狀態(tài)
Log.d("mcy", "attemp to bond:" + device.getName());
try {
boolean returnValue = device.createBond();
Log.e("是否配對成功:", "" + returnValue);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("mcy", "配對失敗");
}
}
}
取消配對:
/**
* 取消配對(取消配對成功與失敗通過廣播返回 也就是配對失旝蕹ぁ)
*
* @param device
*/
public void cancelPinBuleTooth(BluetoothDevice device) {
if (device == null) {
Log.d("mcy", "設(shè)備不可以為空");
return;
}
//判斷設(shè)備是否配對婆排,沒有配對就不用取消了
if (device.getBondState() != BluetoothDevice.BOND_NONE) {
Log.d("mcy", "配對--" + device.getName());
try {
Method removeBondMethod = device.getClass().getMethod("removeBond");
Boolean returnValue = (Boolean) removeBondMethod.invoke(device);
returnValue.booleanValue();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("mcy", "取消配對失敗");
}
}
}
ps:第四步僚祷,嗯嗯嗯酷师,還是比較好看的,只是操作藍牙
第五步惜浅,連接藍牙
這里說一下 uuid 的問題瘫辩,要想進行通信,客戶端和服務(wù)端必須一致坛悉,否則連接失敗伐厌,因為我用的手機進行的通訊,所有吹散,我寫了雙向通信弧械,既可以寫也可以讀。
連接藍牙
注意:在連接藍牙的同時空民,開啟一個子線程刃唐,用來寫入數(shù)據(jù)!=缧;ⅰ!
/**
* @param uuid 用戶指定的 uuid 浊猾,可隨意寫抖甘,只要格式對就行
* @param device 連接的設(shè)備
*/
public void connectionBlueTooth(String uuid, BluetoothDevice device) {
try {
bluetoothSocket = device.createRfcommSocketToServiceRecord(UUID.fromString(uuid));
if (bluetoothSocket != null && !bluetoothSocket.isConnected()) {
sendDataThread = new ClientThread(bluetoothSocket, blueCallBack);
sendDataThread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
ClientThread.java
public class ClientThread extends Thread {
private static final String TAG = "mcy";
private ClientCallBack callBack;
private BluetoothSocket bluetoothSocket = null;
private Handler handler;
private OutputStream outputStream;
public ClientThread(BluetoothSocket bluetoothSocket, ClientCallBack callBack) {
this.callBack = callBack;
this.bluetoothSocket = bluetoothSocket;
}
/**
* 寫數(shù)據(jù)
*
* @param data
*/
public void write(byte[] data) {
Message message = new Message();
message.obj = data;
handler.sendMessage(message);
}
/**
* 關(guān)閉各種連接連接
*/
public void closeSocket() {
try {
outputStream.close();
bluetoothSocket.close();
callBack.onConnectClose();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
bluetoothSocket.connect();
outputStream = bluetoothSocket.getOutputStream();//讀取需要發(fā)送的的數(shù)據(jù)
Looper.prepare();
handler = new Handler() {
@Override
public void handleMessage(Message msg) {
try {
byte[] data = (byte[]) msg.obj;
outputStream.write(data);
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
};
callBack.onConnectSuccess();
Looper.loop();
} catch (IOException e) {
callBack.onConnectFail(e.getMessage());
}
}
}
ps:第五步,有難度葫慎,光這個uuid衔彻,我就研究了好久,到底是個什么玩意偷办,哼艰额、、椒涯、頭大日漸變少了~~
第六步柄沮,通信(實現(xiàn)雙向通信)
1、客戶端發(fā)送數(shù)據(jù)
/**
* 寫數(shù)據(jù)
*/
public void sendData(byte[] data) {
if (sendDataThread != null) {
sendDataThread.write(data);
}
}
2废岂、客戶端接收數(shù)據(jù)
/**
* 讀數(shù)據(jù)
*/
public void readListern(String name, String uuid, ServiceCallback callBack) {
acceptThread = new AcceptThread(name, uuid, bluetoothAdapter, callBack);
acceptThread.start();
}
定義一個接口祖搓,來監(jiān)聽,收到數(shù)據(jù)的狀態(tài)
public interface ServiceCallback {
//連接成功
void onConnectSuccess();
//連接失敗
void onConnectFail(String errorMsg);
//連接關(guān)閉
void onConnectClose();
//接收到的數(shù)據(jù)
void onResultMessage(byte[] data);
}
開啟一個子線程,用來監(jiān)聽服務(wù)端發(fā)過來的數(shù)據(jù)
public class AcceptThread extends Thread {
private static final String TAG = "mcy";
private ServiceCallback callBack;
private BluetoothServerSocket serverSocket = null;
private InputStream inputStream;
private BufferedInputStream bufferedInputStream;
private byte[] data;
public AcceptThread(String name, String uuid, BluetoothAdapter bluetoothAdapter, ServiceCallback callBack) {
this.callBack = callBack;
try {
serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(name, UUID.fromString(uuid));
} catch (IOException e) {
e.printStackTrace();
callBack.onConnectFail(e.getMessage());
}
}
/**
* 關(guān)閉各種流和通信的socket
*/
public void closeSocket() {
try {
inputStream.close();
bufferedInputStream.close();
serverSocket.close();
callBack.onConnectClose();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
final BluetoothSocket bluetoothSocket = serverSocket.accept();
callBack.onConnectSuccess();
inputStream = bluetoothSocket.getInputStream();//獲取服務(wù)端發(fā)來的消息
bufferedInputStream = new BufferedInputStream(inputStream);
while (true) {
int available =0;
wh:
lable==0){
available=inputStream.available();
}
data = new byte[available];
bufferedInputStream.read(data);
callBack.onResultMessage(data);//回傳數(shù)據(jù)
}
} catch (IOException e) {
callBack.onConnectFail(e.getMessage());
e.printStackTrace();
}
}
}
ps:第六步湖苞,昨晚這一步拯欧,基本上做完了~~頭發(fā)沒了、袒啼、哈扮、
第七步纬纪,關(guān)閉各種通信
在第五步和第六步的子線程里均有關(guān)閉通信的方法
/**
* 寫數(shù)據(jù)斷開連接
*
* @return
*/
public void cancleConnecion() {
sendDataThread.closeSocket();
}
/**
* 寫數(shù)據(jù)斷開連接
*
* @return
*/
public void cancleServiceConnecion() {
acceptThread.closeSocket();
}
好了蚓再,放大招滑肉,請看activity和service
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private static final String TAG = "mcy";
private TextView textView;
private TextView textView2;
private TextView textView3;
private EditText editTxt;
String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION};
private final int openBTCode = 100;
// ----------------經(jīng)典藍牙------------------
private ClassicsBlueToothService.ClassicaBlueToothBind classicaBTBind;
private ServiceConnection classicaConnection;
private List<BluetoothDevice> devicesList = new ArrayList<>();
private ClientCallBack blueCallBack;
private String text = "";
private String uuid = "6db14d27-04f1-4df8-98ca-356dfc16ee43";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
//檢查權(quán)限 >6.0以上版本需要動態(tài)的申請定位權(quán)限,< 6.0 清單文件聲明了即可
if (LocalUtils.checkLocalPermissiion(this, permissions)) {
initClassica();
}
}
private void initView() {
textView = findViewById(R.id.textView);
textView2 = findViewById(R.id.textView2);
textView3 = findViewById(R.id.textView3);
editTxt = findViewById(R.id.editTxt);
findViewById(R.id.button5).setOnClickListener(this);
findViewById(R.id.button11).setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button5://經(jīng)典--寫數(shù)據(jù)
text = editTxt.getText().toString();
classicaBTBind.sendData(text.getBytes());
break;
case R.id.button11://低功耗--發(fā)送數(shù)據(jù)
break;
}
}
private void initClassica() {
blueCallBack = new ClientCallBack() {
@Override
public void onScanStarted() {
Log.e("mcy", "開始掃描");
}
@Override
public void onScanFinished() {
Log.e("mcy", "結(jié)束掃描");
}
@Override
public void onScanning(BluetoothDevice device) {
Log.e("mcy", "掃描到設(shè)備-->" + device.getName());
if (!devicesList.contains(device)) {
//將設(shè)備加入列表數(shù)據(jù)中
devicesList.add(device);
}
textView.setText(textView.getText() + "\n" + device.getName());
Log.e(TAG, "" + device.getName());
//已配對的藍牙
if (device.getBondState() == BluetoothDevice.BOND_BONDED) {//BOND_BONDED 已經(jīng)配對狀態(tài)
textView2.setText(textView2.getText() + "\n" + device.getName());
} else {
classicaBTBind.pinBlueTooth(devicesList.get(0));
}
}
@Override
public void onBondRequest() {
Log.e("mcy", "開始配對");
}
@Override
public void onBondFail(BluetoothDevice device) {
Log.e("mcy", "取消配對");
}
@Override
public void onBonding(BluetoothDevice device) {
Log.e("mcy", "配對中");
}
@Override
public void onBondSuccess(BluetoothDevice device) {
Log.e("mcy", "配對成功");
classicaBTBind.connectionBlueTooth(uuid, device);
//registReadListener(); //測試使用,雙端通訊
}
@Override
public void onConnectSuccess() {
Log.e("mcy", "連接成功");
}
@Override
public void onConnectFail(String errorMsg) {
Log.e("mcy", "連接失敗" + errorMsg);
}
@Override
public void onConnectClose() {
Log.e("mcy", "連接關(guān)閉");
}
};
classicaConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
classicaBTBind = ((ClassicsBlueToothService.ClassicaBlueToothBind) service);
if (blueCallBack != null) {
classicaBTBind.setBlueCallback(blueCallBack);//設(shè)置廣播監(jiān)聽
}
if (classicaBTBind.getAdapter() != null) {
//判斷藍牙是否開啟
if (!classicaBTBind.getAdapter().isEnabled()) {
//打開藍牙
openBlueSync(MainActivity.this, openBTCode);
} else {
//========================開始執(zhí)行工作=============================
classicaBTBind.scanBlueTooth();//掃描藍牙
registReadListener();//注冊讀數(shù)據(jù)事件
}
} else {
Toast.makeText(MainActivity.this, "此設(shè)備不支持藍牙", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
classicaBTBind = null;
}
};
bindService(new Intent(this, ClassicsBlueToothService.class), classicaConnection, BIND_AUTO_CREATE);
}
//經(jīng)典藍牙注冊讀數(shù)據(jù)事件
private void registReadListener() {
classicaBTBind.readListern("Demo", uuid, new ServiceCallback() {
@Override
public void onConnectSuccess() {
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.e("mcy", "讀數(shù)據(jù)連接成功~");
}
});
}
@Override
public void onConnectFail(final String errorMsg) {
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.e("mcy", "讀數(shù)據(jù)連接失敗" + errorMsg);
}
});
}
@Override
public void onConnectClose() {
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.e("mcy", "讀數(shù)據(jù)連接關(guān)閉");
}
});
}
@Override
public void onResultMessage(final byte[] data) {
runOnUiThread(new Runnable() {
@Override
public void run() {
textView3.setText(new String(data));
}
});
}
});
}
/**
* 自動打開藍牙(同步)
* 這個方法打開藍牙會彈出提示
* 需要在onActivityResult 方法中判斷resultCode == RESULT_OK true為成功
*/
public void openBlueSync(Activity activity, int requestCode) {
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
activity.startActivityForResult(intent, requestCode);
}
//GPS
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case LocalUtils.open_GPSCode://檢查是否手機打開定位
if (LocalUtils.checkGPSIsOpen(this)) {
LocalUtils.checkLocalPermissiion(this, permissions);
} else {
LocalUtils.goToOpenGPS(this);
}
break;
}
}
/**
* 權(quán)限回調(diào)
*/
@Override
public final void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case LocalUtils.permission_LocationCode://是否打開允許定位權(quán)限
if (grantResults.length > 0) {
for (int i = 0; i < grantResults.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
initClassica();//初始化經(jīng)典藍牙
}
}
}
break;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
unbindService(classicaConnection);
}
}
ClassicsBlueToothService.java:
public class ClassicsBlueToothService extends Service {
private IntentFilter filter;
private BlueReceiver pinBlueReceiver;
private BluetoothAdapter bluetoothAdapter;
private ClientThread sendDataThread;
private BluetoothSocket bluetoothSocket;
private ClientCallBack blueCallBack;
private AcceptThread acceptThread;
@Override
public void onCreate() {
super.onCreate();
//獲取藍牙適配器
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
//注冊廣播
//藍牙廣播,系統(tǒng)自動發(fā)送廣播,只要設(shè)置制定的 action 即可
filter = new IntentFilter();
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);//開始掃描
filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//結(jié)束掃描
filter.addAction(BluetoothDevice.ACTION_FOUND);//發(fā)現(xiàn)設(shè)備
filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);//發(fā)起配對請求
filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//配對狀態(tài)
pinBlueReceiver = new BlueReceiver(blueCallBack);
registerReceiver(pinBlueReceiver, filter);
}
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(pinBlueReceiver);
}
public class ClassicaBlueToothBind extends Binder {
public BluetoothAdapter getAdapter() {
return bluetoothAdapter;
}
public void setBlueCallback(ClientCallBack callback) {
ClassicsBlueToothService.this.blueCallBack = callback;
pinBlueReceiver.setCallBack(callback);
}
/**
* 掃描的方法 返回true 掃描成功
* 通過接收廣播獲取掃描到的設(shè)備
*
* @return
*/
public boolean scanBlueTooth() {
//當前是否在掃描,如果是就取消當前的掃描摘仅,重新掃描
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
//此方法是個異步操作靶庙,一般搜索12秒
return bluetoothAdapter.startDiscovery();
}
/**
* 取消掃描藍牙
*
* @return true 為取消成功
*/
public boolean cancelScanBule() {
return bluetoothAdapter.cancelDiscovery();
}
/**
* 配對(配對成功與失敗通過廣播返回)
* !M奘簟六荒!彈出配對框
*
* @param device
*/
public void pinBlueTooth(BluetoothDevice device) {
if (device == null) {
Log.e("mcy", "設(shè)備不可以為空");
return;
}
//配對之前把掃描關(guān)閉
if (bluetoothAdapter.isDiscovering()) {
bluetoothAdapter.cancelDiscovery();
}
//判斷設(shè)備是否配對,沒有配對在配矾端,配對了就不需要配了
if (device.getBondState() == BluetoothDevice.BOND_NONE) {//BOND_NONE 沒有配對狀態(tài)
Log.d("mcy", "attemp to bond:" + device.getName());
try {
boolean returnValue = device.createBond();
Log.e("是否配對成功:", "" + returnValue);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("mcy", "配對失敗");
}
}
}
/**
* 取消配對(取消配對成功與失敗通過廣播返回 也就是配對失斕突鳌)
*
* @param device
*/
public void cancelPinBuleTooth(BluetoothDevice device) {
if (device == null) {
Log.d("mcy", "設(shè)備不可以為空");
return;
}
//判斷設(shè)備是否配對,沒有配對就不用取消了
if (device.getBondState() != BluetoothDevice.BOND_NONE) {
Log.d("mcy", "配對--" + device.getName());
try {
Method removeBondMethod = device.getClass().getMethod("removeBond");
Boolean returnValue = (Boolean) removeBondMethod.invoke(device);
returnValue.booleanValue();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.d("mcy", "取消配對失敗");
}
}
}
/**
* @param uuid 用戶指定的 uuid 秩铆,可隨意寫砚亭,只要格式對就行,客戶端和服務(wù)端保持一致即可殴玛。
* @param device 連接的設(shè)備
*/
public void connectionBlueTooth(String uuid, BluetoothDevice device) {
try {
bluetoothSocket = device.createRfcommSocketToServiceRecord(UUID.fromString(uuid));
if (bluetoothSocket != null && !bluetoothSocket.isConnected()) {
sendDataThread = new ClientThread(bluetoothSocket, blueCallBack);
sendDataThread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 寫數(shù)據(jù)
*/
public void sendData(byte[] data) {
if (sendDataThread != null) {
sendDataThread.write(data);
}
}
/**
* 寫數(shù)據(jù)斷開連接
*
* @return
*/
public void cancleConnecion() {
sendDataThread.closeSocket();
}
/**
* 讀數(shù)據(jù)
*/
public void readListern(String name, String uuid, ServiceCallback callBack) {
acceptThread = new AcceptThread(name, uuid, bluetoothAdapter, callBack);
acceptThread.start();
}
/**
* 寫數(shù)據(jù)斷開連接
*
* @return
*/
public void cancleServiceConnecion() {
acceptThread.closeSocket();
}
}
@Override
public IBinder onBind(Intent intent) {
return new ClassicaBlueToothBind();
}
}
github捅膘,地址 : https://github.com/Mchunyan/BlueToothTest
-----------------------The End-----------------
下一篇寫,低功耗藍牙開發(fā)~~