代码地址:http://download.csdn.net/detail/u011324501/9418403
备注:亲测可用,若连接失败请关闭Bluetooth chat 重新打开。
1.BluetoothAdapter 顾名思义,蓝牙适配器,直到我们建立bluetoothSocket连接之前,都要不断操作它
BluetoothAdapter里的方法很多,常用的有以下几个:
cancelDiscovery() 根据字面意思,是取消发现,也就是说当我们正在搜索设备的时候调用这个方法将不再继续搜索
disable()关闭蓝牙
enable()打开蓝牙,这个方法打开蓝牙不会弹出提示,更多的时候我们需要问下用户是否打开,一下这两行代码同样是打开蓝牙,不过会提示用户:
Intemtenabler=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enabler,reCode);//同startActivity(enabler);
getAddress()获取本地蓝牙地址
getDefaultAdapter()获取默认BluetoothAdapter,实际上,也只有这一种方法获取BluetoothAdapter
getName()获取本地蓝牙名称
getRemoteDevice(String address)根据蓝牙地址获取远程蓝牙设备
getState()获取本地蓝牙适配器当前状态(感觉可能调试的时候更需要)
isDiscovering()判断当前是否正在查找设备,是返回true
isEnabled()判断蓝牙是否打开,已打开返回true,否则,返回false
listenUsingRfcommWithServiceRecord(String name,UUID uuid)根据名称,UUID创建并返回BluetoothServerSocket,这是创建BluetoothSocket服务器端的第一步
startDiscovery()开始搜索,这是搜索的第一步
2.BluetoothDevice看名字就知道,这个类描述了一个蓝牙设备
createRfcommSocketToServiceRecord(UUIDuuid)根据UUID创建并返回一个BluetoothSocket
这个方法也是我们获取BluetoothDevice的目的——创建BluetoothSocket
这个类其他的方法,如getAddress(),getName(),同BluetoothAdapter
关于手机蓝牙各类服务对应的UUID:http://blog.csdn.net/yuanbieli/article/details/6691502
3.BluetoothServerSocket如果去除了Bluetooth相信大家一定再熟悉不过了,既然是Socket,方法就应该都差不多,这个类一种只有三个方法
两个重载的accept(),accept(inttimeout)两者的区别在于后面的方法指定了过时时间,需要注意的是,执行这两个方法的时候,直到接收到了客户端的请求(或是过期之后),都会阻塞线程,应该放在新线程里运行!
还有一点需要注意的是,这两个方法都返回一个BluetoothSocket,最后的连接也是服务器端与客户端的两个BluetoothSocket的连接。close()关闭蓝牙连接。
4.BluetoothSocket,跟BluetoothServerSocket相对,是客户端
一共5个方法,不出意外,都会用到
close(),关闭
connect()连接
getInptuStream()获取输入流
getOutputStream()获取输出流
getRemoteDevice()获取远程设备,这里指的是获取bluetoothSocket指定连接的那个远程蓝牙设备
5、蓝牙权限
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
main.xml布局代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <ScrollView android:id="@+id/scrollview" android:layout_width="fill_parent" android:layout_height="250dip" android:scrollbars="vertical" > <TextView android:id="@+id/textview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="" /> </ScrollView> <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" > <Button android:id="@+id/connect" android:layout_width="150dip" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_alignParentRight="true" android:layout_marginBottom="16dp" android:onClick="onConnectButtonClicked" android:text="@string/connect" android:textColor="#FFD700" /> <Button android:id="@+id/send" android:text="@string/send" android:layout_width="150dip" android:textColor="#FFD700" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/connect" android:layout_alignBottom="@+id/connect" android:layout_alignParentLeft="true" /> <EditText android:id="@+id/input" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_above="@+id/connect" android:layout_alignParentLeft="true" android:ems="10" android:inputType="none" /> </RelativeLayout> </LinearLayout>MainActivity.java代码:
package com.example.bluetooth; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.UUID; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.Intent; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.ScrollView; import android.widget.TextView; import android.widget.Toast; /* * 若连接失败请关闭Bluetooth chat 重新打开。 * * */ public class MainActivity extends Activity { private BluetoothAdapter _bluetooth = BluetoothAdapter.getDefaultAdapter(); // 获取本地蓝牙适配器,即蓝牙设备 public static String smsg = ""; // 显示用数据缓存 private String fmsg = ""; // 保存用数据缓存 BluetoothDevice _device = null; // 蓝牙设备 private ScrollView scrollview; // 翻页句柄 public static BluetoothSocket _socket = null; // 蓝牙通信socket private final static int REQUEST_CONNECT_DEVICE = 1; // 宏定义查询设备句柄 //private final static String MY_UUID = "00001101-0000-1000-8000-00805F9B34FB"; // SPP服务UUID号 private final static String MY_UUID = "fa87c0d0-afac-11de-8a39-0800200c9a66"; // SPP服务UUID号 private InputStream is; // 输入流,用来接收蓝牙数据 boolean _discoveryFinished = false; boolean bRun = true; boolean abc = true; boolean bThread = false; private TextView textview; private Button connect; private Button send; private EditText input; private String inputdate; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); initUI(); } //初始化ui private void initUI() { // TODO Auto-generated method stub bluetooth(); textview = (TextView)findViewById(R.id.textview); connect = (Button)findViewById(R.id.connect); input = (EditText)findViewById(R.id.input); send = (Button)findViewById(R.id.send); send.setOnClickListener(new sendListener()); scrollview = (ScrollView)findViewById(R.id.scrollview); } //发送数据 public class sendListener implements OnClickListener{ @Override public void onClick(View arg0) { // TODO Auto-generated method stub inputdate = input.getText().toString();//获取发送数据 if(inputdate!=null && _device!=null){ send(inputdate); }else{ Toast.makeText(getApplication(), "请输入数据或查看蓝牙是否有连接!", Toast.LENGTH_SHORT).show(); } } } public void bluetooth(){ // 如果打开本地蓝牙设备不成功,提示信息,结束程序 if (_bluetooth == null) { Toast.makeText(this, "无法打开手机蓝牙,请确认手机是否有蓝牙功能!", Toast.LENGTH_LONG) .show(); finish(); return; } // 设置设备可以被搜索 new Thread() { public void run() { if (_bluetooth.isEnabled() == false) { _bluetooth.enable(); } } }.start(); } // 接收活动结果,响应startActivityForResult() public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case REQUEST_CONNECT_DEVICE: // 连接结果,由DeviceListActivity设置返回 // 响应返回结果 if (resultCode == Activity.RESULT_OK) { // 连接成功,由DeviceListActivity设置返回 // MAC地址,由DeviceListActivity设置返回 String address = data.getExtras().getString( DeviceListActivity.EXTRA_DEVICE_ADDRESS); // 得到蓝牙设备句柄 _device = _bluetooth.getRemoteDevice(address); // 用服务号得到socket try { _socket = _device.createRfcommSocketToServiceRecord(UUID.fromString(MY_UUID)); // 创建蓝牙客户端 } catch (IOException e) { Toast.makeText(this, "连接失败!", Toast.LENGTH_SHORT).show(); } // 连接socket try { _socket.connect(); Toast.makeText(this, "连接" + _device.getName() + "成功!", Toast.LENGTH_SHORT).show(); connect.setText("断开"); } catch (IOException e) { try { Toast.makeText(this, "连接失败!", Toast.LENGTH_SHORT) .show(); _socket.close(); _socket = null; } catch (IOException ee) { Toast.makeText(this, "连接失败!", Toast.LENGTH_SHORT) .show(); } return; } // 打开接收线程 try { is = _socket.getInputStream(); // 得到蓝牙数据输入流 } catch (IOException e) { Toast.makeText(this, "接收数据失败!", Toast.LENGTH_SHORT).show(); return; } if (bThread == false) { ReadThread.start(); bThread = true; } else { bRun = true; } } break; default: break; } } // 接收数据线程 Thread ReadThread = new Thread() { public void run() { int num = 0; byte[] buffer = new byte[1024]; byte[] buffer_new = new byte[1024]; int i = 0; int n = 0; bRun = true; // 接收线程 while (true) { try { while (is.available() == 0) { while (bRun == false) { } } while (true) { num = is.read(buffer); // 读入数据 n = 0; String s0 = new String(buffer, 0, num); fmsg += s0; // 保存收到数据 for (i = 0; i < num; i++) { if ((buffer[i] == 0x0d) && (buffer[i + 1] == 0x0a)) { buffer_new[n] = 0x0a; i++; } else { buffer_new[n] = buffer[i]; } n++; } String s = new String(buffer_new, 0, n); if (abc == true) smsg += s+"\n"; // 写入接收缓存,并换行 if (is.available() == 0) break; // 短时间没有数据才跳出进行显示 } // 发送显示消息,进行显示刷新 handler.sendMessage(handler.obtainMessage()); } catch (IOException e) { } } } }; // 消息处理队列 Handler handler = new Handler() { public void handleMessage(Message msg) { super.handleMessage(msg); if (abc == true) { textview.setText(smsg); //显示数据 //smsg = ""; scrollview.scrollTo(0, textview.getMeasuredHeight()); // 跳至数据最后一页 } } }; // 关闭程序掉用处理部分 public void onDestroy() { super.onDestroy(); if (_socket != null) // 关闭连接socket try { _socket.close(); } catch (IOException e) { } // _bluetooth.disable(); //关闭蓝牙服务 } // 连接按键响应函数 public void onConnectButtonClicked(View v) { if (_bluetooth.isEnabled() == false) { // 如果蓝牙服务不可用则提示 Toast.makeText(this, " 打开蓝牙中...", Toast.LENGTH_LONG).show(); return; } // 如未连接设备则打开DeviceListActivity进行设备搜索 if (_socket == null) { Intent serverIntent = new Intent(this, DeviceListActivity.class); // 跳转程序设置 startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE); // 设置返回宏定义 } else { // 关闭连接socket try { is.close(); _socket.close(); _socket = null; bRun = false; connect.setText("连接"); } catch (IOException e) { } } return; } // 通过蓝牙发送数据 public void send(String msg) { // int i=0; // int n=0; try { // System.out.println(111111); OutputStream os = _socket.getOutputStream(); // 蓝牙连接输出流 byte[] bos = msg.getBytes(); // bytesToHexString(bos); os.write(bos); System.out.println("发送成功"); } catch (IOException e) { System.out.println("发送失败"); } } /* * 发送数据 */ public void sendmesg(String msg) { int i = 0; int n = 0; try { OutputStream os = _socket.getOutputStream(); // 蓝牙连接输出流 // byte[] bos = edit0.getText().toString().getBytes(); byte[] bos = msg.getBytes(); for (i = 0; i < bos.length; i++) { if (bos[i] == 0x0a) n++; } byte[] bos_new = new byte[bos.length + n]; n = 0; for (i = 0; i < bos.length; i++) { // 手机中换行为0a,将其改为0d 0a后再发送 if (bos[i] == 0x0a) { bos_new[n] = 0x0d; n++; bos_new[n] = 0x0a; } else { bos_new[n] = bos[i]; } n++; } os.write(bos_new); } catch (IOException e) { } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }DeviceListActivity.java代码:
package com.example.bluetooth; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; import android.util.Log; import android.view.View; import android.view.Window; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.ListView; import android.widget.TextView; import android.widget.AdapterView.OnItemClickListener; public class DeviceListActivity extends Activity { // 调试用 private static final String TAG = "DeviceListActivity"; private static final boolean D = true; // 返回时数据标签 public static String EXTRA_DEVICE_ADDRESS = "设备地址"; // 成员域 private BluetoothAdapter mBtAdapter; private ArrayAdapter<String> mPairedDevicesArrayAdapter; private ArrayAdapter<String> mNewDevicesArrayAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 创建并显示窗口 requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); // 设置窗口显示模式为窗口方式 setContentView(R.layout.device_list); // 设定默认返回值为取消 setResult(Activity.RESULT_CANCELED); // 设定扫描按键响应 Button scanButton = (Button) findViewById(R.id.button_scan); scanButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { doDiscovery(); v.setVisibility(View.GONE); } }); // 初使化设备存储数组 mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name); mNewDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name); // 设置已配队设备列表 ListView pairedListView = (ListView) findViewById(R.id.paired_devices); pairedListView.setAdapter(mPairedDevicesArrayAdapter); pairedListView.setOnItemClickListener(mDeviceClickListener); // 设置新查找设备列表 ListView newDevicesListView = (ListView) findViewById(R.id.new_devices); newDevicesListView.setAdapter(mNewDevicesArrayAdapter); newDevicesListView.setOnItemClickListener(mDeviceClickListener); // 注册接收查找到设备action接收器 IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); this.registerReceiver(mReceiver, filter); // 注册查找结束action接收器 filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); this.registerReceiver(mReceiver, filter); // 得到本地蓝牙句柄 mBtAdapter = BluetoothAdapter.getDefaultAdapter(); // 得到已配对蓝牙设备列表 // Set<BluetoothDevice> pairedDevices = mBtAdapter.getBondedDevices(); // 添加已配对设备到列表并显示 // if (pairedDevices.size() > 0) { // findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE); // for (BluetoothDevice device : pairedDevices) { // mPairedDevicesArrayAdapter.add(device.getName() + "\n" + // device.getAddress()); // } // } else { // String noDevices = "No devices have been paired"; // mPairedDevicesArrayAdapter.add(noDevices); // } } @Override protected void onDestroy() { super.onDestroy(); // 关闭服务查找 if (mBtAdapter != null) { mBtAdapter.cancelDiscovery(); } // 注销action接收器 this.unregisterReceiver(mReceiver); } public void OnCancel(View v) { finish(); } /** * 开始服务和设备查找 */ private void doDiscovery() { if (D) Log.d(TAG, "doDiscovery()"); // 在窗口显示查找中信息 setProgressBarIndeterminateVisibility(true); setTitle("查找设备中..."); // 显示其它设备(未配对设备)列表 findViewById(R.id.title_new_devices).setVisibility(View.VISIBLE); // 关闭再进行的服务查找 if (mBtAdapter.isDiscovering()) { mBtAdapter.cancelDiscovery(); } // 并重新开始 mBtAdapter.startDiscovery(); } // 选择设备响应函数 private OnItemClickListener mDeviceClickListener = new OnItemClickListener() { public void onItemClick(AdapterView<?> av, View v, int arg2, long arg3) { // 准备连接设备,关闭服务查找 mBtAdapter.cancelDiscovery(); // 得到mac地址 String info = ((TextView) v).getText().toString(); String address = info.substring(info.length() - 17); // 设置返回数据 Intent intent = new Intent(); intent.putExtra(EXTRA_DEVICE_ADDRESS, address); // 设置返回值并结束程序 setResult(Activity.RESULT_OK, intent); finish(); } }; // 查找到设备和搜索完成action监听器 private final BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); // 查找到设备action if (BluetoothDevice.ACTION_FOUND.equals(action)) { // 得到蓝牙设备 BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // 如果是已配对的则略过,已得到显示,其余的在添加到列表中进行显示 if (device.getBondState() != BluetoothDevice.BOND_BONDED) { mNewDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress()); } else { // 添加到已配对设备列表 mPairedDevicesArrayAdapter.add(device.getName() + "\n" + device.getAddress()); } // 搜索完成action } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED .equals(action)) { setProgressBarIndeterminateVisibility(false); setTitle("选择要连接的设备"); if (mNewDevicesArrayAdapter.getCount() == 0) { String noDevices = "没有找到新设备"; mNewDevicesArrayAdapter.add(noDevices); } // if(mPairedDevicesArrayAdapter.getCount() > 0) // findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE); } } }; }