編輯:關於Android編程
藍牙技術在智能硬件方面有很多用武之地,今天我就為大家分享一下藍牙在Android系統下的使用方法技巧,並實現一下兩個終端間數據的傳輸。
藍牙(Bluetooth)是一種短距離的無線通信技術標准,藍牙協議分為4層,即核心協議層、電纜替代協議層、電話控制協議層和采納的其它協議層。
這4種協議中最重要的是核心協議。藍牙的核心協議包括基帶、鏈路管理、邏輯鏈路控制和適應協議四部分。其中鏈路管理(LMP)負責藍牙組件間連接的建立。邏輯鏈路控制與適應協議(L2CAP)位於基帶協議層上,屬於數據鏈路層,是一個為高層傳輸和應用層協議屏蔽基帶協議的適配協議。
1.打開和關閉藍牙
第一種方法相對簡單,直接調用系統對話框啟動藍牙:
在AndroidManifest文件中添加需要的權限,高版本也不需要動態授權:
<uses-permission android:name="android.permission.BLUETOOTH" />
startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), 1);
如果不想讓用戶看到這個對話框,那麼我們還可以選擇第二種方法,進行靜默開啟藍牙。
第二種方法,靜默開啟,不會有方法一的對話框:
在AndroidManifest文件中添加需要的權限:
<!-- 已適配Android6.0 --> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
由於藍牙所需要的權限包含Dangerous Permissions,所以我們需要在Java代碼中進行動態授權處理:
private static final int REQUEST_BLUETOOTH_PERMISSION=10; private void requestBluetoothPermission(){ //判斷系統版本 if (Build.VERSION.SDK_INT >= 23) { //檢測當前app是否擁有某個權限 int checkCallPhonePermission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION); //判斷這個權限是否已經授權過 if(checkCallPhonePermission != PackageManager.PERMISSION_GRANTED){ //判斷是否需要 向用戶解釋,為什麼要申請該權限 if(ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_COARSE_LOCATION)) Toast.makeText(this,"Need bluetooth permission.", Toast.LENGTH_SHORT).show(); ActivityCompat.requestPermissions(this ,new String[] {Manifest.permission.ACCESS_COARSE_LOCATION},REQUEST_BLUETOOTH_PERMISSION); return; }else{ } } else { } }
接下來我們就可以靜默開啟藍牙了:
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); mBluetoothAdapter.enable(); //開啟 //mBluetoothAdapter.disable(); //關閉
下面我們來看一下如何通過代碼搜索藍牙設備。
2.通過代碼搜索藍牙設備
搜索分為主動搜索和被動搜索。
我們開始進行主動搜索:
(1)創建BluetoothAdapter對象
TextView tvDevices = (TextView)findViewById(R.id.tv_devices); BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
(2)我們先獲取並顯示一下已經配對的藍牙設備列表
//獲取已經配對的藍牙設備 Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices(); if (pairedDevices.size() > 0) { for (BluetoothDevice device : pairedDevices) { tvDevices.append(device.getName() + ":" + device.getAddress()); } }
(3)下面我們定義廣播接收器
// 設置廣播信息過濾 IntentFilter filter = new IntentFilter(); filter.addAction(BluetoothDevice.ACTION_FOUND);//每搜索到一個設備就會發送一個該廣播 filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//當全部搜索完後發送該廣播 filter.setPriority(Integer.MAX_VALUE);//設置優先級 // 注冊藍牙搜索廣播接收者,接收並處理搜索結果 this.registerReceiver(receiver, filter);
藍牙設備的廣播接收器如下:
/** * 定義廣播接收器 */ private final BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (device.getBondState() != BluetoothDevice.BOND_BONDED) { tvDevices.append(device.getName() + ":"+ device.getAddress()); } } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { //已搜素完成 } } };
(4)我們創建一個Button按鈕,當點擊Button時進行搜索,Button點擊事件如下:
//如果當前在搜索,就先取消搜索 if (mBluetoothAdapter.isDiscovering()) { mBluetoothAdapter.cancelDiscovery(); } //開啟搜索 mBluetoothAdapter.startDiscovery();
3.藍牙的UUID
兩個藍牙設備進行連接時需要使用同一個UUID。但很多讀者可能發現,有很多型號的手機(可能是非Android系統的手機)之間使用了不同的程序也可以使用藍牙進行通訊。從表面上看,它們之間幾乎不可能使用同一個UUID。
UUID的格式如下:
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
UUID的格式被分成5段,其中中間3段的字符數相同,都是4,第1段是8個字符,最後一段是12個字符。所以UUID實際上是一個8-4-4-4-12的字符串。
實際上,UUID和TCP的端口一樣,也有一些默認的值。例如,將藍牙模擬成串口的服務就使用了一個標准的UUID:
00001101-0000-1000-8000-00805F9B34FB
除此之外,還有很多標准的UUID,如下面就是兩個標准的UUID:
信息同步服務:00001104-0000-1000-8000-00805F9B34FB
文件傳輸服務:00001106-0000-1000-8000-00805F9B34FB
4.藍牙終端間數據傳輸
通過藍牙傳輸數據與Socket類似。在網絡中使用Socket和ServerSocket控制客戶端和服務端的數據讀寫。而藍牙通訊也由客戶端和服務端Socket來完成。藍牙客戶端Socket是BluetoothSocket,藍牙服務端Socket是BluetoothServerSocket。這兩個類都在android.bluetooth包中。
無論是BluetoothSocket,還是BluetoothServerSocket,都需要一個UUID(全局唯一標識符,Universally Unique Identifier),UUID相當於Socket的端口,而藍牙地址相當於Socket的IP。
我們開始進行模擬一個藍牙數據的傳輸:
首先來看客戶端:
(1)定義全局常量變量
private ListView lvDevices; private BluetoothAdapter mBluetoothAdapter; private List<String> bluetoothDevices = new ArrayList<String>(); private ArrayAdapter<String> arrayAdapter; private final UUID MY_UUID = UUID .fromString("abcd1234-ab12-ab12-ab12-abcdef123456");//隨便定義一個 private BluetoothSocket clientSocket; private BluetoothDevice device; private OutputStream os;//輸出流
(2)在onCreate方法中做初始化操作
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); lvDevices = (ListView) findViewById(R.id.lv_devices); //獲取已經配對的藍牙設備 Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices(); if (pairedDevices.size() > 0) { for (BluetoothDevice device : pairedDevices) { bluetoothDevices.add(device.getName() + ":"+ device.getAddress()); } } arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, android.R.id.text1,bluetoothDevices); lvDevices.setAdapter(arrayAdapter); lvDevices.setOnItemClickListener(this);//Activity實現OnItemClickListener接口 //每搜索到一個設備就會發送一個該廣播 IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); this.registerReceiver(receiver, filter); //當全部搜索完後發送該廣播 filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); this.registerReceiver(receiver, filter);
藍牙設備的廣播接收器如下:
/** * 定義廣播接收器 */ private final BroadcastReceiver receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (device.getBondState() != BluetoothDevice.BOND_BONDED) { bluetoothDevices.add(device.getName() + ":" + device.getAddress()); arrayAdapter.notifyDataSetChanged();//更新適配器 } } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { //已搜素完成 } } };
(4)我們創建一個Button按鈕,當點擊Button時進行搜索,Button點擊事件如下:
//如果當前在搜索,就先取消搜索 if (mBluetoothAdapter.isDiscovering()) { mBluetoothAdapter.cancelDiscovery(); } //開啟搜索 mBluetoothAdapter.startDiscovery();
(5)接下來我們設置列表的點擊事件:
@Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { String s = arrayAdapter.getItem(position); String address = s.substring(s.indexOf(":") + 1).trim();//把地址解析出來 //主動連接藍牙服務端 try { //判斷當前是否正在搜索 if (mBluetoothAdapter.isDiscovering()) { mBluetoothAdapter.cancelDiscovery(); } try { if (device == null) { //獲得遠程設備 device = mBluetoothAdapter.getRemoteDevice(address); } if (clientSocket == null) { //創建客戶端藍牙Socket clientSocket = device.createRfcommSocketToServiceRecord(MY_UUID); //開始連接藍牙,如果沒有配對則彈出對話框提示我們進行配對 clientSocket.connect(); //獲得輸出流(客戶端指向服務端輸出文本) os = clientSocket.getOutputStream(); } } catch (Exception e) { } if (os != null) { //往服務端寫信息 os.write("藍牙信息來了".getBytes("utf-8")); } } catch (Exception e) { } }
接下來看服務端:
服務端使用的是另一部手機,接受上面手機通過藍牙發送過來的信息並顯示。
(1)定義全局常量變量:
private BluetoothAdapter mBluetoothAdapter; private AcceptThread acceptThread; private final UUID MY_UUID = UUID .fromString("abcd1234-ab12-ab12-ab12-abcdef123456");//和客戶端相同的UUID private final String NAME = "Bluetooth_Socket"; private BluetoothServerSocket serverSocket; private BluetoothSocket socket; private InputStream is;//輸入流
(2)定義服務端線程類:
private Handler handler = new Handler() { public void handleMessage(Message msg) { Toast.makeText(getApplicationContext(), String.valueOf(msg.obj), Toast.LENGTH_LONG).show(); super.handleMessage(msg); } }; //服務端監聽客戶端的線程類 private class AcceptThread extends Thread { public AcceptThread() { try { serverSocket = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID); } catch (Exception e) { } } public void run() { try { socket = serverSocket.accept(); is = socket.getInputStream(); while(true) { byte[] buffer =new byte[1024]; int count = is.read(buffer); Message msg = new Message(); msg.obj = new String(buffer, 0, count, "utf-8"); handler.sendMessage(msg); } } catch (Exception e) { } } }
(3)在onCreate方法中初始化線程類並開啟
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); acceptThread = new AcceptThread(); acceptThread.start();
我們運行程序看一下效果圖:
點擊“搜索藍牙設備”按鈕,就會搜索到另一台手機的藍牙信息,我們點擊條目,另一台手機會出現如下變化:
彈出Toast,此時證明我們的藍牙數據已經傳輸過來了。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。
前言在Android中經常要使用Dialog來實現一些提示以及一些特殊的效果,而且樣式也不一樣,每次都得查一大堆資料,還不一定能解決。對話框是個好東西,創建簡單有實用。當
在之前的第一篇文章: android自動化測試中hierarchyviewer和uiautomatorviewer獲取控件信息的方式比對(1) 我說uiauto
實現刮刮卡我們可以Get到哪些技能?* 圓形圓角圖片的實現原理* 雙緩沖技術繪圖* Bitmap獲取像素值數據* 獲取繪制文本的長寬* 自定義View的掌握* 獲取屏幕密
完全屬於自己的新聞展示平台,展示給大家,希望大家喜歡。一、新聞的數據庫的構建腳本代碼如下:(使用的mysql5.0 數據庫)SET SQL_MODE = NO_AUTO_