您的位置:首页 > 移动开发 > Android开发

android 蓝牙打印机

2015-08-03 11:42 561 查看
最近在做一个安卓应用,其中有一个需求是要求用蓝牙连接打印机实现打印功能。一开始没有一点头绪,网上找了很多资料也找不到有用的数据。所以自己就去研究,最终,功夫不负有心人,顺利的完成了这个功能。下边贴出我写的代码,共有需要的IT哥们参考学习。

完整源码下载

我们先看看运行效果图吧。。。

1.这是主界面的效果图



贴上布局文件的代码:bluetooth_layout.xml

[html] view
plaincopy

<span style="font-size:12px"><?xml version="1.0" encoding="utf-8"?>

<RelativeLayout

android:layout_width="match_parent"

android:layout_height="match_parent" >

<Button

android:id="@+id/openBluetooth_tb"

android:layout_width="130dp"

android:layout_height="wrap_content"

android:layout_alignParentRight="true"

android:layout_marginRight="18dp"

android:layout_marginTop="5dp"

android:text="打开蓝牙" />

<Button

android:id="@+id/searchDevices"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_below="@+id/openBluetooth_tb"

android:layout_marginTop="20dp"

android:text="搜索设备" />

<View

android:layout_width="match_parent"

android:layout_height="3dp"

android:layout_alignParentLeft="true"

android:layout_below="@+id/searchDevices"

android:background="@android:color/darker_gray" />

<LinearLayout

android:id="@+id/linearLayout1"

android:layout_width="match_parent"

android:layout_height="150dp"

android:layout_marginTop="125dp"

android:orientation="vertical" >

<TextView

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="未配对设备" />

<ListView

android:id="@+id/unbondDevices"

android:layout_width="wrap_content"

android:layout_height="wrap_content" />

</LinearLayout>

<View

android:layout_width="match_parent"

android:layout_height="3dp"

android:layout_alignParentLeft="true"

android:layout_below="@+id/searchDevices"

android:layout_marginTop="160dp"

android:background="@android:color/darker_gray" />

<LinearLayout

android:layout_width="match_parent"

android:layout_height="190dp"

android:layout_marginTop="288dp"

android:orientation="vertical" >

<TextView

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="已配对设备" />

<ListView

android:id="@+id/bondDevices"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_below="@+id/linearLayout1" >

</ListView>

</LinearLayout>

<Button

android:id="@+id/return_Bluetooth_btn"

android:layout_width="100dp"

android:layout_height="wrap_content"

android:layout_above="@+id/searchDevices"

android:layout_alignParentLeft="true"

android:text="返回" />

</RelativeLayout></span>

从上边的布局文件中不难看出,其中有两个ListView,OK,那下边贴出对应的两个item布局文件

--> 第一个item:unbonddevice_item.xml

[html] view
plaincopy

<span style="font-size:14px"><?xml version="1.0" encoding="utf-8"?>

<RelativeLayout

android:layout_width="match_parent"

android:layout_height="match_parent" >

<TextView

android:id="@+id/device_name"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_alignParentTop="true"

android:text="未绑定设备"

android:textAppearance="?android:attr/textAppearanceLarge" />

</RelativeLayout></span>

-->第二个item:bonddevice_item.xml

[html] view
plaincopy

<span style="font-size:14px"><?xml version="1.0" encoding="utf-8"?>

<RelativeLayout

android:layout_width="match_parent"

android:layout_height="match_parent" >

<TextView

android:id="@+id/device_name"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_alignParentTop="true"

android:text="已绑定设备"

android:textAppearance="?android:attr/textAppearanceLarge" />

</RelativeLayout></span>

2.还有另外一个布局文件,就是当点击已绑定蓝牙设备下边的某个item时进入打印的界面,不多说,看图!



代码如下:printdata_layout.xml

[html] view
plaincopy

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout

android:layout_width="match_parent"

android:layout_height="match_parent" >

<EditText

android:id="@+id/print_data"

android:layout_width="match_parent"

android:layout_height="200dp"

android:layout_alignParentLeft="true"

android:layout_alignParentTop="true"

android:layout_marginTop="46dp" >

</EditText>

<TextView

android:id="@+id/device_name"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_alignParentTop="true"

android:layout_marginTop="16dp"

android:text="Large Text"

android:textAppearance="?android:attr/textAppearanceLarge" />

<TextView

android:id="@+id/connect_state"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_alignBaseline="@+id/device_name"

android:layout_alignBottom="@+id/device_name"

android:layout_marginLeft="42dp"

android:layout_toRightOf="@+id/device_name"

android:text="Large Text"

android:textAppearance="?android:attr/textAppearanceLarge" />

<Button

android:id="@+id/send"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_below="@+id/print_data"

android:layout_marginTop="21dp"

android:text="打印" />

<Button

android:id="@+id/command"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_alignParentLeft="true"

android:layout_below="@+id/send"

android:text="指令" />

</RelativeLayout>

至此,布局文件就搞定了,接下来就要编写java代码了。主要有一下这么几个类,一个一个来哈

BluetoothActivity.java

这个类的主要作用是初始化主界面,看代码

[java] view
plaincopy

public class BluetoothActivity extends Activity {

private Context context = null;

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

this.context = this;

setTitle("蓝牙打印");

setContentView(R.layout.bluetooth_layout);

this.initListener();

}

private void initListener() {

ListView unbondDevices = (ListView) this

.findViewById(R.id.unbondDevices);

ListView bondDevices = (ListView) this.findViewById(R.id.bondDevices);

Button switchBT = (Button) this.findViewById(R.id.openBluetooth_tb);

Button searchDevices = (Button) this.findViewById(R.id.searchDevices);

BluetoothAction bluetoothAction = new BluetoothAction(this.context,

unbondDevices, bondDevices, switchBT, searchDevices,

BluetoothActivity.this);

Button returnButton = (Button) this

.findViewById(R.id.return_Bluetooth_btn);

bluetoothAction.setSearchDevices(searchDevices);

bluetoothAction.initView();

switchBT.setOnClickListener(bluetoothAction);

searchDevices.setOnClickListener(bluetoothAction);

returnButton.setOnClickListener(bluetoothAction);

}

//屏蔽返回键的代码:

public boolean onKeyDown(int keyCode,KeyEvent event)

{

switch(keyCode)

{

case KeyEvent.KEYCODE_BACK:return true;

}

return super.onKeyDown(keyCode, event);

}

}

BluetoothAction.java

这个类顾名思义,是处理bluetoothActivity中各种操作事件的action类,看代码

[java] view
plaincopy

<span style="font-size:14px">public class BluetoothAction implements OnClickListener {

private Button switchBT = null;

private Button searchDevices = null;

private Activity activity = null;

private ListView unbondDevices = null;

private ListView bondDevices = null;

private Context context = null;

private BluetoothService bluetoothService = null;

public BluetoothAction(Context context, ListView unbondDevices,

ListView bondDevices, Button switchBT, Button searchDevices,

Activity activity) {

super();

this.context = context;

this.unbondDevices = unbondDevices;

this.bondDevices = bondDevices;

this.switchBT = switchBT;

this.searchDevices = searchDevices;

this.activity = activity;

this.bluetoothService = new BluetoothService(this.context,

this.unbondDevices, this.bondDevices, this.switchBT,

this.searchDevices);

}

public void setSwitchBT(Button switchBT) {

this.switchBT = switchBT;

}

public void setSearchDevices(Button searchDevices) {

this.searchDevices = searchDevices;

}

public void setUnbondDevices(ListView unbondDevices) {

this.unbondDevices = unbondDevices;

}

/**

* 初始化界面

*/

public void initView() {

if (this.bluetoothService.isOpen()) {

System.out.println("蓝牙有开!");

switchBT.setText("关闭蓝牙");

}

if (!this.bluetoothService.isOpen()) {

System.out.println("蓝牙没开!");

this.searchDevices.setEnabled(false);

}

}

private void searchDevices() {

bluetoothService.searchDevices();

}

/**

* 各种按钮的监听

*/

@Override

public void onClick(View v) {

if (v.getId() == R.id.searchDevices) {

this.searchDevices();

} else if (v.getId() == R.id.return_Bluetooth_btn) {

activity.finish();

} else if (v.getId() == R.id.openBluetooth_tb) {

if (!this.bluetoothService.isOpen()) {

// 蓝牙关闭的情况

System.out.println("蓝牙关闭的情况");

this.bluetoothService.openBluetooth(activity);

} else {

// 蓝牙打开的情况

System.out.println("蓝牙打开的情况");

this.bluetoothService.closeBluetooth();

}

}

}

}</span>

这个类会把各种请求动作分门别类,交给BluetoothService.java来处理,看代码

[java] view
plaincopy

public class BluetoothService {

private Context context = null;

private BluetoothAdapter bluetoothAdapter = BluetoothAdapter

.getDefaultAdapter();

private ArrayList<BluetoothDevice> unbondDevices = null; // 用于存放未配对蓝牙设备

private ArrayList<BluetoothDevice> bondDevices = null;// 用于存放已配对蓝牙设备

private Button switchBT = null;

private Button searchDevices = null;

private ListView unbondDevicesListView = null;

private ListView bondDevicesListView = null;

/**

* 添加已绑定蓝牙设备到ListView

*/

private void addBondDevicesToListView() {

ArrayList<HashMap<String, Object>> data = new ArrayList<HashMap<String, Object>>();

int count = this.bondDevices.size();

System.out.println("已绑定设备数量:" + count);

for (int i = 0; i < count; i++) {

HashMap<String, Object> map = new HashMap<String, Object>();

map.put("deviceName", this.bondDevices.get(i).getName());

data.add(map);// 把item项的数据加到data中

}

String[] from = { "deviceName" };

int[] to = { R.id.device_name };

SimpleAdapter simpleAdapter = new SimpleAdapter(this.context, data,

R.layout.bonddevice_item, from, to);

// 把适配器装载到listView中

this.bondDevicesListView.setAdapter(simpleAdapter);

this.bondDevicesListView

.setOnItemClickListener(new OnItemClickListener() {

@Override

public void onItemClick(AdapterView<?> arg0, View arg1,

int arg2, long arg3) {

BluetoothDevice device = bondDevices.get(arg2);

Intent intent = new Intent();

intent.setClassName(context,

"com.lifeng.jdxt.view.PrintDataActivity");

intent.putExtra("deviceAddress", device.getAddress());

context.startActivity(intent);

}

});

}

/**

* 添加未绑定蓝牙设备到ListView

*/

private void addUnbondDevicesToListView() {

ArrayList<HashMap<String, Object>> data = new ArrayList<HashMap<String, Object>>();

int count = this.unbondDevices.size();

System.out.println("未绑定设备数量:" + count);

for (int i = 0; i < count; i++) {

HashMap<String, Object> map = new HashMap<String, Object>();

map.put("deviceName", this.unbondDevices.get(i).getName());

data.add(map);// 把item项的数据加到data中

}

String[] from = { "deviceName" };

int[] to = { R.id.device_name };

SimpleAdapter simpleAdapter = new SimpleAdapter(this.context, data,

R.layout.unbonddevice_item, from, to);

// 把适配器装载到listView中

this.unbondDevicesListView.setAdapter(simpleAdapter);

// 为每个item绑定监听,用于设备间的配对

this.unbondDevicesListView

.setOnItemClickListener(new OnItemClickListener() {

@Override

public void onItemClick(AdapterView<?> arg0, View arg1,

int arg2, long arg3) {

try {

Method createBondMethod = BluetoothDevice.class

.getMethod("createBond");

createBondMethod

.invoke(unbondDevices.get(arg2));

// 将绑定好的设备添加的已绑定list集合

bondDevices.add(unbondDevices.get(arg2));

// 将绑定好的设备从未绑定list集合中移除

unbondDevices.remove(arg2);

addBondDevicesToListView();

addUnbondDevicesToListView();

} catch (Exception e) {

Toast.makeText(context, "配对失败!", Toast.LENGTH_SHORT)

.show();

}

}

});

}

public BluetoothService(Context context, ListView unbondDevicesListView,

ListView bondDevicesListView, Button switchBT, Button searchDevices) {

this.context = context;

this.unbondDevicesListView = unbondDevicesListView;

this.bondDevicesListView = bondDevicesListView;

// this.bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

this.unbondDevices = new ArrayList<BluetoothDevice>();

this.bondDevices = new ArrayList<BluetoothDevice>();

this.switchBT = switchBT;

this.searchDevices = searchDevices;

this.initIntentFilter();

}

private void initIntentFilter() {

// 设置广播信息过滤

IntentFilter intentFilter = new IntentFilter();

intentFilter.addAction(BluetoothDevice.ACTION_FOUND);

intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);

intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);

intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);

// 注册广播接收器,接收并处理搜索结果

context.registerReceiver(receiver, intentFilter);

}

/**

* 打开蓝牙

*/

public void openBluetooth(Activity activity) {

Intent enableBtIntent = new Intent(

BluetoothAdapter.ACTION_REQUEST_ENABLE);

activity.startActivityForResult(enableBtIntent, 1);

}

/**

* 关闭蓝牙

*/

public void closeBluetooth() {

this.bluetoothAdapter.disable();

}

/**

* 判断蓝牙是否打开

*

* @return boolean

*/

public boolean isOpen() {

return this.bluetoothAdapter.isEnabled();

}

/**

* 搜索蓝牙设备

*/

public void searchDevices() {

this.bondDevices.clear();

this.unbondDevices.clear();

// 寻找蓝牙设备,android会将查找到的设备以广播形式发出去

this.bluetoothAdapter.startDiscovery();

}

/**

* 添加未绑定蓝牙设备到list集合

*

* @param device

*/

public void addUnbondDevices(BluetoothDevice device) {

System.out.println("未绑定设备名称:" + device.getName());

if (!this.unbondDevices.contains(device)) {

this.unbondDevices.add(device);

}

}

/**

* 添加已绑定蓝牙设备到list集合

*

* @param device

*/

public void addBandDevices(BluetoothDevice device) {

System.out.println("已绑定设备名称:" + device.getName());

if (!this.bondDevices.contains(device)) {

this.bondDevices.add(device);

}

}

/**

* 蓝牙广播接收器

*/

private BroadcastReceiver receiver = new BroadcastReceiver() {

ProgressDialog progressDialog = null;

@Override

public void onReceive(Context context, Intent intent) {

String action = intent.getAction();

if (BluetoothDevice.ACTION_FOUND.equals(action)) {

BluetoothDevice device = intent

.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

if (device.getBondState() == BluetoothDevice.BOND_BONDED) {

addBandDevices(device);

} else {

addUnbondDevices(device);

}

} else if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) {

progressDialog = ProgressDialog.show(context, "请稍等...",

"搜索蓝牙设备中...", true);

} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED

.equals(action)) {

System.out.println("设备搜索完毕");

progressDialog.dismiss();

addUnbondDevicesToListView();

addBondDevicesToListView();

// bluetoothAdapter.cancelDiscovery();

}

if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {

if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {

System.out.println("--------打开蓝牙-----------");

switchBT.setText("关闭蓝牙");

searchDevices.setEnabled(true);

bondDevicesListView.setEnabled(true);

unbondDevicesListView.setEnabled(true);

} else if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF) {

System.out.println("--------关闭蓝牙-----------");

switchBT.setText("打开蓝牙");

searchDevices.setEnabled(false);

bondDevicesListView.setEnabled(false);

unbondDevicesListView.setEnabled(false);

}

}

}

};

}

到这里,第一个界面的代码就写完了,当我们点击要打印的蓝牙设备时就会跳转到打印页面,跳转代码在BluetoothService.java的addBondDevicesToListView()中

接下来让我们来看看第二个界面的代码,结构和第一个界面的代码一样,分类三个类,请看代码。。。。。

PrintDataActivity.java

[java] view
plaincopy

public class PrintDataActivity extends Activity {

private Context context = null;

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

this.setTitle("蓝牙打印");

this.setContentView(R.layout.printdata_layout);

this.context = this;

this.initListener();

}

/**

* 获得从上一个Activity传来的蓝牙地址

* @return String

*/

private String getDeviceAddress() {

// 直接通过Context类的getIntent()即可获取Intent

Intent intent = this.getIntent();

// 判断

if (intent != null) {

return intent.getStringExtra("deviceAddress");

} else {

return null;

}

}

private void initListener() {

TextView deviceName = (TextView) this.findViewById(R.id.device_name);

TextView connectState = (TextView) this

.findViewById(R.id.connect_state);

PrintDataAction printDataAction = new PrintDataAction(this.context,

this.getDeviceAddress(), deviceName, connectState);

EditText printData = (EditText) this.findViewById(R.id.print_data);

Button send = (Button) this.findViewById(R.id.send);

Button command = (Button) this.findViewById(R.id.command);

printDataAction.setPrintData(printData);

send.setOnClickListener(printDataAction);

command.setOnClickListener(printDataAction);

}

@Override

protected void onDestroy() {

PrintDataService.disconnect();

super.onDestroy();

}

}

PrintDataAction.java

[java] view
plaincopy

<span style="font-size:14px">public class PrintDataAction implements OnClickListener {

private Context context = null;

private TextView deviceName = null;

private TextView connectState = null;

private EditText printData = null;

private String deviceAddress = null;

private PrintDataService printDataService = null;

public PrintDataAction(Context context, String deviceAddress,

TextView deviceName, TextView connectState) {

super();

this.context = context;

this.deviceAddress = deviceAddress;

this.deviceName = deviceName;

this.connectState = connectState;

this.printDataService = new PrintDataService(this.context,

this.deviceAddress);

this.initView();

}

private void initView() {

// 设置当前设备名称

this.deviceName.setText(this.printDataService.getDeviceName());

// 一上来就先连接蓝牙设备

boolean flag = this.printDataService.connect();

if (flag == false) {

// 连接失败

this.connectState.setText("连接失败!");

} else {

// 连接成功

this.connectState.setText("连接成功!");

}

}

public void setPrintData(EditText printData) {

this.printData = printData;

}

@Override

public void onClick(View v) {

if (v.getId() == R.id.send) {

String sendData = this.printData.getText().toString();

this.printDataService.send(sendData + "\n");

} else if (v.getId() == R.id.command) {

this.printDataService.selectCommand();

}

}

}</span>

PrintDataService.java

[java] view
plaincopy

<span style="font-size:14px">public class PrintDataService {

private Context context = null;

private String deviceAddress = null;

private BluetoothAdapter bluetoothAdapter = BluetoothAdapter

.getDefaultAdapter();

private BluetoothDevice device = null;

private static BluetoothSocket bluetoothSocket = null;

private static OutputStream outputStream = null;

private static final UUID uuid = UUID

.fromString("00001101-0000-1000-8000-00805F9B34FB");

private boolean isConnection = false;

final String[] items = { "复位打印机", "标准ASCII字体", "压缩ASCII字体", "字体不放大",

"宽高加倍", "取消加粗模式", "选择加粗模式", "取消倒置打印", "选择倒置打印", "取消黑白反显", "选择黑白反显",

"取消顺时针旋转90°", "选择顺时针旋转90°" };

final byte[][] byteCommands = { { 0x1b, 0x40 },// 复位打印机

{ 0x1b, 0x4d, 0x00 },// 标准ASCII字体

{ 0x1b, 0x4d, 0x01 },// 压缩ASCII字体

{ 0x1d, 0x21, 0x00 },// 字体不放大

{ 0x1d, 0x21, 0x11 },// 宽高加倍

{ 0x1b, 0x45, 0x00 },// 取消加粗模式

{ 0x1b, 0x45, 0x01 },// 选择加粗模式

{ 0x1b, 0x7b, 0x00 },// 取消倒置打印

{ 0x1b, 0x7b, 0x01 },// 选择倒置打印

{ 0x1d, 0x42, 0x00 },// 取消黑白反显

{ 0x1d, 0x42, 0x01 },// 选择黑白反显

{ 0x1b, 0x56, 0x00 },// 取消顺时针旋转90°

{ 0x1b, 0x56, 0x01 },// 选择顺时针旋转90°

};

public PrintDataService(Context context, String deviceAddress) {

super();

this.context = context;

this.deviceAddress = deviceAddress;

this.device = this.bluetoothAdapter.getRemoteDevice(this.deviceAddress);

}

/**

* 获取设备名称

*

* @return String

*/

public String getDeviceName() {

return this.device.getName();

}

/**

* 连接蓝牙设备

*/

public boolean connect() {

if (!this.isConnection) {

try {

bluetoothSocket = this.device

.createRfcommSocketToServiceRecord(uuid);

bluetoothSocket.connect();

outputStream = bluetoothSocket.getOutputStream();

this.isConnection = true;

if (this.bluetoothAdapter.isDiscovering()) {

System.out.println("关闭适配器!");

this.bluetoothAdapter.isDiscovering();

}

} catch (Exception e) {

Toast.makeText(this.context, "连接失败!", 1).show();

return false;

}

Toast.makeText(this.context, this.device.getName() + "连接成功!",

Toast.LENGTH_SHORT).show();

return true;

} else {

return true;

}

}

/**

* 断开蓝牙设备连接

*/

public static void disconnect() {

System.out.println("断开蓝牙设备连接");

try {

bluetoothSocket.close();

outputStream.close();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

/**

* 选择指令

*/

public void selectCommand() {

new AlertDialog.Builder(context).setTitle("请选择指令")

.setItems(items, new DialogInterface.OnClickListener() {

@Override

public void onClick(DialogInterface dialog, int which) {

try {

outputStream.write(byteCommands[which]);

} catch (IOException e) {

Toast.makeText(context, "设置指令失败!",

Toast.LENGTH_SHORT).show();

}

}

}).create().show();

}

/**

* 发送数据

*/

public void send(String sendData) {

if (this.isConnection) {

System.out.println("开始打印!!");

try {

byte[] data = sendData.getBytes("gbk");

outputStream.write(data, 0, data.length);

outputStream.flush();

} catch (IOException e) {

Toast.makeText(this.context, "发送失败!", Toast.LENGTH_SHORT)

.show();

}

} else {

Toast.makeText(this.context, "设备未连接,请重新连接!", Toast.LENGTH_SHORT)

.show();

}

}

}</span>








到此,全部代码贴完,也就大功告成了








对了对了,差点忘记一件很重要的事情!!清单文件忘记给权限啦!!

权限

[html] view
plaincopy

<span style="font-size:14px"><uses-permission android:name="android.permission.BLUETOOTH" />

<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> </span>

注册Activity

[html] view
plaincopy

<span style="font-size:14px"><activity android:name=".BluetoothActivity" />

<activity android:name=".PrintDataActivity" /> </span><span style="font-size:14px">
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: