吼,花了2天最后做出了一个类似于蓝牙串口助手功能的小程序,其实也是实习公司的要求---有一个蓝牙无线扫描枪,要求终端可以通过蓝牙连接到该设备,并且蓝牙无线扫描枪扫描二维码或者条形码的时候可以将二维码或者条形码的数据输出到TextView中。
听效果是不是感觉很好做。说明下蓝牙扫描器的功能,有2中常用的模式--普通模式,SPP模式。 普通模式的话就是相当于蓝牙连接后,扫描器就相当于一个外接的键盘,可以扫码然后将数据输出到EditText(必须获得焦点)。SPP模式则是用于模拟串口通信的,在我看来就相当于开发者模式。。。
主要代码就是Edittext的setOnKeyListener里设置就好了。
et.setOnKeyListener(new EditText.OnKeyListener() { @Override publicboolean onKey(View v, int keyCode, KeyEvent event) { tv.setText(et.getText()); returnfalse; } });
操作简单,思路清晰,简单粗暴!但是问题也很多,万一你一个界面好多个EditText,比如登陆界面,除了你的那个自己知道别人看不到的EditText,还得有两个EditText,一旦某一个获得光标,你的扫描器就失去了作用,还会吓使用者一跳。所以这种方案不适合用在需要推送的APP上。
https://segmentfault.com/a/1190000004899799
http://www.cnblogs.com/wenjiang/p/3200138.html
具体的解释我会在代码里说,光说理论本人菜的抠脚。首先说说布局,超级简单。一个TextView,一个EditText(测试用的) , 一个Button(可以根据自己的需要去掉)。码就不贴了,到时候直接发项目吧!
说说Button的点击事件(可以根据自己的需求进行修改),点击进入一个Activity显示所有的扫描到的蓝牙设备--DeviceListAcitivty
DeviceListActivity里面需要做的事情就是将能扫描到的蓝牙设备显示在ListView中,如果你确定你只要连接一种设备的话并且知道设备的Address的话你大可省略这个操作。这里当学习用。
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<>(this, R.layout.device_name); mNewDevicesArrayAdapter = new ArrayAdapter<>(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); } } }; }
代码贴在上面,具体的代码解释也写在代码上了,其实我后面是不打算做这部操作的,因为针对只需要连接一个蓝牙设备的程序来说,当我知道了蓝牙设备的Mac地址我就可以直接找到设备,根本不需要查询。但不得不说回来, 当厂家没有给你蓝牙设备的Mac地址的时候。你就不得不做这步操作了!所以推荐的话还是把这步操作给做了的好,具体怎么操作还是得看项目的要求。至于如何查找蓝牙设备以及蓝牙设备的状态,上面的代码写的很详细,结合我之前推荐的两篇文章就很好懂了。
但由于它写的代码过于复杂也不是一个框架可以直接利用,所以就没有深究。https://github.com/hzjerry/BluetoothSppPro。
没办法了,实践是检验真理的唯一标准那就只能开始自己测试了,接下来第二篇文章就发挥了作用,可能我不需要实现ServerSocket服务端的编程,在使用蓝牙串口助手测试的时候,你配对上加连接上就可以直接用了,说明我只需要和它(蓝牙枪)能连接上就好了。连接的做法步骤如下:
btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mBluetoothDevice = mBluetoothAdapter.getRemoteDevice(address); try{ mBluetoothSocket = mBluetoothDevice. createRfcommSocketToServiceRecord (UUID.fromString(MY_UUID)); }catch (IOException e){ Toast.makeText(MainActivity.this, "配对失败,原因是:" + e.getMessage(), Toast.LENGTH_SHORT) .show(); Log.e("过程", "失败的原因是:" + e.getMessage()); } //与设备进行连接 try{ mBluetoothSocket.connect(); Toast.makeText(MainActivity.this, "连接"+ mBluetoothDevice.getName() + "成功", Toast.LENGTH_SHORT).show(); Log.e("TAGGGAGGAGGHG","连接过程"); } catch (IOException e) { try{ Toast.makeText(MainActivity.this, "连接失败,原因是:" + e.getMessage(), Toast.LENGTH_SHORT).show(); mBluetoothSocket.close(); mBluetoothSocket = null; Log.e("连接失败", "连接失败的原因是:" + e.getMessage()); } catch (IOException e1) { e1.printStackTrace(); } return; } //与设备进行数据传输 try{ is = mBluetoothSocket.getInputStream(); }catch (IOException e){ Toast.makeText(MainActivity.this, "接收数据失败", Toast.LENGTH_SHORT).show(); return; } if(ready_receive == false){ ReadThread.start(); ready_receive = true; }else { isReceiving = true; } } });
Thread ReadThread = new Thread(){ public void run(){ int num = 0; byte[] buffer = new byte[1024]; byte[] buffer_new = new byte[1024]; int n = 0; isReceiving= true; while(true){ try { while (is.available() == 0){ while (isReceiving == false){} } while(true){ num = is.read(buffer); n = 0; String s0 = new String(buffer, 0, num); // fmsg += s0; for (int 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); receive_msg += s; if (is.available() == 0) break; } handler.sendMessage(handler.obtainMessage()); }catch (IOException e){ } } } };
这样就完成了蓝牙串口助手的部分功能,具体的实例见源码下载。
http://download.csdn.net/detail/cuihaoren01/9496677
扫描蓝牙设备,选择需要连接的设备,进行传输。
http://download.csdn.net/detail/cuihaoren01/9496711