編輯:關於Android編程
事先說明:
安卓藍牙需要定位權限申請,在安卓6.0需要用戶手動確認權限後才能使用,各位可以自行查詢資料實現,如果嫌麻煩,可以用第三方Bmob集成好的工具類進行實現,詳細可以看http://blog.csdn.net/qq_30379689/article/details/52223244
藍牙連接過程:
1、查詢用戶是否開啟藍牙。
2、搜索附近的可用的藍牙。
3、進行藍牙配對。
4、進行藍牙連接。
5、獲取輸入流和輸出流。
6、發送消息。
曬上我自己畫的美圖:
實驗效果圖:
實現需要的權限:由於安卓4.x以上的版本使用藍牙,需要開啟定位權限才能搜索到附近的藍牙設備
<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" />
服務端
實現思路:
1、拿到本地藍牙設備。
2、藍牙之間的通訊需要一個唯一識別UUID來匹配正確的設備,使用UUID獲取藍牙的通訊Socket。
3、開啟獲取數據的線程
public class MainActivity extends AppCompatActivity implements View.OnClickListener { BluetoothSocket BTSocket; BluetoothAdapter BTAdapter; Button bt_start; TextView tv_msg; StringBuilder sb; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bt_start = (Button) findViewById(R.id.bt_start); tv_msg = (TextView) findViewById(R.id.tv_msg); bt_start.setOnClickListener(this); sb = new StringBuilder(); //拿到本地藍牙設備 BTAdapter = BluetoothAdapter.getDefaultAdapter(); } /** * UI文本輸出 * * @param msg */ public void show(String msg) { sb.append(msg + "\n"); runOnUiThread(new Runnable() { @Override public void run() { tv_msg.setText(sb.toString()); } }); } @Override public void onClick(View v) { //開啟服務器 ServerThread startServerThread = new ServerThread(); startServerThread.start(); } /** * 開啟服務器 */ private class ServerThread extends Thread { public void run() { try { BluetoothServerSocket mserverSocket = BTAdapter.listenUsingRfcommWithServiceRecord("btspp", UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); show("服務端:等待連接"); BTSocket = mserverSocket.accept(); show("服務端:連接成功"); readThread mreadThread = new readThread(); mreadThread.start(); show("服務端:啟動接受數據"); } catch (IOException e) { e.printStackTrace(); } } } /** * 讀取數據 */ private class readThread extends Thread { public void run() { byte[] buffer = new byte[1024]; int bytes; InputStream mmInStream = null; try { mmInStream = BTSocket.getInputStream(); show("服務端:獲得輸入流"); } catch (IOException e1) { e1.printStackTrace(); } while (true) { try { if ((bytes = mmInStream.read(buffer)) > 0) { byte[] buf_data = new byte[bytes]; for (int i = 0; i < bytes; i++) { buf_data[i] = buffer[i]; } String s = new String(buf_data); show("服務端:讀取數據了~~" + s); } } catch (IOException e) { try { mmInStream.close(); } catch (IOException e1) { e1.printStackTrace(); } break; } } } } }
客戶端
實現思路:
1、檢查是否開啟藍牙。
2、注冊一系列藍牙的廣播。
3、由於藍牙每經過一個階段都會發送一個廣播,根據廣播來實現對應的方法。
4、藍牙配對->藍牙連接->發送消息(UUID必須相同)
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private TextView tv_msg; private Button bt_search, bt_send; private BluetoothSocket BTSocket; private BluetoothAdapter BTAdapter; private BluetoothDevice device; private StringBuilder sb; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bt_search = (Button) findViewById(R.id.bt_search); bt_send = (Button) findViewById(R.id.bt_send); tv_msg = (TextView) findViewById(R.id.tv_msg); bt_search.setOnClickListener(this); bt_send.setOnClickListener(this); sb = new StringBuilder(); show("客戶端:檢查BT"); checkBT(this); show("客戶端:注冊接收者"); registerBTReceiver(); } /** * UI文本輸出 * * @param msg */ public void show(String msg) { sb.append(msg + "\n"); runOnUiThread(new Runnable() { @Override public void run() { tv_msg.setText(sb.toString()); } }); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.bt_search: show("客戶端:開始尋找設備"); BTAdapter.startDiscovery(); break; case R.id.bt_send: sendMessage(); break; } } /** * 檢查藍牙 */ public void checkBT(Context context) { BTAdapter = BluetoothAdapter.getDefaultAdapter(); if (BTAdapter != null) { if (!BTAdapter.isEnabled()) { Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); // 設置藍牙可見性,最多300秒 intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); context.startActivity(intent); } } else { System.out.println("本地設備驅動異常!"); } } /** * 開啟客戶端 */ private class clientThread extends Thread { public void run() { try { //創建一個Socket連接:只需要服務器在注冊時的UUID號 BTSocket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); //連接 show("客戶端:開始連接..."); BTSocket.connect(); show("客戶端:連接成功"); //啟動接受數據 show("客戶端:啟動接受數據"); readThread mreadThread = new readThread(); mreadThread.start(); } catch (IOException e) { show("客戶端:連接服務端異常!斷開連接重新試一試"); e.printStackTrace(); } } } /** * 讀取數據 */ private class readThread extends Thread { public void run() { byte[] buffer = new byte[1024]; int bytes; InputStream is = null; try { is = BTSocket.getInputStream(); show("客戶端:獲得輸入流"); } catch (IOException e1) { e1.printStackTrace(); } while (true) { try { if ((bytes = is.read(buffer)) > 0) { byte[] buf_data = new byte[bytes]; for (int i = 0; i < bytes; i++) { buf_data[i] = buffer[i]; } String s = new String(buf_data); show("客戶端:讀取數據了" + s); } } catch (IOException e) { try { is.close(); } catch (IOException e1) { e1.printStackTrace(); } break; } } } } /** * 發送數據 */ public void sendMessage() { if (BTSocket == null) { Toast.makeText(this, "沒有連接", Toast.LENGTH_SHORT).show(); return; } try { OutputStream os = BTSocket.getOutputStream(); os.write("我愛你dahsid132456@#%¥*".getBytes()); os.flush(); show("客戶端:發送信息成功"); } catch (IOException e) { e.printStackTrace(); } } /** * 注冊廣播 */ public void registerBTReceiver() { // 設置廣播信息過濾 IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BluetoothDevice.ACTION_FOUND); intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); // 注冊廣播接收器,接收並處理搜索結果 registerReceiver(BTReceive, intentFilter); } /** * 注銷廣播 */ public void unregisterBTReceiver() { unregisterReceiver(BTReceive); } @Override protected void onDestroy() { super.onDestroy(); unregisterBTReceiver(); } /** * 廣播接收者 */ private BroadcastReceiver BTReceive = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); show("客戶端:找到的BT名:" + device.getName()); // 如果查找到的設備符合要連接的設備,處理 if (device.getName().equalsIgnoreCase("xu")) { show("客戶端:配對xu藍牙:"); // 搜索藍牙設備的過程占用資源比較多,一旦找到需要連接的設備後需要及時關閉搜索 BTAdapter.cancelDiscovery(); // 獲取藍牙設備的連接狀態 int connectState = device.getBondState(); switch (connectState) { // 未配對 case BluetoothDevice.BOND_NONE: show("客戶端:開始配對:"); try { Method createBondMethod = BluetoothDevice.class.getMethod("createBond"); createBondMethod.invoke(device); } catch (Exception e) { e.printStackTrace(); } break; // 已配對 case BluetoothDevice.BOND_BONDED: try { show("客戶端:開始連接:"); clientThread clientConnectThread = new clientThread(); clientConnectThread.start(); } catch (Exception e) { e.printStackTrace(); } break; } } } else if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) { // 獲取藍牙設備的連接狀態 int connectState = device.getBondState(); // 已配對 if (connectState == BluetoothDevice.BOND_BONDED) { try { show("客戶端:開始連接:"); clientThread clientConnectThread = new clientThread(); clientConnectThread.start(); } catch (Exception e) { e.printStackTrace(); } } } show(action); } }; }
藍牙廣播內容:
ACTION_STATE_CHANGED 當你藍牙開啟或者關閉的時候發送
ACTION_FOUND 當你匹配到附近藍牙設備時發送
ACTION_DISCOVERY_STARTED 當你開始搜索附近藍牙設備時發送
ACTION_DISCOVERY_FINISHED 當你結束搜索附近藍牙設備時發送
ACTION_BOND_STATE_CHANGED 當你藍牙設備匹配狀態發生變化時發送
源碼下載:http://xiazai.jb51.net/201609/yuanma/Androidrobot(jb51.net).rar
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持本站。
很多時候Android常用的控件不能滿足我們的需求,那麼我們就需要自定義一個控件了。今天做了一個自定義控件的實例,來分享下。首先定義一個layout實現按鈕內部布局:&n
1.android緩存的介紹Android開發本質上就是手機和互聯網中的web服務器之間進行通信,就必然需要從服務端獲取數據,而反復通過網絡獲取數據是比較耗時的,特別是訪
效果圖如下所示:一、shape 樣式:(在drawable新建--》new--》Drawable resource file 在父級標簽selector添加Item )&
OKHttp3是如今非常流行的Android網絡請求框架,那麼如何利用Android實現斷點續傳呢,今天寫了個Demo嘗試了一下,感覺還是有點意思准備階段我們會用到OKH