基于蓝牙的安卓客户端开发

Posted 笑着刻印在那一张泛黄

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于蓝牙的安卓客户端开发相关的知识,希望对你有一定的参考价值。

一.安卓蓝牙开发基本流程

  • 获取本地蓝牙适配器,打开蓝牙,获得已配对蓝牙设备列表

mBtAdapter = BluetoothAdapter.getDefaultAdapter();

mBtAdapter.enable(); 

Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();

  • 扫描未配对设备,通过广播(BluetoothDevice.ACTION_FOUND)接收列表出未配对的设备

mBtAdapter.startDiscovery();

  • 从列表设备选择某个蓝牙进行连接,获得BluetoothDevice 对象

device.getName()

device.getAddress()

BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address)

  • 开始连接线程,获得BluetoothSocket

private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

BluetoothSocket bluetoothSocket= device.createRfcommSocketToServiceRecord(MY_UUID)

  • 开始已连接线程,由BluetoothSocket获得输入输出流从而收发数据

二.权限申明

1 <!--蓝牙权限-->
2     <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
3     <uses-permission android:name="android.permission.BLUETOOTH" />

三.布局文件

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     xmlns:tools="http://schemas.android.com/tools"
 4     android:id="@+id/activity_main"
 5     android:layout_width="match_parent"
 6     android:layout_height="match_parent"
 7     android:orientation="vertical"
 8     >
 9     <!--标题栏-->
10     <LinearLayout
11         android:layout_width="match_parent"
12         android:layout_height="wrap_content"
13         android:background="#CDC9C9">
14         <TextView
15             android:id="@+id/DeviceTextView"
16             android:layout_width="wrap_content"
17             android:layout_weight="1"
18             android:layout_height="wrap_content"
19             android:text="设备:"
20             android:textColor="#FFFFFF"
21             android:textSize="20dp"
22             />
23         <TextView
24             android:id="@+id/StateTextView"
25             android:layout_width="wrap_content"
26             android:layout_weight="1"
27             android:layout_height="wrap_content"
28             android:text="状态:"
29             android:textColor="#FFFFFF"
30             android:textSize="20dp"
31             />
32     </LinearLayout>
33     <!--聊天界面-->
34     <LinearLayout
35         android:id="@+id/chatPage"
36         android:layout_width="match_parent"
37         android:layout_height="wrap_content"
38         android:orientation="vertical"
39         android:visibility="gone"
40         android:layout_marginLeft="10dp"
41         android:layout_marginRight="10dp"
42         >
43         <LinearLayout
44             android:layout_width="match_parent"
45             android:layout_height="wrap_content"
46 
47             >
48             <EditText
49                 android:id="@+id/MessageEditText"
50                 android:layout_marginTop="5dp"
51                 android:layout_width="wrap_content"
52                 android:layout_weight="1"
53                 android:layout_height="40dp"
54                 />
55             <Button
56                 android:id="@+id/SendButton"
57                 android:layout_width="wrap_content"
58                 android:layout_height="wrap_content"
59                 android:layout_marginTop="4dp"
60                 android:textAllCaps="false"
61                 android:text="Send"
62                 />
63         </LinearLayout>
64         <LinearLayout
65             android:layout_width="match_parent"
66             android:layout_height="wrap_content">
67             <TextView
68                 android:id="@+id/DisplayTextView"
69                 android:layout_width="match_parent"
70                 android:layout_height="wrap_content"
71                 android:hint="DisplayTextView"/>
72         </LinearLayout>
73 
74     </LinearLayout>
75     <!--控制界面-->
76     <LinearLayout
77         android:id="@+id/controlPage"
78         android:layout_width="match_parent"
79         android:layout_height="match_parent"
80         android:orientation="vertical"
81         android:visibility="visible">
82     </LinearLayout>
83     <!--数据中心-->
84     <LinearLayout
85         android:id="@+id/displayPage"
86         android:layout_width="match_parent"
87         android:layout_height="match_parent"
88         android:orientation="vertical"
89         android:visibility="gone">
90     </LinearLayout>
91 </LinearLayout>

 

四.具体代码实现

  • MainActivity

  1 package com.example.john.esdc;
  2 
  3 import android.app.Activity;
  4 import android.bluetooth.BluetoothAdapter;
  5 import android.bluetooth.BluetoothDevice;
  6 import android.content.Intent;
  7 import android.os.Handler;
  8 import android.os.Message;
  9 import android.support.v7.app.AppCompatActivity;
 10 import android.os.Bundle;
 11 import android.view.Menu;
 12 import android.view.MenuItem;
 13 import android.view.View;
 14 import android.widget.Button;
 15 import android.widget.EditText;
 16 import android.widget.TextView;
 17 import android.widget.Toast;
 18 
 19 public class MainActivity extends AppCompatActivity {
 20 
 21     // Intent request codes
 22     private static final int REQUEST_CONNECT_DEVICE = 1;
 23     // Local Bluetooth adapter
 24     private BluetoothAdapter mBluetoothAdapter = null;
 25     // Member object for the chat services
 26     private BluetoothChatService mChatService = null;
 27     // Message types sent from the BluetoothChatService Handler
 28     public static final int MESSAGE_STATE_CHANGE = 1;
 29     public static final int MESSAGE_READ = 2;
 30     public static final int MESSAGE_WRITE = 3;
 31     public static final int MESSAGE_DEVICE_NAME = 4;
 32     public static final int MESSAGE_TOAST = 5;
 33     // Key names received from the BluetoothChatService Handler
 34     public static final String DEVICE_NAME = "device_name";
 35     public static final String TOAST = "toast";
 36     // Name of the connected device
 37     private String mConnectedDeviceName = null;
 38     //控件
 39     TextView deviceTextView;
 40     TextView stateTextView;
 41     EditText messageEditText;
 42     Button sendButton;
 43     TextView displayTextView;
 44     private int numofMessage=0; //显示的消息数
 45     //界面
 46     View controlPage;
 47     View displayPage;
 48     View chatPage;
 49 
 50 
 51     @Override
 52     protected void onCreate(Bundle savedInstanceState) {
 53         super.onCreate(savedInstanceState);
 54         setContentView(R.layout.activity_main);
 55         getWidget();
 56         // Initialize the BluetoothChatService to perform bluetooth connections
 57         mChatService = new BluetoothChatService(this, mHandler);
 58         // Get local Bluetooth adapter
 59         mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
 60         sendButton.setOnClickListener(new View.OnClickListener() {
 61             @Override
 62             public void onClick(View v) {
 63                 String message = messageEditText.getText().toString();
 64                 sendMessage(message);
 65             }
 66         });
 67     }
 68     //获取控件对象
 69     private void getWidget(){
 70         deviceTextView = (TextView)findViewById(R.id.DeviceTextView);
 71         stateTextView = (TextView)findViewById(R.id.StateTextView);
 72         messageEditText = (EditText)findViewById(R.id.MessageEditText);
 73         sendButton = (Button)findViewById(R.id.SendButton);
 74         displayTextView = (TextView)findViewById(R.id.DisplayTextView);
 75 
 76         chatPage = (View)findViewById(R.id.chatPage);
 77         controlPage = (View)findViewById(R.id.controlPage);
 78         displayPage = (View)findViewById(R.id.displayPage);
 79     }
 80     //发送一条消息
 81     private void sendMessage(String message){
 82         if (mChatService.getState()!=BluetoothChatService.STATE_CONNECTED){
 83             Toast.makeText(this, "未连接蓝牙设备", Toast.LENGTH_SHORT).show();
 84             return;
 85         }
 86         if (message.length()>0){
 87             byte[] send = message.getBytes();
 88             mChatService.write(send);
 89             messageEditText.setText("");
 90         }
 91     }
 92     //*********************************************************************************
 93     //建立菜单
 94     @Override
 95     public boolean onCreateOptionsMenu(Menu menu) {
 96         getMenuInflater().inflate(R.menu.option_menu,menu);
 97         return true;
 98     }
 99     //菜单响应事件,主要完成界面切换
100     @Override
101     public boolean onOptionsItemSelected(MenuItem item) {
102         switch (item.getItemId()){
103             case R.id.scan:  //点击“Scan”项,执行DeviceListActivity,在onActivityResult中返回用户点击连接的蓝牙MAC地址
104                 Intent serverIntent = new Intent(this,DeviceListActivity.class);
105                 startActivityForResult(serverIntent,REQUEST_CONNECT_DEVICE);
106                 return true;
107             case R.id.chatPage:
108                 chatPage.setVisibility(View.VISIBLE);
109                 displayPage.setVisibility(View.GONE);
110                 controlPage.setVisibility(View.GONE);
111                 return true;
112             case R.id.displayPage:
113                 chatPage.setVisibility(View.GONE);
114                 displayPage.setVisibility(View.VISIBLE);
115                 controlPage.setVisibility(View.GONE);
116                 return true;
117             case R.id.controlPage:
118                 chatPage.setVisibility(View.GONE);
119                 displayPage.setVisibility(View.GONE);
120                 controlPage.setVisibility(View.VISIBLE);
121                 return true;
122         }
123         return false;
124     }
125     //**********************************************************************************************
126     //获得DeviceList活动反馈回的蓝牙设备地址,获取BluetoothDevice,开始连接
127     @Override
128     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
129         switch (requestCode){
130             case REQUEST_CONNECT_DEVICE:
131                 //获取蓝牙地址并执行连接
132                 if(resultCode== Activity.RESULT_OK){
133                     String address = data.getExtras()
134                             .getString(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
135                     BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
136                     mChatService.connect(device);
137 
138                 }
139         }
140     }
141     //**********************************************************************************************
142     //主要负责更新UI
143     private final Handler mHandler = new Handler(){
144         @Override
145         public void handleMessage(Message msg) {
146 
147             switch (msg.what){
148                 case MESSAGE_STATE_CHANGE:
149                     switch (msg.arg1){
150                         case BluetoothChatService.STATE_CONNECTED:
151                             stateTextView.setText("状态:已连接");
152                             break;
153                         case BluetoothChatService.STATE_CONNECTING:
154                             stateTextView.setText("状态:正连接");
155                             break;
156                         case BluetoothChatService.STATE_NONE:
157                             stateTextView.setText("状态:未连接");
158                             break;
159                     }
160                     break;
161                 case MESSAGE_TOAST:
162                     Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST),
163                             Toast.LENGTH_SHORT).show();
164                     break;
165                 case MESSAGE_DEVICE_NAME:
166                     mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
167                     deviceTextView.setText("设备:"+mConnectedDeviceName);
168                     Toast.makeText(MainActivity.this, "已连接上"+mConnectedDeviceName, Toast.LENGTH_SHORT).show();
169                     break;
170                 case MESSAGE_READ:
171                     if (chatPage.getVisibility() == View.VISIBLE){
172                         displayTextView.append(mConnectedDeviceName+":"+msg.obj+"\\n");
173                         numofMessage++;
174                         if (numofMessage==10) {
175                             displayTextView.setText("");
176                             numofMessage = 0;
177                         }
178                     }
179                     break;
180                 case MESSAGE_WRITE:
181                     byte[] writeBuf = (byte[]) msg.obj;
182                     String writeMessage = new String(writeBuf);
183                     if (chatPage.getVisibility() == View.VISIBLE){
184                         displayTextView.append("本机:"+writeMessage+"\\n");
185                         numofMessage++;
186                         if (numofMessage==10) {
187                             displayTextView.setText("");
188                             numofMessage = 0;
189                         }
190                     }
191                     break;
192             }
193         }
194     };
195 }
  • DeviceListActivity

  1 package com.example.john.esdc;
  2 import android.annotation.SuppressLint;
  3 import android.app.Activity;
  4 import android.bluetooth.BluetoothAdapter;
  5 import android.bluetooth.BluetoothDevice;
  6 import android.content.BroadcastReceiver;
  7 import android.content.Context;
  8 import android.content.Intent;
  9 import android.content.IntentFilter;
 10 import android.support.v7.app.AppCompatActivity;
 11 import android.os.Bundle;
 12 import android.view.View;
 13 import android.view.Window;
 14 import android.widget.AdapterView;
 15 import android.widget.ArrayAdapter;
 16 import android.widget.ListView;
 17 import android.widget.TextView;
 18 import android.widget.Toast;
 19 
 20 import java.util.Set;
 21 
 22 import static android.R.attr.filter;
 23 @SuppressLint("NewApi")
 24 public class DeviceListActivity extends AppCompatActivity {
 25 
 26     // Return Intent extra
 27     public static String EXTRA_DEVICE_ADDRESS = "device_address";
 28 
 29     // Member fields
 30     private BluetoothAdapter     mBtAdapter;
 31     private ArrayAdapter<String> mPairedDevicesArrayAdapter;
 32     private ArrayAdapter<String> mNewDevicesArrayAdapter;
 33 
 34     @Override
 35     protected void onCreate(Bundle savedInstanceState) {
 36         super.onCreate(savedInstanceState);
 37         setContentView(R.layout.activity_device_list);
 38         setResult(Activity.RESULT_CANCELED);
 39         // 获取本地蓝牙适配器
 40         mBtAdapter = BluetoothAdapter.getDefaultAdapter();
 41         mBtAdapter.enable(); //打开蓝牙
 42         doDiscovery();  //开始搜索蓝牙设备
 43 
 44 
 45         //ListView控件适配器组装
 46         mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1);
 47         mNewDevicesArrayAdapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1);
 48         ListView pairedListView = (ListView)findViewById(R.id.paired_devices);
 49         pairedListView.setAdapter(mPairedDevicesArrayAdapter);
 50         pairedListView.setOnItemClickListener(mDeviceClickListener1);
 51         ListView newDevicesListView = (ListView)findViewById(R.id.new_devices);
 52         newDevicesListView.setAdapter(mNewDevicesArrayAdapter);
 53         newDevicesListView.setOnItemClickListener(mDeviceClickListener2);
 54 
 55         //注册广播
 56         IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
 57         this.registerReceiver(mReceive,filter);
 58         filter = new IntentFilter((BluetoothAdapter.ACTION_DISCOVERY_FINISHED));
 59         this.registerReceiver(mReceive,filter);
 60 
 61         //获得已配对的蓝牙设备
 62         Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
 63         if (pairedDevices.size()>0) {
 64             for (BluetoothDevice device : pairedDevices) {
 65                 mPairedDevicesArrayAdapter.add(device.getName() + "\\n" + device.getAddress());
 66             }
 67         }
 68         else{
 69             mPairedDevicesArrayAdapter.add("无已配对设备");
 70         }
 71 
 72     }
 73 
 74     //蓝牙设备列表的点击响应
 75     private AdapterView.OnItemClickListener mDeviceClickListener1 = new AdapterView.OnItemClickListener() {
 76         @Override
 77         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
 78             mBtAdapter.cancelDiscovery();
 79             //获取蓝牙设备的MAC地址返回到主活动
 80             String info = mPairedDevicesArrayAdapter.getItem(position);
 81             String address = info.substring(info.length()-17);
 82             Intent intent = new Intent();
 83             intent.putExtra(EXTRA_DEVICE_ADDRESS,address);
 84             setResult(Activity.RESULT_OK,intent);
 85             finish();
 86 
 87 
 88 
 89         }
 90     };
 91     private AdapterView.OnItemClickListener mDeviceClickListener2 = new AdapterView.OnItemClickListener() {
 92         @Override
 93         public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
 94             mBtAdapter.cancelDiscovery();
 95             //获取蓝牙设备的MAC地址返回到主活动
 96             String info = mNewDevicesArrayAdapter.getItem(position);
 97             String address = info.substring(info.length()-17);
 98             //Toast.makeText(DeviceListActivity.this, address, Toast.LENGTH_SHORT).show();
 99             Intent intent = new Intent();
100             intent.putExtra(EXTRA_DEVICE_ADDRESS,address);
101             setResult(Activity.RESULT_OK,intent);
102             finish();
103 
104 
105 
106         }
107     };
108 
109     private void doDiscovery(){
110         setTitle("扫描中,请稍等……");
111         if (mBtAdapter.isDiscovering()){
112             mBtAdapter.cancelDiscovery();
113         }
114         mBtAdapter.startDiscovery();
115     }
116 
117 
118     @Override
119     protected void onDestroy() {
120         super.onDestroy();
121         // Make sure we\'re not doing discovery anymore
122         if (mBtAdapter != null) {
123             mBtAdapter.cancelDiscovery();
124         }
125         // Unregister broadcast listeners
126         this.unregisterReceiver(mReceive);
127     }
128     //广播监听,当发现新设备时将其添加至列表
129     private final BroadcastReceiver mReceive = new BroadcastReceiver() {
130         @Override
以上是关于基于蓝牙的安卓客户端开发的主要内容,如果未能解决你的问题,请参考以下文章

安卓通讯开发——蓝牙的开启,搜索与传输

安卓开发蓝牙接收数据,返回数据如何处理

[安卓] 20基于蓝牙BLE的广播包高频快速搜索

androidstudio没有蓝牙模块

安卓怎样连接两个蓝牙?

安卓蓝牙开发 1. 发现过程