




版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
【移動(dòng)應(yīng)用開(kāi)發(fā)技術(shù)】Android中怎么實(shí)現(xiàn)藍(lán)牙通信
這期內(nèi)容當(dāng)中在下將會(huì)給大家?guī)?lái)有關(guān)Android中怎么實(shí)現(xiàn)藍(lán)牙通信,文章內(nèi)容豐富且以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。一:注意事項(xiàng)
1:android6.0使用藍(lán)牙時(shí),需要開(kāi)啟gps定位權(quán)限,不然無(wú)法搜索其它藍(lán)牙設(shè)備。二:權(quán)限
1:權(quán)限配置<!--允許程序連接到已配對(duì)的藍(lán)牙設(shè)備-->
<uses-permission
android:name="android.permission.BLUETOOTH"
/>
<!--
允許程序發(fā)現(xiàn)和配對(duì)藍(lán)牙設(shè)備
-->
<uses-permission
android:name="android.permission.BLUETOOTH_ADMIN"
/>
<!--android
6.0
涉及到的權(quán)限-->
<uses-permission
android:name="android.permission.ACCESS_FINE_LOCATION"
/>
<uses-permission
android:name="android.permission.ACCESS_COARSE_LOCATION"
/>
<!--
在SDCard中創(chuàng)建與刪除文件的權(quán)限
-->
<uses-permission
android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!--
往SDCard寫(xiě)入數(shù)據(jù)的權(quán)限
-->
<uses-permission
android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
2:動(dòng)態(tài)權(quán)限代碼
由于需要用到存儲(chǔ)卡,定位等,android6.0以上需要代碼動(dòng)態(tài)設(shè)置。
a)獲取定位設(shè)置if
(Build.VERSION.SDK_INT
>=
23)
{
boolean
isLocat
=
isLocationOpen(getApplicationContext());
Toast.makeText(mContext,
"isLo:"
+
isLocat,
Toast.LENGTH_LONG).show();
//開(kāi)啟位置服務(wù),支持獲取ble藍(lán)牙掃描結(jié)果
if
(!isLocat)
{
Intent
enableLocate
=
new
Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(enableLocate,
1);
}
}
/**
*
判斷位置信息是否開(kāi)啟
*
*
@param
context
*
@return
*/
private
static
boolean
isLocationOpen(final
Context
context)
{
LocationManager
manager
=
(LocationManager)
context.getSystemService(Context.LOCATION_SERVICE);
//gps定位
boolean
isGpsProvider
=
manager.isProviderEnabled(LocationManager.GPS_PROVIDER);
//網(wǎng)絡(luò)定位
boolean
isNetWorkProvider
=
manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
return
isGpsProvider
||
isNetWorkProvider;
}b)存儲(chǔ)卡權(quán)限設(shè)置if
(Build.VERSION.SDK_INT
>=
23)
{
int
write
=
checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
int
read
=
checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
//動(dòng)態(tài)請(qǐng)求讀寫(xiě)sd卡權(quán)限
if
(write
!=
PackageManager.PERMISSION_GRANTED
||
read
!=
PackageManager.PERMISSION_GRANTED)
{
requestPermissions(new
String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE},
SD_CARD);
}
}然后通過(guò)onRequestPermissionsResult()方法獲取動(dòng)態(tài)權(quán)限的結(jié)果:@Override
public
void
onRequestPermissionsResult(int
requestCode,
String[]
permissions,
int[]
grantResults)
{
switch
(requestCode){
case
SD_CARD:
if(grantResults.length>0&&grantResults[0]
==
PackageManager.PERMISSION_GRANTED){
//允許訪問(wèn)
}else{
Toast.makeText(mContext,"您拒絕了程序訪問(wèn)存儲(chǔ)卡",Toast.LENGTH_LONG).show();
}
break;
case
COARES_LOCATION:
break;
}
}
三:藍(lán)牙搜索android.bluetooth.BluetoothAdapter是藍(lán)牙開(kāi)發(fā)用得比較多,并且比較重要的一個(gè)類(lèi),可以設(shè)備藍(lán)牙名稱(chēng),打開(kāi),關(guān)閉,搜索等常規(guī)操作。
1藍(lán)牙打開(kāi),以及搜索
藍(lán)牙打開(kāi)和關(guān)閉信息使用BluetoothAdapter.ACTION_STATE_CHANGED去接收廣播BluetoothAdapter
mBluetoothAdapter
=
BluetoothAdapter.getDefaultAdapter();
mBluetoothAdapter.setName("blueTestPhone");
//判斷藍(lán)牙是否打開(kāi)
boolean
originalBluetooth
=
(mBluetoothAdapter
!=
null
&&
mBluetoothAdapter.isEnabled());
if
(originalBluetooth)
{
mBluetoothAdapter.startDiscovery();
}
else
if
(originalBluetooth
==
false)
{
mBluetoothAdapter.enable();
}藍(lán)牙打開(kāi)后,我們可以獲取設(shè)備的藍(lán)牙信息StringBuilder
sb
=
new
StringBuilder();
//獲取本機(jī)藍(lán)牙名稱(chēng)
String
name
=
mBluetoothAdapter.getName();
//獲取本機(jī)藍(lán)牙地址
String
address
=
mBluetoothAdapter.getAddress();搜索完成后,通過(guò)BluetoothDevice.ACTION_FOUND廣播去接收結(jié)果,廣播代碼如下(注意:可能出現(xiàn)設(shè)備搜索不到的情況,設(shè)備需要開(kāi)啟允許周?chē)O(shè)備搜索,或者通過(guò)程序來(lái)控制允許搜索的時(shí)間范圍)
/*確保藍(lán)牙被發(fā)現(xiàn),在榮耀8手機(jī)上,設(shè)置了還是默認(rèn)的2分鐘,所以以下幾句代碼程序中沒(méi)有,*/
Intent
discoverableIntent
=
new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
//設(shè)置可見(jiàn)狀態(tài)的持續(xù)時(shí)間為300秒,但是最多是300秒
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,
300);
startActivityForResult(discoverableIntent,
REQUEST_DISCOVERABLE_BLUETOOTH);
private
void
initSearchBroadcast()
{
IntentFilter
intentFilter
=
new
IntentFilter();
//發(fā)現(xiàn)設(shè)備
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
//設(shè)備配對(duì)狀態(tài)改變
intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
//藍(lán)牙設(shè)備狀態(tài)改變
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
//開(kāi)始掃描
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
//結(jié)束掃描
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
//其它設(shè)備請(qǐng)求配對(duì)
intentFilter.addAction(ACTION_PAIRING_REQUEST);
//intentFilter.addAction(BluetoothAdapter.CONNECTION_STATE_CHANGED);
registerReceiver(bluetoothReceiver,
intentFilter);
}
private
BroadcastReceiver
bluetoothReceiver
=
new
BroadcastReceiver()
{
@Override
public
void
onReceive(Context
context,
Intent
intent)
{
String
action
=
intent.getAction();
Logger.e(TAG
+
"mBluetoothReceiver
action
="
+
action);
try
{
if
(BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action))
{//開(kāi)始掃描
setProgressBarIndeterminateVisibility(true);
log1.setText("正在掃描設(shè)備,請(qǐng)稍候...");
}
else
if
(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action))
{//結(jié)束掃描
Logger.e(TAG
+
"設(shè)備搜索完畢");
setProgressBarIndeterminateVisibility(false);
log1.setText("掃描完成");
bondAdapter.notifyDataSetChanged();
unbondAdapter.notifyDataSetChanged();
scanStatus
=
false;
}
else
if
(BluetoothDevice.ACTION_FOUND.equals(action))
{//發(fā)現(xiàn)設(shè)備
findDevice(intent);
}
else
if
(BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action))
{//藍(lán)牙配對(duì)狀態(tài)的廣播
BluetoothDevice
device
=
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Logger.e(TAG
+
device.getName()
+
"藍(lán)牙配對(duì)廣播:"
+
device.getBondState());
switch
(device.getBondState())
{
case
BluetoothDevice.BOND_BONDING:
Logger.e(TAG
+
device.getName()
+
"藍(lán)牙配對(duì)廣播
正在配對(duì)");
break;
case
BluetoothDevice.BOND_BONDED:
Logger.e(TAG
+
device.getName()
+
"藍(lán)牙配對(duì)廣播
完成配對(duì),本機(jī)自動(dòng)配對(duì)");
bondDevices.add(device);
unbondDevices.remove(device);
bondAdapter.notifyDataSetChanged();
unbondAdapter.notifyDataSetChanged();
break;
case
BluetoothDevice.BOND_NONE:
Logger.e(TAG
+
device.getName()
+
"藍(lán)牙配對(duì)廣播
取消配對(duì)");
unbondDevices.add(device);
bondDevices.remove(device);
unbondAdapter.notifyDataSetChanged();
bondAdapter.notifyDataSetChanged();
default:
break;
}
}
else
if
(action.equals(ACTION_PAIRING_REQUEST))
{//其它設(shè)備藍(lán)牙配對(duì)請(qǐng)求
BluetoothDevice
btDevice
=
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
int
state
=
intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
BluetoothDevice.BOND_NONE);
//當(dāng)前的配對(duì)的狀態(tài)
try
{
String
path
=
Environment.getExternalStorageDirectory()
+
"/blueTest/";
String
deviceName
=
btDevice.getName();
Logger.e(TAG
+
"藍(lán)牙
匹配信息:"
+
deviceName
+
","
+
btDevice.getAddress()
+
",state:"
+
state);
//1.確認(rèn)配對(duì),高版本無(wú)效,藍(lán)牙配對(duì)不是zuk的問(wèn)題,而是安卓6.0的bug,凡是遇到藍(lán)牙適配問(wèn)題的,請(qǐng)同時(shí)打開(kāi)藍(lán)牙和定位,再去配對(duì),基本90%都沒(méi)有問(wèn)題了。
Object
object
=
ClsUtils.setPairingConfirmation(btDevice.getClass(),
btDevice,
true);
//2.終止有序廣播,如果沒(méi)有將廣播終止,則會(huì)出現(xiàn)一個(gè)一閃而過(guò)的配對(duì)框。
abortBroadcast();
//3.調(diào)用setPin方法進(jìn)行配對(duì)...
boolean
ret
=
ClsUtils.setPin(btDevice.getClass(),
btDevice,
PWD);
}
catch
(Exception
e)
{
//
TODO
Auto-generated
catch
block
e.printStackTrace();
Toast.makeText(mContenxt,
"error:"
+
btDevice
+
","
+
state,
Toast.LENGTH_LONG).show();
}
}
else
if
(action.equals(BluetoothAdapter.ACTION_STATE_CHANGED))
{//藍(lán)牙開(kāi)關(guān)狀態(tài)
//
BluetoothDevice
device
=
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
int
statue
=
mBluetoothAdapter.getState();
switch
(statue)
{
case
BluetoothAdapter.STATE_OFF:
Logger.e("藍(lán)牙狀態(tài):,藍(lán)牙關(guān)閉");
ClsUtils.closeDiscoverableTimeout(mBluetoothAdapter);
break;
case
BluetoothAdapter.STATE_ON:
Logger.e("藍(lán)牙狀態(tài):,藍(lán)牙打開(kāi)");
ClsUtils.setDiscoverableTimeout(1000
*
60,
mBluetoothAdapter);
scanBluetooth();
break;
case
BluetoothAdapter.STATE_TURNING_OFF:
Logger.e("藍(lán)牙狀態(tài):,藍(lán)牙正在關(guān)閉");
mBluetoothAdapter.cancelDiscovery();
break;
case
BluetoothAdapter.STATE_TURNING_ON:
Logger.e("藍(lán)牙狀態(tài):,藍(lán)牙正在打開(kāi)");
break;
}
}
}
catch
(Exception
e)
{
e.printStackTrace();
}
}
};
//發(fā)現(xiàn)設(shè)備的代碼如下
private
void
findDevice(Intent
intent)
throws
Exception{
//獲取到設(shè)備對(duì)象
BluetoothDevice
device
=
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
String
str
=
device.getName()
+
"|"
+
device.getAddress();
Logger.e("掃描到設(shè)備:"
+
str);
if
(device.getBondState()
==
BluetoothDevice.BOND_BONDED)
{//判斷當(dāng)前設(shè)備地址下的device是否已經(jīng)配對(duì)
if
(!bondDevices.contains(device))
{
bondDevices.add(device);
}
}
else
{
if
(!unbondDevices.contains(device))
{
unbondDevices.add(device);
}
if
(device.getName().equals(TEST_DEVICE_NAME))
{
boolean
bondStatus
=
ClsUtils.createBond(device.getClass(),
device);
Logger.i(TAG
+
"
bondStatus:"
+
bondStatus);
}
}
Log.e("error",
"搜索完畢,準(zhǔn)備刷新!");
bondAdapter.notifyDataSetChanged();
unbondAdapter.notifyDataSetChanged();
}四:藍(lán)牙配對(duì)
正常情況下,藍(lán)牙匹配需要彈出一個(gè)匹配確認(rèn)框,如下圖,但我想實(shí)現(xiàn)的是,匹配其中一方,不能手動(dòng)點(diǎn)擊配對(duì),因?yàn)榘l(fā)起藍(lán)牙連接的設(shè)備是android設(shè)備,是不能觸摸的,所以就要通過(guò)程序來(lái)解決這個(gè)問(wèn)題,特別聲明:(測(cè)試的android設(shè)備,版本為5.x,并且已經(jīng)root,沒(méi)有root的設(shè)備,或者不是android5.x不清楚能否實(shí)現(xiàn)自動(dòng)匹配,因?yàn)槲抑挥羞@個(gè)測(cè)試設(shè)備)。1當(dāng)我們搜索到目標(biāo)手機(jī)的藍(lán)牙后,android設(shè)備主動(dòng)發(fā)起連接請(qǐng)求,代碼如下
if
(device.getName().equals(TEST_DEVICE_NAME))
{
boolean
bondStatus
=
ClsUtils.createBond(device.getClass(),
device);
Logger.i(TAG
+
"
bondStatus:"
+
bondStatus);
}
//發(fā)起藍(lán)牙匹配請(qǐng)求
public
boolean
createBond(Class
btClass,
BluetoothDevice
btDevice)
throws
Exception
{
Method
createBondMethod
=
btClass.getMethod("createBond");
Boolean
returnValue
=
(Boolean)
createBondMethod.invoke(btDevice);
return
returnValue.booleanValue();
}2當(dāng)被匹配方點(diǎn)擊配對(duì)后,系統(tǒng)會(huì)通過(guò)BluetoothDevice.ACTION_BOND_STATE_CHANGED廣播告訴android設(shè)備,此時(shí)android設(shè)備就可以自動(dòng)確認(rèn),通過(guò)這個(gè)流程來(lái)完成整個(gè)藍(lán)牙的配對(duì),具體代碼如下
BluetoothDevice
btDevice
=
intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
int
state
=
intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE,
BluetoothDevice.BOND_NONE);
//當(dāng)前的配對(duì)的狀態(tài)
try
{
String
path
=
Environment.getExternalStorageDirectory()
+
"/blueTest/";
String
deviceName
=
btDevice.getName();
Logger.e(TAG
+
"藍(lán)牙
匹配信息:"
+
deviceName
+
","
+
btDevice.getAddress()
+
",state:"
+
state);
if(deviceName.equals(TEST_DEVICE_NAME)){//TEST_DEVICE_NAME
為被匹配藍(lán)牙設(shè)備的名稱(chēng),自己手動(dòng)定義
Object
object
=
ClsUtils.setPairingConfirmation(btDevice.getClass(),
btDevice,
true);
abortBroadcast();
boolean
ret
=
ClsUtils.setPin(btDevice.getClass(),
btDevice,
PWD);
}
}
catch
(Exception
e)
{
//
TODO
Auto-generated
catch
block
e.printStackTrace();
Toast.ma
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025福建福州古厝集團(tuán)有限公司招聘6人筆試參考題庫(kù)附帶答案詳解
- 2025浙江松陽(yáng)縣新華書(shū)店有限公司招聘見(jiàn)習(xí)生1人筆試參考題庫(kù)附帶答案詳解
- 2025年度湖南省交通規(guī)劃勘察設(shè)計(jì)院有限公司社會(huì)招聘15人筆試參考題庫(kù)附帶答案詳解
- 2025年華電煤業(yè)集團(tuán)有限公司校園招聘筆試參考題庫(kù)附帶答案詳解
- 2025年上半年安徽黃山市徽城投資集團(tuán)限公司招聘7人易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 2025年上半年安徽馬鞍山博望區(qū)政府部門(mén)招聘派遣制人員5人易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 2025年上半年安徽阜陽(yáng)市城鄉(xiāng)建設(shè)局招聘1人易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 2025年上半年安徽蕪湖三山區(qū)市容局招考協(xié)管員8人易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 2025年上半年安徽省宣城市直事業(yè)單位招考易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 2025年上半年安徽池州市東至縣事業(yè)單位公開(kāi)招聘工作人員46人易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 男護(hù)士的職業(yè)生涯規(guī)劃書(shū)
- 2025年黑龍江旅游職業(yè)技術(shù)學(xué)院?jiǎn)握新殬I(yè)技能測(cè)試題庫(kù)含答案
- 工藝技術(shù)人員工作總結(jié)
- DB61T-農(nóng)產(chǎn)品區(qū)域公用品牌管理規(guī)范
- 中央2025年中國(guó)民航大學(xué)勞動(dòng)合同制人員招聘7人筆試歷年參考題庫(kù)附帶答案詳解
- 高一生活指南模板
- 廣州電視塔鋼結(jié)構(gòu)施工方案
- 【9物一模】2024年安徽省合肥市廬陽(yáng)中學(xué)九年級(jí)中考一模物理試卷
- 護(hù)理安全警示教育ppt
- 老年人醫(yī)養(yǎng)結(jié)合服務(wù)記錄表單
- DSA室的手術(shù)配合教學(xué)課件
評(píng)論
0/150
提交評(píng)論