mBtAdapter = BluetoothAdapter.getDefaultAdapter();
mBtAdapter.enable();
Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices();
mBtAdapter.startDiscovery();
device.getName()
device.getAddress()
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address)
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
BluetoothSocket bluetoothSocket= device.createRfcommSocketToServiceRecord(MY_UUID)
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 <LinearLayout11 android:layout_width="match_parent"12 android:layout_height="wrap_content"13 android:background="#CDC9C9">14 <TextView15 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 <TextView24 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 <LinearLayout35 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 <LinearLayout44 android:layout_width="match_parent"45 android:layout_height="wrap_content"46 47 >48 <EditText49 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 <Button56 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 <LinearLayout65 android:layout_width="match_parent"66 android:layout_height="wrap_content">67 <TextView68 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 <LinearLayout77 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 <LinearLayout85 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>
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 @Override101 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 @Override128 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 //主要负责更新UI143 private final Handler mHandler = new Handler(){144 @Override145 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 }
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 @Override119 protected void onDestroy() {120 super.onDestroy();121 // Make sure we‘re not doing discovery anymore122 if (mBtAdapter != null) {123 mBtAdapter.cancelDiscovery();124 }125 // Unregister broadcast listeners126 this.unregisterReceiver(mReceive);127 }128 //广播监听,当发现新设备时将其添加至列表129 private final BroadcastReceiver mReceive = new BroadcastReceiver() {130 @Override131 public void onReceive(Context context, Intent intent) {132 String action = intent.getAction();133 if(BluetoothDevice.ACTION_FOUND.equals(action)){134 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);135 if (device.getBondState()!=BluetoothDevice.BOND_BONDED){136 mNewDevicesArrayAdapter.add(device.getName()+"\n"+device.getAddress());137 }138 }else if(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){139 setTitle("请点击设备进行连接:");140 if(mNewDevicesArrayAdapter.getCount() == 0){141 mNewDevicesArrayAdapter.add("没有搜索到新设备");142 }143 }144 145 }146 };147 }
1 package com.example.john.esdc; 2 3 import android.annotation.SuppressLint; 4 import android.app.Notification; 5 import android.bluetooth.BluetoothAdapter; 6 import android.bluetooth.BluetoothDevice; 7 import android.bluetooth.BluetoothSocket; 8 import android.content.Context; 9 import android.os.Bundle; 10 import android.os.Handler; 11 import android.os.Message; 12 import android.util.Log; 13 import android.widget.Toast; 14 15 import java.io.BufferedReader; 16 import java.io.IOException; 17 import java.io.InputStream; 18 import java.io.InputStreamReader; 19 import java.io.OutputStream; 20 import java.util.UUID; 21 22 /** 23 * Created by john on 2017/2/21. 24 */ 25 26 @SuppressLint("NewApi") 27 public class BluetoothChatService { 28 29 // Unique UUID for this application 30 private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); 31 // Member fields 32 private final BluetoothAdapter mAdapter; 33 private final Handler mHandler; 34 private int mState; 35 private ConnectThread mConnectThread; 36 private ConnectedThread mConnectedThread; 37 private OutputStream mmOutStream=null; 38 39 // Constants that indicate the current connection state 40 public static final int STATE_NONE = 0; // we‘re doing nothing 41 public static final int STATE_LISTEN = 1; // now listening for incoming connections 42 public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection 43 public static final int STATE_CONNECTED = 3; // now connected to a remote device 44 45 //构造函数 46 public BluetoothChatService(Context context,Handler handler){ 47 mAdapter = BluetoothAdapter.getDefaultAdapter(); 48 mState = STATE_NONE; 49 mHandler = handler; 50 } 51 //设置蓝牙状态并且通过Hander通知UI更新状态 52 private synchronized void setState(int state){ 53 mState = state; 54 Message message = new Message(); 55 message.what = MainActivity.MESSAGE_STATE_CHANGE; 56 message.arg1 = state; 57 mHandler.sendMessage(message); 58 } 59 public synchronized int getState(){ 60 return mState; 61 } 62 63 //停止所有线程 64 public synchronized void stop() { 65 if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} 66 if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} 67 setState(STATE_NONE); 68 } 69 //连接失败函数,通过UI发出“连接失败”的Toast 70 private void connectionFailed() { 71 setState(STATE_NONE); 72 // Send a failure message back to the Activity 73 Message msg = mHandler.obtainMessage(MainActivity.MESSAGE_TOAST); 74 Bundle bundle = new Bundle(); 75 bundle.putString(MainActivity.TOAST, "连接失败"); 76 msg.setData(bundle); 77 mHandler.sendMessage(msg); 78 } 79 //连接丢失函数,通过UI发出“连接丢失”的Toast 80 private void connectionLost() { 81 setState(STATE_NONE); 82 83 // Send a failure message back to the Activity 84 Message msg = mHandler.obtainMessage(MainActivity.MESSAGE_TOAST); 85 Bundle bundle = new Bundle(); 86 bundle.putString(MainActivity.TOAST, "连接丢失"); 87 msg.setData(bundle); 88 mHandler.sendMessage(msg); 89 } 90 private void sendFailed(){ 91 Message msg = mHandler.obtainMessage(MainActivity.MESSAGE_TOAST); 92 Bundle bundle = new Bundle(); 93 bundle.putString(MainActivity.TOAST, "发送失败"); 94 msg.setData(bundle); 95 mHandler.sendMessage(msg); 96 } 97 //连接函数 98 public synchronized void connect(BluetoothDevice device){ 99 mConnectThread = new ConnectThread(device);100 mConnectThread.start();101 setState(STATE_CONNECTING);102 }103 //连接线程类104 private class ConnectThread extends Thread{105 private final BluetoothSocket mmSocket;106 private final BluetoothDevice mmDevice;107 //构造函数,获得BluetoothDevice,BluetoothSocket108 public ConnectThread(BluetoothDevice device){109 mmDevice = device;110 BluetoothSocket tmp = null;111 try{112 tmp = device.createRfcommSocketToServiceRecord(MY_UUID);113 }catch (IOException e){114 connectionFailed();115 }116 mmSocket = tmp;117 }118 //连接线程的执行逻辑,连接成功后转到ConnectedThraed119 public void run(){120 mAdapter.cancelDiscovery();121 try{122 mmSocket.connect();123 }catch (IOException e){124 connectionFailed();125 try{126 mmSocket.close();127 }catch (IOException e2){128 }129 return;130 }131 //此处开始connected线程132 connected(mmSocket, mmDevice);133 134 }135 public void cancel(){136 try{137 mmSocket.close();138 }catch (IOException e){139 140 }141 }142 }143 //开始已连接线程,发消息通知主活动更新UI144 public synchronized void connected(BluetoothSocket socket,BluetoothDevice device){145 146 mConnectedThread = new ConnectedThread(socket);147 mConnectedThread.start();148 149 Message msg = mHandler.obtainMessage(MainActivity.MESSAGE_DEVICE_NAME);150 Bundle bundle = new Bundle();151 bundle.putString(MainActivity.DEVICE_NAME,device.getName());152 msg.setData(bundle);153 mHandler.sendMessage(msg);154 setState(STATE_CONNECTED);155 }156 //已连接线程类157 private class ConnectedThread extends Thread{158 private final BluetoothSocket mmSocket;159 private final InputStream mmInStream;160 //构造函数,获取InputStream,OutputStream161 public ConnectedThread(BluetoothSocket socket){162 mmSocket = socket;163 InputStream tmpIn = null;164 OutputStream tmpOut = null;165 //获取BluetoothSocket的输入输出流166 try{167 tmpIn = socket.getInputStream();168 tmpOut = socket.getOutputStream();169 }catch (IOException e){170 171 }172 mmInStream = tmpIn;173 mmOutStream = tmpOut;174 }175 //已连接线程的执行逻辑,连接之后持续监听InputStream进行读取176 public void run() {177 while (true){178 try{179 byte[] arrayOfByte = new byte[1024];180 int length = 0;181 length = mmInStream.read(arrayOfByte);182 Message msg = new Message();183 msg.what = MainActivity.MESSAGE_READ;184 msg.obj = new String(arrayOfByte,0,length);185 mHandler.sendMessage(msg);186 187 }catch (IOException e){188 connectionLost();189 return;190 }191 }192 }193 194 public void cancel(){195 try{196 mmSocket.close();197 }catch (IOException e){198 199 }200 }201 }202 //写OutputStream函数,被Send按钮触发sendMessage调用203 public void write(byte[] buffer){204 try{205 mmOutStream.write(buffer);206 mHandler.obtainMessage(MainActivity.MESSAGE_WRITE,-1,-1,buffer).sendToTarget();207 }catch (IOException e){208 return;209 }210 }211 }