最近要做两个Android demo 。第一个要求用手机蓝牙连接打印机实现手填报表打印功能,第二个是手机蓝牙连接的手持设备,需求同步里面的数据,同步成功后要删除设备里面的数据。
先开始玩的是佳能IP100的打印机, 发现这款打印机蓝牙只能实现打印图片功能,文档什么的要么接受了没反应,要么就乱码。 后来又玩了下佳能IP110的, 这款机型实现的是wifi无线打印 。 由于用户需求最后研究了IP100蓝牙打印 。 网上搜了关于蓝牙打印的东西不多, 其中有个看起来挺不错了, 但他好像是热敏打印机,在我这儿没法使用 连接: 热敏打印机 ; 最后自己用了一个比较偷懒快捷的方式把测试Demo的功能实现了。
String photoUri= Environment.getExternalStorageDirectory()+"/CheckAPP/Screen.jpg";
public void SharePhoto(String photoUri,final Activity activity) {
Intent shareIntent = new Intent(Intent.ACTION_SEND);
File file = new File(photoUri);
shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file));
shareIntent.setType("image/jpeg");
startActivity(Intent.createChooser(shareIntent, activity.getTitle()));
}
调用截屏的功能,将图片保存到手机sd卡中
/**
* 截屏方法
* @return
*/
private Bitmap shot() {
View view = getWindow().getDecorView();
Display display = this.getWindowManager().getDefaultDisplay();
view.layout(0, 0, display.getWidth(), display.getHeight());
view.setDrawingCacheEnabled(true);//允许当前窗口保存缓存信息,这样getDrawingCache()方法才会返回一个Bitmap
ScreenBmp = Bitmap.createBitmap(view.getDrawingCache());
return ScreenBmp;
}
这样一个用户填写表格实现打印的功能就这样的完成了 。 虽然比较low也算是实现了^_^, 后续如果可以拿到佳能提供的驱动也是可以更灵活的去实现。
后期发现用截图的这个工具并不是很方便, 因为对于纸张的大小跟文字图片摆放的位置还是有局限性的。 后来用到的还是绘图工具Canvas。创建一个内部类PrintView继承View然后声明Canvas、Paint跟Bitmap 。 在初始PaintView的时候同时也初始这些绘图工具 。
由于我打印的表格都是用户输入的,所以同时创建了javabean类跟.txt文本用于保存用户输入的这些表格信息(PS:也可以创建sqlite用与保存本地) 。 在当用户点击打印的时候去解析是哪张表 来读取信息赋值给相应的javaBean。 然后就能生成图片, 进行分享打印图片咯
第二个Demo要求手机蓝牙连接的手持设备,需求是同步里面的数据,同步成功后要删除里面的数据。 于是就要用到了BluetoothDevice 并接收BluetoothGattCallback 的回调 。并在onCharacteristicRead 中对数据进行操作,在操作完成之后通过BluetoothGatt.writeCharacteristic 来写入收据 删除设备中的记录数据。
BluetoothAdapter
BluetoothAdapter 拥有基本的蓝牙操作,例如开启蓝牙扫描,使用已知的 MAC 地址 (BluetoothAdapter#getRemoteDevice)实例化一个 BluetoothDevice 用于连接蓝牙设备的操作等等。
BluetoothDevice
代表一个远程蓝牙设备。这个类可以让你连接所代表的蓝牙设备或者获取一些有关它的信息,例如它的名字,地址和绑定状态等等。
BluetoothGatt
这个类提供了 Bluetooth GATT 的基本功能。例如重新连接蓝牙设备,发现蓝牙设备的 Service 等等。
BluetoothGattService
这一个类通过 BluetoothGatt#getService 获得,如果当前服务不可见那么将返回一个 null。这一个类对应上面说过的 Service。我们可以通过这个类的 getCharacteristic(UUID uuid) 进一步获取 Characteristic 实现蓝牙数据的双向传输。
BluetoothGattCharacteristic
这个类对应上面提到的 Characteristic。通过这个类定义需要往外围设备写入的数据和读取外围设备发送过来的数据。
//使用蓝牙所需要的权限
//使用扫描和设置蓝牙的权限(申明这一个权限必须申明上面一个权限)
1、检查当前手机是否支持ble 蓝牙,如果不支持退出程序
// 检查当前手机是否支持ble 蓝牙,如果不支持退出程序
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, “当前设备不支持”, Toast.LENGTH_SHORT).show();
Blutooth_Activity.this.finish();
}
2、初始化 Bluetooth adapter, 通过蓝牙管理器得到一个参考蓝牙适配器(API必须在以上android4.3或以上和版本)
// 初始化Bluetooth adapter, 通过蓝牙管理器得到一个参考蓝牙适配器(API必须在以上android4.3或以上和版本)
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothAdapter = bluetoothManager.getAdapter();
3、为了确保设备上蓝牙能使用, 如果当前蓝牙设备没启用,弹出对话框向用户要求授予权限来启用
// 为了确保设备上蓝牙能使用, 如果当前蓝牙设备没启用,弹出对话框向用户要求授予权限来启用
if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
1.开启扫描
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
/**
* @param device 蓝牙设备类 包含了名字,MAC 地址
* @param arg1 信号强弱指标
* @param arg2 蓝牙广播出来的数据 包含了广播数据 和 扫描应答数据
*/
@Override
public void onLeScan(final BluetoothDevice device, int arg1, byte[] arg2) {
// TODO Auto-generated method stub
runOnUiThread(new Runnable() {
public void run() {
mLeDeviceListAdapter.addDevice(device);
}
});
}
};
2.停止扫描
mBluetoothAdapter.stopLeScan(mLeScanCallback);
// 得到该蓝牙MAc的设备
BluetoothDevice localBluetoothDevice = myBluetoothAdapter.getRemoteDevice(paramString);
if(localBluetoothDevice==null)
return false;
/**
* 连接Gatt ,回调,返回BluetoothGatt
* 第二个字段 是否需要自动连接。如果设置为 true, 表示如果设备断开了,会不断的尝试自动连接。设置为 false 表示只进行一次连接尝试。
*/
myBluetoothGatt=localBluetoothDevice.connectGatt(this,true,myGattCallback);
其中paramString 就是刚才LeScanCallback 中device的字段
在建立连接之后,就可以通过 BluetoothGatt实例 进行发现服务操作,查找设备支持的服务。BluetoothGatt中有几个重要的方法需要重写:onConnectionStateChange()、onServicesDiscovered()、onCharacteristicRead()、onCharacteristicWrite()、onCharacteristicChanged()。
当onConnectionStateChange方法被成功回调并且状态为BluetoothProfile.STATE_CONNECTED,如果状态为BluetoothProfile.STATE_DISCONNECTED则表示连接断开
当onServicesDiscovered 方法被回调成功后手机设备和蓝牙设备才算是真正建立了可通信的连接。意味着可以执行如:写入数据,读取蓝牙设备的数据等操作了
/**
* 读操作的回调
* @param characteristic: 读取后的特征
* @param status: 读取结果,成功为 GATT_SUCCESS
*/
void onCharacteristicRead(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic,
int status) { ··· }
/**
*
* @param dataString 写入的值
*/
private void writeStringToGatt(String dataString) {
if (dataString != null){
byte[] data = getBytesByString(dataString);
writeGattCharacteristic.setValue(data);
myBluetoothGatt.writeCharacteristic(writeGattCharacteristic);
}else {
return;
}
}
其中getBytesByString()方法是将转换成16进制 在转成byte数组类型 写入到数据通道Characteristic 这个类中,传给BluetoothGatt
/**
* 启用或禁用给定特征的通知或指示
* @param characteristic: 需要进行操作的特征
* @param enable : 开启或关闭
*/
BluetoothGatt.setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
boolean enable);
更新推送会回调BluetoothGattCallback的onCharacteristicChanged()方法:
/**
* 特征变更推送触发的回调
* @param gatt: 特征 关联的 BluetoothGatt 实例
* @param characteristic: 更新后的 特征
*/
void onCharacteristicChanged(BluetoothGatt gatt,
BluetoothGattCharacteristic characteristic)
/* 断开当前连接,如果正在连接中,则取消连接操作 */
BluetoothGatt.disconnect();
BluetoothGatt==null
最近有读者找我要源码由于时间过了太久, 有需要的同学可以参照代码。具体全部的代码我贴出来了(业务代码有点繁琐可以忽略,整体功能是没问题的)
有什么问题也可以直接联系我的扣扣850773882。 愿我们可以互相成长 (#^.^#)