gpt4 book ai didi

Android 打印到任何蓝牙打印机

转载 作者:行者123 更新时间:2023-11-30 00:35:39 25 4
gpt4 key购买 nike

我已经为 android 开发了一个应用程序,可以通过蓝牙连接到 zebra 打印机,它工作正常。这要归功于 Zebra 提供的库。

我的问题是,如果我想使用另一种类型的打印机,那将迫使我重新编程并使用另一个库。

有什么方法可以打印到任何蓝牙打印机吗?无需针对每种特定类型的品牌进行编程?

最佳答案

这是一个 github link它提供了一个简单的安卓蓝牙打印库,适用于任何蓝牙打印机。它可以很容易地集成到您的项目中。我对其进行了一些调整,这样就不必在每次打印时都选择蓝牙设备。

我用它为这个 video 中显示的应用程序提供打印功能.基本上有三个重要的类。

public class PrinterCommands {
public static final byte HT = 0x9;
public static final byte LF = 0x0A;
public static final byte CR = 0x0D;
public static final byte ESC = 0x1B;
public static final byte DLE = 0x10;
public static final byte GS = 0x1D;
public static final byte FS = 0x1C;
public static final byte STX = 0x02;
public static final byte US = 0x1F;
public static final byte CAN = 0x18;
public static final byte CLR = 0x0C;
public static final byte EOT = 0x04;

public static final byte[] INIT = {27, 64};
public static byte[] FEED_LINE = {10};

public static byte[] SELECT_FONT_A = {20, 33, 0};

public static byte[] SET_BAR_CODE_HEIGHT = {29, 104, 100};
public static byte[] PRINT_BAR_CODE_1 = {29, 107, 2};
public static byte[] SEND_NULL_BYTE = {0x00};

public static byte[] SELECT_PRINT_SHEET = {0x1B, 0x63, 0x30, 0x02};
public static byte[] FEED_PAPER_AND_CUT = {0x1D, 0x56, 66, 0x00};

public static byte[] SELECT_CYRILLIC_CHARACTER_CODE_TABLE = {0x1B, 0x74, 0x11};

public static byte[] SELECT_BIT_IMAGE_MODE = {0x1B, 0x2A, 33, -128, 0};
public static byte[] SET_LINE_SPACING_24 = {0x1B, 0x33, 24};
public static byte[] SET_LINE_SPACING_30 = {0x1B, 0x33, 30};

public static byte[] TRANSMIT_DLE_PRINTER_STATUS = {0x10, 0x04, 0x01};
public static byte[] TRANSMIT_DLE_OFFLINE_PRINTER_STATUS = {0x10, 0x04, 0x02};
public static byte[] TRANSMIT_DLE_ERROR_STATUS = {0x10, 0x04, 0x03};
public static byte[] TRANSMIT_DLE_ROLL_PAPER_SENSOR_STATUS = {0x10, 0x04, 0x04};

public static final byte[] ESC_FONT_COLOR_DEFAULT = new byte[] { 0x1B, 'r',0x00 };
public static final byte[] FS_FONT_ALIGN = new byte[] { 0x1C, 0x21, 1, 0x1B,
0x21, 1 };
public static final byte[] ESC_ALIGN_LEFT = new byte[] { 0x1b, 'a', 0x00 };
public static final byte[] ESC_ALIGN_RIGHT = new byte[] { 0x1b, 'a', 0x02 };
public static final byte[] ESC_ALIGN_CENTER = new byte[] { 0x1b, 'a', 0x01 };
public static final byte[] ESC_CANCEL_BOLD = new byte[] { 0x1B, 0x45, 0 };


/*********************************************/
public static final byte[] ESC_HORIZONTAL_CENTERS = new byte[] { 0x1B, 0x44, 20, 28, 00};
public static final byte[] ESC_CANCLE_HORIZONTAL_CENTERS = new byte[] { 0x1B, 0x44, 00 };
/*********************************************/

public static final byte[] ESC_ENTER = new byte[] { 0x1B, 0x4A, 0x40 };
public static final byte[] PRINTE_TEST = new byte[] { 0x1D, 0x28, 0x41 };

下面显示的另一个类可帮助您从已配对的蓝牙设备列表中选择打印机。

public class DeviceListActivity extends Activity {
protected static final String TAG = "TAG";
private BluetoothAdapter mBluetoothAdapter;
private ArrayAdapter<String> mPairedDevicesArrayAdapter;
private static PrinterSelectedListener printerSelectedListener;

@Override
protected void onCreate(Bundle mSavedInstanceState) {
super.onCreate(mSavedInstanceState);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.devices_list);

newConnection();
}

public static void setPrinterSelectedListener(PrinterSelectedListener printerSelectedListener_) {
printerSelectedListener = printerSelectedListener_;
}

private void newConnection() {
try {
setResult(Activity.RESULT_CANCELED);
mPairedDevicesArrayAdapter = new ArrayAdapter<String>(this, R.layout.device_name);

ListView mPairedListView = findViewById(R.id.paired_devices);

mPairedListView.setAdapter(mPairedDevicesArrayAdapter);
mPairedListView.setOnItemClickListener(mDeviceClickListener);

mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> mPairedDevices = mBluetoothAdapter.getBondedDevices();

if (mPairedDevices.size() > 0) {
findViewById(R.id.title_paired_devices).setVisibility(View.VISIBLE);
for (BluetoothDevice mDevice : mPairedDevices) {
mPairedDevicesArrayAdapter.add(mDevice.getName() + "\n" + mDevice.getAddress());
}
} else {
String mNoDevices = "None Paired";//getResources().getText(R.string.none_paired).toString();
mPairedDevicesArrayAdapter.add(mNoDevices);
}
}catch(Exception ex){
Log.e("exception", ex.toString());
}
}

@Override
protected void onDestroy() {
super.onDestroy();
if (mBluetoothAdapter != null) {
mBluetoothAdapter.cancelDiscovery();
}
}

private OnItemClickListener mDeviceClickListener = new OnItemClickListener() {
public void onItemClick(AdapterView<?> mAdapterView, View mView, int mPosition, long mLong) {

try {


mBluetoothAdapter.cancelDiscovery();
String mDeviceInfo = ((TextView) mView).getText().toString();
String mDeviceAddress = mDeviceInfo.substring(mDeviceInfo.length() - 17);
String mDeviceName = mDeviceInfo.substring(0, mDeviceInfo.length()- 17);


Bundle mBundle = new Bundle();
mBundle.putString("DeviceAddress", mDeviceAddress);

//save this printer address in sharedpreference
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
SharedPreferences.Editor editor = pref.edit();
editor.putString("bluetooth_printer", mDeviceAddress); //
editor.putString("bluetooth_name", mDeviceName);
editor.apply();

//respond to listerner
if(printerSelectedListener != null)
{
printerSelectedListener.onPrinterSelected(mDeviceName);
}

Intent mBackIntent = new Intent();
mBackIntent.putExtras(mBundle);
setResult(Activity.RESULT_OK, mBackIntent);
finish();
}
catch (Exception ex)
{

}
}
};

第三个类是您应该扩展的类,以便 super 方法可以为您打印。该类如下所示。

public class MainActivity extends AppCompatActivity implements Runnable {
protected static final String TAG = "TAG";
protected static final int REQUEST_CONNECT_DEVICE = 1;
protected static final int REQUEST_ENABLE_BT = 2;
protected static final int BT_ON = 3;

protected BluetoothAdapter mBluetoothAdapter;
protected UUID applicationUUID = UUID
.fromString("00001101-0000-1000-8000-00805F9B34FB");
protected ProgressDialog mBluetoothConnectProgressDialog;
protected BluetoothSocket mBluetoothSocket;
protected BluetoothDevice mBluetoothDevice;
protected OutputStream outputStream;
public String BILL = "";
protected String printerName = "";
protected boolean isChangingName = false;
protected boolean isTestingPrinter = false;

@Override
protected void onCreate(Bundle mSavedInstanceState) {
super.onCreate(mSavedInstanceState);
setContentView(R.layout.activity_printer);


}// onCreate

public void doPrint(final String job) {
String name = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()).getString("bluetooth_printer", "");
printerName = name;
this.BILL = job;
this.mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

if (name.equalsIgnoreCase(""))
{

if (this.mBluetoothAdapter == null)
{
Toast.makeText(getApplicationContext(), "Your Bluetooth adapter has issues", Toast.LENGTH_LONG).show();
return;
} else if (!this.mBluetoothAdapter.isEnabled())
{
//put on the bluetooth
Intent enableBtIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent,
REQUEST_ENABLE_BT);
return;
} else
{
introduceNewDevice();
return;
}
}else
{
Intent enableBtIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent,
BT_ON);
return;
}


}

protected void printingProcess(final String BILL, String name) {
this.mBluetoothDevice = this.mBluetoothAdapter.getRemoteDevice(name);

try {
this.mBluetoothSocket = this.mBluetoothDevice.createRfcommSocketToServiceRecord(this.applicationUUID);
this.mBluetoothSocket.connect();
} catch (IOException eConnectException) {
Toast.makeText(MainActivity.this, "The printer is not available. Check if it is on", Toast.LENGTH_SHORT).show();

}

new Thread() {
public void run() {
try { //outputStream
outputStream = mBluetoothSocket.getOutputStream();


if(isTestingPrinter){
//invoice details
printConfig(BILL, 2, 1,1);//align 1=center
printNewLine();
}
closeSocket(mBluetoothSocket); //close the connection

} catch (Exception e) {
Log.e("MainActivity", "Exe ", e);
}
}
}.start();
}

protected void printConfig(String bill, int size, int style, int align)
{
//size 1 = large, size 2 = medium, size 3 = small
//style 1 = Regular, style 2 = Bold
//align 0 = left, align 1 = center, align 2 = right

try{

byte[] format = new byte[]{27,33, 0};
byte[] change = new byte[]{27,33, 0};

outputStream.write(format);

//different sizes, same style Regular
if (size==1 && style==1) //large
{
change[2] = (byte) (0x10); //large
outputStream.write(change);
}else if(size==2 && style==1) //medium
{
//nothing to change, uses the default settings
}else if(size==3 && style==1) //small
{
change[2] = (byte) (0x3); //small
outputStream.write(change);
}

//different sizes, same style Bold
if (size==1 && style==2) //large
{
change[2] = (byte) (0x10 | 0x8); //large
outputStream.write(change);
}else if(size==2 && style==2) //medium
{
change[2] = (byte) (0x8);
outputStream.write(change);
}else if(size==3 && style==2) //small
{
change[2] = (byte) (0x3 | 0x8); //small
outputStream.write(change);
}


switch (align) {
case 0:
//left align
outputStream.write(PrinterCommands.ESC_ALIGN_LEFT);
break;
case 1:
//center align
outputStream.write(PrinterCommands.ESC_ALIGN_CENTER);
break;
case 2:
//right align
outputStream.write(PrinterCommands.ESC_ALIGN_RIGHT);
break;
}
outputStream.write(bill.getBytes());
outputStream.write(PrinterCommands.LF);
}catch(Exception ex){
Log.e("error", ex.toString());
}
}


@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
try {
if (mBluetoothSocket != null)
mBluetoothSocket.close();
} catch (Exception e) {
Log.e("Tag", "Exe ", e);
}
}

@Override
public void onBackPressed() {
try {
if (mBluetoothSocket != null)
mBluetoothSocket.close();
} catch (Exception e) {
Log.e("Tag", "Exe ", e);
}
setResult(RESULT_CANCELED);
finish();
}

public void onActivityResult(int mRequestCode, int mResultCode,
Intent mDataIntent) {
super.onActivityResult(mRequestCode, mResultCode, mDataIntent);

try {
switch (mRequestCode) {
case REQUEST_CONNECT_DEVICE:
if (mResultCode == Activity.RESULT_OK) {
Bundle mExtra = mDataIntent.getExtras();
String mDeviceAddress = mExtra.getString("DeviceAddress");
Log.e(TAG, "Coming incoming address " + mDeviceAddress);
mBluetoothDevice = mBluetoothAdapter
.getRemoteDevice(mDeviceAddress);

mBluetoothConnectProgressDialog = ProgressDialog.show(this,
"Connecting...", mBluetoothDevice.getName() + " : "
+ mBluetoothDevice.getAddress(), true, false);

mBluetoothAdapter.cancelDiscovery();
mHandler.sendEmptyMessage(0);

//don't print if we are just changing name
if (!isChangingName)
printingProcess(BILL, mDeviceAddress);
else {
Toast.makeText(MainActivity.this, "Printer selected successfully!", Toast.LENGTH_SHORT).show();

}
}
break;

case REQUEST_ENABLE_BT:
if (mResultCode == Activity.RESULT_OK) {
introduceNewDevice();
} else {
Toast.makeText(MainActivity.this, "Request denied", Toast.LENGTH_SHORT).show();
}
break; //BT_ON
case BT_ON:
if (mResultCode == Activity.RESULT_OK) {
if (isChangingName) {
introduceNewDevice();
} else {
printingProcess(BILL, printerName);
}
} else {
Toast.makeText(MainActivity.this, "Request denied", Toast.LENGTH_SHORT).show();
}
break;
}
}catch(Exception ex){
Log.e(TAG, ex.toString());
}
}



protected void introduceNewDevice() {
ListPairedDevices();
Intent connectIntent = new Intent(MainActivity.this,
DeviceListActivity.class);
startActivityForResult(connectIntent, REQUEST_CONNECT_DEVICE);
}

protected void ListPairedDevices() {
try {
Set<BluetoothDevice> mPairedDevices = mBluetoothAdapter
.getBondedDevices();
if (mPairedDevices.size() > 0) {
for (BluetoothDevice mDevice : mPairedDevices) {
Log.e(TAG, "PairedDevices: " + mDevice.getName() + " "
+ mDevice.getAddress());
}
}
}catch(Exception ex){
Log.e(TAG, ex.toString());
}
}


public void run() {
try {
mBluetoothSocket = mBluetoothDevice
.createRfcommSocketToServiceRecord(applicationUUID);
mBluetoothAdapter.cancelDiscovery();
mBluetoothSocket.connect();
mHandler.sendEmptyMessage(0);
Log.e("main run","inside the main run");
} catch (IOException eConnectException) {
Log.d(TAG, "CouldNotConnectToSocket", eConnectException);
closeSocket(mBluetoothSocket);
return;
}
}

protected void closeSocket(BluetoothSocket nOpenSocket) {
try {
nOpenSocket.close();
Log.d(TAG, "SocketClosed");
} catch (IOException ex) {
Log.d(TAG, "CouldNotCloseSocket");
}
}

protected Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
mBluetoothConnectProgressDialog.dismiss();
// Toast.makeText(MainActivity.this, "Device Connected", Toast.LENGTH_SHORT).show();
}
};

public static byte intToByteArray(int value) {
byte[] b = ByteBuffer.allocate(4).putInt(value).array();

for (int k = 0; k < b.length; k++) {
System.out.println("Selva [" + k + "] = " + "0x"
+ UnicodeFormatter.byteToHex(b[k]));
}

return b[3];
}

public byte[] sel(int val) {
ByteBuffer buffer = ByteBuffer.allocate(2);
buffer.putInt(val);
buffer.flip();
return buffer.array();
}

//print photo
public void printPhoto(int img) {
try {
Bitmap bmp = BitmapFactory.decodeResource(getResources(),
img);
if(bmp!=null){
byte[] command = Utils.decodeBitmap(bmp);
outputStream.write(PrinterCommands.ESC_ALIGN_CENTER);
printText(command);
}else{
Log.e("Print Photo error", "the file isn't exists");
}
} catch (Exception e) {
e.printStackTrace();
Log.e("PrintTools", "the file isn't exists");
}
}

//print unicode
public void printUnicode(){
try {
outputStream.write(PrinterCommands.ESC_ALIGN_CENTER);
printText(Utils.UNICODE_TEXT);
} catch (UnsupportedEncodingException e) {
Log.e("printUnicodeProblem", e.toString());
} catch (IOException e) {
e.printStackTrace();
}
}


//print new line
protected void printNewLine() {
try {
outputStream.write(PrinterCommands.FEED_LINE);
} catch (IOException e) {
e.printStackTrace();
}
}

public void resetPrint() {
try{
outputStream.write(PrinterCommands.ESC_FONT_COLOR_DEFAULT);
outputStream.write(PrinterCommands.FS_FONT_ALIGN);
outputStream.write(PrinterCommands.ESC_ALIGN_LEFT);
outputStream.write(PrinterCommands.ESC_CANCEL_BOLD);
outputStream.write(PrinterCommands.LF);
} catch (IOException e) {
e.printStackTrace();
}
}

//print text
protected void printText(String msg) {
try {
// Print normal text
outputStream.write(msg.getBytes());
} catch (IOException e) {
e.printStackTrace();
}

}

//print byte[]
protected void printText(byte[] msg) {
try {
// Print normal text
outputStream.write(msg);
// printNewLine();
} catch (IOException e) {
Log.e("printTextError",e.toString());
}
}


protected String leftRightAlign(String str1, String str2) {
String ans = str1 +str2;
if(ans.length() <31){
int n = (31 - str1.length() + str2.length());
ans = str1 + new String(new char[n]).replace("\0", " ") + str2;
}
return ans;
}

上面类中的布局 activity_printer.xml 应更改为您的布局。但是,您需要包含此 devices_list.xml 文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/title_paired_devices"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#666"
android:paddingLeft="5dip"
android:text="Bluetooth Devices"
android:textColor="#fff"
android:visibility="gone" />

<ListView
android:id="@+id/paired_devices"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#fff"
android:layout_weight="1"
android:stackFromBottom="true" />
</LinearLayout>

要打印,只需将字符串传递给方法

doPrint("your strings that needs to be printed");

我做了一些补充,这样您就可以在选择打印机后得到回电。界面如下图。您必须在您希望用户选择打印机并对其进行测试的 Activity 中实现该接口(interface)

public interface PrinterSelectedListener {

void onPrinterSelected(String name); }

要选择一台打印机并在单独的 Activity 中对其进行测试,您的 Activity 必须扩展 MainActivity 并实现 PrinterSelectedListener。要选择新打印机或更改打印机,请调用此

isChangingName = true;
doPrint("");

要测试打印机,调用这个

                isChangingName = false;
isTestingPrinter = true;
String test = "This is a test printer page" + "\n";
doPrint(test);

关于Android 打印到任何蓝牙打印机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43462836/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com