养乐多滋滋滋 2026-01-14 09:05 采纳率: 76%
浏览 6

安卓连接打印机,正常出纸,但是纸上没有内容

今天写了份代码,通过使用斑马手持机(TC26)蓝牙的方式连接打印(TSC-30B)出现的问题如下:
通过手持机的前段界面,点击打印,打印机正常出纸,但是纸上没有测试内容,但是控制台提示ok,以下截图

img

img


这个是厂家给的打印机指令:

img

img

以下是核心代码:
MainActivity

package com.jl.bluetoothprinter_two;

import android.Manifest;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainActivity extends AppCompatActivity {
    // 基础常量
    private static final String TAG = "TSC-Printer-API28";
    private static final int REQUEST_PERMISSIONS = 100;
    private static final int REQUEST_ENABLE_BT = 101;
    private static final UUID PRINTER_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
    // 打印配置(可统一修改)
    private static final String LABEL_WIDTH = "60";    // 标签宽度(mm)
    private static final String LABEL_HEIGHT = "40";   // 标签高度(mm)
    private static final int PRINT_DENSITY = 30;       // 打印浓度(0-30,默认10)
    private static final Charset PRINT_CHARSET = Charset.forName("GBK"); // 打印编码

    // 蓝牙核心组件
    private BluetoothAdapter bluetoothAdapter;
    private BluetoothSocket bluetoothSocket;
    private OutputStream outputStream;

    // UI组件
    private TextView connectionStatus;
    private ListView deviceListView;
    private Button searchBtn;          // 搜索按钮
    private Button printBtn;           // 打印按钮
    private Button disconnectBtn;      // 新增:断开连接按钮

    // 设备列表
    private ArrayList<String> deviceList = new ArrayList<>();
    private ArrayList<String> deviceAddresses = new ArrayList<>();
    private ArrayAdapter<String> deviceAdapter;

    // 线程池(替代裸线程,更稳定)
    private ExecutorService executor = Executors.newSingleThreadExecutor();
    private Handler mainHandler = new Handler(Looper.getMainLooper());

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "=== 应用启动 ===");
        setContentView(R.layout.activity_main);

        initViews();
        initBluetoothAdapter();
        registerBluetoothReceiver();
    }

    // 初始化UI(新增断开连接按钮)
    private void initViews() {
        Log.d(TAG, "初始化UI组件");
        connectionStatus = findViewById(R.id.connection_status);
        deviceListView = findViewById(R.id.device_list);
        searchBtn = findViewById(R.id.search_button);
        printBtn = findViewById(R.id.print_button);
        // 新增:绑定断开连接按钮(需在layout中添加id为disconnect_button的Button)
        disconnectBtn = findViewById(R.id.disconnect_button);

        // 初始化列表适配器
        deviceAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, deviceList);
        deviceListView.setAdapter(deviceAdapter);

        // 搜索按钮:点击时禁用,避免重复触发
        searchBtn.setOnClickListener(v -> {
            if (!searchBtn.isEnabled()) return;
            Log.d(TAG, "搜索按钮被点击");
            searchBtn.setEnabled(false);
            clearDeviceList();
            checkPermissionsAndSearch();
        });

        // 设备列表点击:连接打印机(增加加载状态)
        deviceListView.setOnItemClickListener((parent, view, position, id) -> {
            String address = deviceAddresses.get(position);
            String name = deviceList.get(position).split("\n")[0];
            Log.d(TAG, "选中设备: " + name + ",地址: " + address);

            // 禁用UI,避免重复点击
            printBtn.setEnabled(false);
            disconnectBtn.setEnabled(false);
            searchBtn.setEnabled(false);
            updateStatus("正在连接: " + name, false);

            connectToPrinter(address, name);
        });

        // 打印按钮:增加状态校验
        printBtn.setOnClickListener(v -> {
            if (!printBtn.isEnabled()) return;
            Log.d(TAG, "打印按钮被点击");
            if (isConnected()) {
                printBtn.setEnabled(false);
                printTestPage();
            } else {
                showToast("请先连接打印机");
                Log.w(TAG, "打印失败:未连接设备");
            }
        });

        // 新增:断开连接按钮点击事件
        disconnectBtn.setOnClickListener(v -> {
            if (!disconnectBtn.isEnabled()) return;
            Log.d(TAG, "断开连接按钮被点击");
            disconnectFromPrinter();
        });

        // 初始状态:打印按钮、断开连接按钮禁用
        printBtn.setEnabled(false);
        disconnectBtn.setEnabled(false);
    }

    // 初始化蓝牙适配器(增加状态日志)
    private void initBluetoothAdapter() {
        Log.d(TAG, "初始化蓝牙适配器");
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        if (bluetoothAdapter == null) {
            Log.e(TAG, "设备不支持蓝牙");
            showToast("设备不支持蓝牙");
            finish();
        } else {
            Log.d(TAG, "蓝牙适配器初始化成功,状态:" + (bluetoothAdapter.isEnabled() ? "已开启" : "未开启"));
            updateStatus("蓝牙已就绪(未连接设备)", false);
        }
    }

    // 注册蓝牙广播接收器(增加权限校验)
    private void registerBluetoothReceiver() {
        Log.d(TAG, "注册蓝牙广播接收器");
        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        registerReceiver(bluetoothReceiver, filter);

        filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        registerReceiver(bluetoothReceiver, filter);
    }

    // 蓝牙广播接收器(优化重复判断,增加搜索完成后恢复UI)
    private final BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
        @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 != null && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED) {
                    String name = device.getName() != null ? device.getName() : "未知设备";
                    String address = device.getAddress();

                    if (!deviceAddresses.contains(address)) {
                        deviceList.add(name + "\n" + address);
                        deviceAddresses.add(address);
                        deviceAdapter.notifyDataSetChanged();
                        Log.d(TAG, "发现设备: " + name + " (" + address + ")");
                    }
                }
            } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
                Log.d(TAG, "搜索完成,共发现" + deviceList.size() + "个设备");
                // 恢复搜索按钮
                searchBtn.setEnabled(true);
                if (deviceList.isEmpty()) {
                    showToast("未发现蓝牙设备");
                    updateStatus("搜索完成:无设备", false);
                } else {
                    showToast("找到" + deviceList.size() + "个设备");
                    updateStatus("搜索完成:可选择设备连接", false);
                }
            }
        }
    };

    // 检查权限(补充Bluetooth权限,Android 9部分机型需要)
    private void checkPermissionsAndSearch() {
        Log.d(TAG, "检查Android 9所需权限");
        String[] requiredPermissions = {
                Manifest.permission.ACCESS_FINE_LOCATION,
                Manifest.permission.BLUETOOTH,
                Manifest.permission.BLUETOOTH_ADMIN
        };

        ArrayList<String> needPermissions = new ArrayList<>();
        for (String perm : requiredPermissions) {
            if (ContextCompat.checkSelfPermission(this, perm) != PackageManager.PERMISSION_GRANTED) {
                needPermissions.add(perm);
                Log.d(TAG, "缺少权限: " + perm);
            }
        }

        if (needPermissions.isEmpty()) {
            startBluetoothSearch();
        } else {
            ActivityCompat.requestPermissions(this, needPermissions.toArray(new String[0]), REQUEST_PERMISSIONS);
        }
    }

    // 开始搜索(增加状态提示)
    private void startBluetoothSearch() {
        Log.d(TAG, "开始搜索蓝牙设备");
        if (!bluetoothAdapter.isEnabled()) {
            Log.d(TAG, "蓝牙未开启,请求开启");
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
            return;
        }

        if (bluetoothAdapter.isDiscovering()) {
            bluetoothAdapter.cancelDiscovery();
            Log.d(TAG, "取消正在进行的搜索");
        }

        // 加载已配对设备
        loadPairedDevices();

        // 开始搜索
        updateStatus("正在搜索蓝牙设备...", false);
        boolean isSearching = bluetoothAdapter.startDiscovery();
        if (isSearching) {
            showToast("正在搜索设备...");
            Log.d(TAG, "搜索启动成功");
        } else {
            showToast("搜索失败,请重试");
            Log.e(TAG, "搜索启动失败");
            searchBtn.setEnabled(true); // 恢复按钮
        }
    }

    // 加载已配对设备(补充权限校验)
    private void loadPairedDevices() {
        Log.d(TAG, "加载已配对设备");
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
        if (pairedDevices.size() > 0) {
            for (BluetoothDevice device : pairedDevices) {
                String name = device.getName() != null ? device.getName() : "未知设备";
                String address = device.getAddress();
                deviceList.add(name + "\n" + address + " (已配对)");
                deviceAddresses.add(address);
                Log.d(TAG, "已配对设备: " + name + " (" + address + ")");
            }
            deviceAdapter.notifyDataSetChanged();
        } else {
            Log.d(TAG, "无已配对设备");
        }
    }

    // 连接打印机(重构为线程池执行,增加异常兜底)
    private void connectToPrinter(String address, String name) {
        executor.execute(() -> {
            BluetoothDevice device = null;
            try {
                // 权限校验
                if (ActivityCompat.checkSelfPermission(this, Manifest.permission.BLUETOOTH) != PackageManager.PERMISSION_GRANTED) {
                    mainHandler.post(() -> {
                        showToast("缺少蓝牙权限,无法连接");
                        resetUiStatus();
                    });
                    return;
                }

                // 取消搜索
                if (bluetoothAdapter.isDiscovering()) {
                    bluetoothAdapter.cancelDiscovery();
                }

                // 获取远程设备
                device = bluetoothAdapter.getRemoteDevice(address);
                Log.d(TAG, "开始连接设备: " + device.getName() + " (" + address + ")");

                // 关闭旧连接
                closeConnection();

                // 创建Socket并连接(增加超时逻辑)
                bluetoothSocket = device.createRfcommSocketToServiceRecord(PRINTER_UUID);
                bluetoothSocket.connect(); // 底层默认超时约12秒
                outputStream = bluetoothSocket.getOutputStream();

                // 连接成功:更新UI(启用断开连接按钮)
                Log.d(TAG, "连接成功: " + name);
                mainHandler.post(() -> {
                    updateStatus("已连接: " + name, true);
                    showToast("连接成功:" + name);
                    printBtn.setEnabled(true);
                    disconnectBtn.setEnabled(true); // 启用断开连接按钮
                    searchBtn.setEnabled(true);
                });

            } catch (IOException e) {
                // 连接失败:详细日志+UI恢复
                Log.e(TAG, "连接失败: " + (device != null ? device.getName() : address) + ",原因:" + e.getMessage(), e);
                closeConnection(); // 确保关闭资源
                mainHandler.post(() -> {
                    updateStatus("连接失败: " + e.getMessage(), false);
                    showToast("连接失败:" + (e.getMessage() != null ? e.getMessage() : "未知错误"));
                    resetUiStatus(); // 恢复UI状态
                });
            }
        });
    }

    // 断开连接打印机
    private void disconnectFromPrinter() {
        executor.execute(() -> {
            Log.d(TAG, "开始断开蓝牙连接");
            try {
                // 关闭连接资源
                closeConnection();

                // 断开成功:更新UI
                mainHandler.post(() -> {
                    updateStatus("已断开连接", false);
                    showToast("已断开与打印机的连接");
                    // 禁用打印和断开按钮,启用搜索按钮
                    printBtn.setEnabled(false);
                    disconnectBtn.setEnabled(false);
                    searchBtn.setEnabled(true);
                });
                Log.d(TAG, "断开连接成功");

            } catch (Exception e) {
                // 断开失败:日志+UI提示
                Log.e(TAG, "断开连接失败: " + e.getMessage(), e);
                mainHandler.post(() -> {
                    showToast("断开连接失败:" + e.getMessage());
                });
            }
        });
    }

    // 打印测试页
    private void printTestPage() {
        executor.execute(() -> {
            if (outputStream == null) {
                mainHandler.post(() -> {
                    showToast("未连接打印机");
                    printBtn.setEnabled(true);
                });
                return;
            }

            try {
                // 1. 硬重置打印机
                outputStream.write(new byte[]{0x1B, 0x40});
                Thread.sleep(500);

                // 2. 初始化配置(只执行一次)
                String initCmd =
                        "SIZE " + LABEL_WIDTH + "mm," + LABEL_HEIGHT + "mm\n" +
                                "GAP 2mm,0mm\n" +
                                "SET DENSITY " + PRINT_DENSITY + "\n" +
                                "CLS\n";
                outputStream.write(initCmd.getBytes(PRINT_CHARSET));
                Thread.sleep(300);
                // 3. 构建打印内容
                StringBuilder cmd = new StringBuilder();
                cmd.append("TEXT 10,10,\"3\",0,2,2,\"您好世界您好世界您好世界您好世界您好世界\"\n");
                cmd.append("TEXT 10,50,\"3\",0,1,1,\"测试打印-TSC\"\n");
                cmd.append("PRINT 1,1\n");

                // 4. 添加结束符
                byte[] printCmd = cmd.toString().getBytes(PRINT_CHARSET);
                byte[] finalCmd = new byte[printCmd.length + 1];
                System.arraycopy(printCmd, 0, finalCmd, 0, printCmd.length);
                finalCmd[printCmd.length] = 0x0C;

                // 5. 发送完整指令
                outputStream.write(finalCmd);
                outputStream.flush();
                Thread.sleep(200);

                // 6. 成功反馈
                Log.d(TAG, "打印指令发送完成,指令:\n" + cmd.toString() + "[0x0C]");
                mainHandler.post(() -> {
                    showToast("打印成功!");
                    printBtn.setEnabled(true);
                });

            } catch (Exception e) {
                Log.e(TAG, "打印异常: " + e.getMessage(), e);
                mainHandler.post(() -> {
                    showToast("打印失败:" + (e.getMessage() != null ? e.getMessage() : "未知错误"));
                    printBtn.setEnabled(true);
                });
            }
        });
    }



    // 关闭连接(增加空指针保护)
    private void closeConnection() {
        Log.d(TAG, "关闭蓝牙连接");
        try {
            if (outputStream != null) {
                outputStream.close();
                outputStream = null;
            }
            if (bluetoothSocket != null) {
                bluetoothSocket.close();
                bluetoothSocket = null;
            }
        } catch (IOException e) {
            Log.e(TAG, "关闭连接失败: " + e.getMessage(), e);
        }
    }

    // 检查连接状态(更严谨)
    private boolean isConnected() {
        return bluetoothSocket != null && bluetoothSocket.isConnected() && outputStream != null;
    }

    // 更新状态(封装+主线程保障)
    private void updateStatus(String text, boolean isSuccess) {
        mainHandler.post(() -> {
            connectionStatus.setText(text);
            connectionStatus.setTextColor(isSuccess ?
                    getResources().getColor(android.R.color.holo_green_dark) :
                    getResources().getColor(android.R.color.holo_red_dark));
        });
    }

    // 显示Toast(封装)
    private void showToast(String msg) {
        mainHandler.post(() -> Toast.makeText(this, msg, Toast.LENGTH_SHORT).show());
    }

    // 清空设备列表(封装)
    private void clearDeviceList() {
        deviceList.clear();
        deviceAddresses.clear();
        deviceAdapter.notifyDataSetChanged();
    }

    // 恢复UI状态(统一管理,新增断开按钮状态)
    private void resetUiStatus() {
        printBtn.setEnabled(false);
        disconnectBtn.setEnabled(false); // 新增:禁用断开按钮
        searchBtn.setEnabled(true);
    }

    // 权限请求结果(优化提示)
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        Log.d(TAG, "权限请求结果,请求码: " + requestCode);

        if (requestCode == REQUEST_PERMISSIONS) {
            boolean allGranted = true;
            for (int result : grantResults) {
                if (result != PackageManager.PERMISSION_GRANTED) {
                    allGranted = false;
                    break;
                }
            }

            if (allGranted) {
                Log.d(TAG, "权限已授予,开始搜索");
                startBluetoothSearch();
            } else {
                Log.w(TAG, "权限被拒绝");
                new AlertDialog.Builder(this)
                        .setTitle("权限不足")
                        .setMessage("需要位置和蓝牙权限才能搜索/连接打印机,请在设置中开启")
                        .setPositiveButton("去设置", (dialog, which) -> {
                            Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                            intent.setData(Uri.fromParts("package", getPackageName(), null));
                            startActivity(intent);
                        })
                        .setNegativeButton("取消", null)
                        .show();
                searchBtn.setEnabled(true); // 恢复按钮
            }
        }
    }

    // 蓝牙开启结果(优化状态)
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Log.d(TAG, "onActivityResult: 请求码=" + requestCode + ", 结果码=" + resultCode);

        if (requestCode == REQUEST_ENABLE_BT) {
            if (resultCode == RESULT_OK) {
                Log.d(TAG, "蓝牙已开启,开始搜索");
                startBluetoothSearch();
            } else {
                Log.w(TAG, "用户拒绝开启蓝牙");
                showToast("请开启蓝牙后重试");
                updateStatus("蓝牙未开启", false);
                searchBtn.setEnabled(true); // 恢复按钮
            }
        }
    }

    // 生命周期:优化资源释放
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "应用销毁,清理资源");
        // 注销广播
        try {
            unregisterReceiver(bluetoothReceiver);
        } catch (IllegalArgumentException e) {
            Log.w(TAG, "广播接收器已注销,无需重复操作");
        }
        // 关闭连接
        closeConnection();
        // 关闭线程池
        executor.shutdown();
        // 移除Handler回调
        mainHandler.removeCallbacksAndMessages(null);
    }

    // 暂停时:优化蓝牙处理
    @Override
    protected void onPause() {
        super.onPause();
        if (bluetoothAdapter != null && bluetoothAdapter.isDiscovering()) {
            bluetoothAdapter.cancelDiscovery();
            Log.d(TAG, "暂停,停止搜索");
        }
        // 恢复按钮状态
        if (!isFinishing()) {
            searchBtn.setEnabled(true);
        }
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <!-- 蓝牙基础权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <!-- Android 12+ 蓝牙权限 -->
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <!-- 位置权限(低版本蓝牙扫描需要) -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <!-- 后台定位(可选,用于持续扫描) -->
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-feature
        android:name="android.hardware.bluetooth"
        android:required="true" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Bluetoothprinter_Two"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

activity_main.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"
    android:padding="20dp"
    android:background="#F8F9FA">

    <!-- 连接状态卡片(简单圆角+白色背景) -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#FFFFFF"
        android:padding="16dp"
        android:layout_marginBottom="20dp"
        android:orientation="vertical"
        android:elevation="2dp"
        android:radius="10dp">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="连接状态"
            android:textSize="14sp"
            android:textColor="#666666"
            android:layout_marginBottom="6dp"/>

        <TextView
            android:id="@+id/connection_status"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="蓝牙已就绪(未连接设备)"
            android:textSize="17sp"
            android:textColor="#333333"/>
    </LinearLayout>

    <!-- 按钮区域(圆角按钮+间距) -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <Button
            android:id="@+id/search_button"
            android:layout_width="0dp"
            android:layout_height="48dp"
            android:layout_weight="1"
            android:text="搜索"
            android:textSize="16sp"
            android:backgroundTint="#4A90E2"
            android:textColor="#FFFFFF"/>

        <Button
            android:id="@+id/print_button"
            android:layout_width="0dp"
            android:layout_height="48dp"
            android:layout_weight="1"
            android:text="打印"
            android:textSize="16sp"
            android:backgroundTint="#5CB85C"
            android:textColor="#FFFFFF"
            />

        <Button
            android:id="@+id/disconnect_button"
            android:layout_width="0dp"
            android:layout_height="48dp"
            android:layout_weight="1"
            android:text="断开"
            android:textSize="16sp"
            android:backgroundTint="#D9534F"
            android:textColor="#FFFFFF"
           />
    </LinearLayout>

    <!-- 设备列表(圆角+白色背景) -->
    <ListView
        android:id="@+id/device_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#FFFFFF"
        android:divider="#EEEEEE"
        android:dividerHeight="1dp"
        android:padding="8dp"
        android:elevation="2dp"
        android:radius="8dp"
        android:listSelector="#E8F4F8"/>

</LinearLayout>
  • 写回答

3条回答 默认 最新

  • 檀越@新空间 2026-01-14 09:06
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    你描述的问题是:安卓设备通过蓝牙连接打印机(如 TSC-30B)时,打印机正常出纸,但纸上没有内容。这表明 蓝牙连接已经建立,但是 打印内容未成功发送到打印机


    一、问题分析

    1. 可能原因总结

    • 打印指令格式错误:打印机不识别你的指令格式(例如 ZPL 或其他格式),导致打印内容无法解析。
    • 数据未正确写入输出流:虽然连接成功,但代码中未将正确的打印内容写入 OutputStream
    • 编码问题:使用了不兼容的字符集(如 GBK)或未正确设置编码。
    • 蓝牙权限问题:虽然已获取权限,但某些 Android 版本仍需额外处理。
    • 打印机配置不匹配:如标签尺寸、密度等参数不符合打印机实际规格。

    二、解决方案(详细步骤)

    第一步:确认打印指令是否正确

    根据你提供的代码片段,目前并没有看到任何打印指令的发送逻辑。你需要在点击打印按钮后发送正确的打印指令。

    修改后的打印按钮逻辑(核心代码)

    printBtn.setOnClickListener(v -> {
        if (bluetoothSocket == null || !bluetoothSocket.isConnected()) {
            Toast.makeText(MainActivity.this, "请先连接打印机", Toast.LENGTH_SHORT).show();
            return;
        }
    
        // 发送打印指令(以 ZPL 指令为例)
        String zplCommand = "^XA" +
                            "^FO50,50^A0N,20,20^FDHello World^FS" +
                            "^XZ";
    
        try {
            outputStream = bluetoothSocket.getOutputStream();
            outputStream.write(zplCommand.getBytes(PRINT_CHARSET));
            outputStream.flush();
            Log.d(TAG, "打印指令已发送: " + zplCommand);
            Toast.makeText(MainActivity.this, "打印指令发送成功", Toast.LENGTH_SHORT).show();
        } catch (IOException e) {
            Log.e(TAG, "发送打印指令失败: ", e);
            Toast.makeText(MainActivity.this, "打印失败,请重试", Toast.LENGTH_SHORT).show();
        }
    });
    

    重点说明:

    • 必须发送正确的打印语言指令(如 ZPL 或 EPL),否则打印机不会识别内容。
    • 如果你使用的是 TSC-30B 打印机,它支持 ZPL 指令。
    • 上面的示例是一个简单的 ZPL 指令,用于打印 "Hello World"。

    第二步:检查蓝牙连接状态和输出流

    确保在发送打印指令前,蓝牙连接已建立且输出流可用

    新增连接状态检测逻辑

    private void sendPrintCommand() {
        if (bluetoothSocket == null || !bluetoothSocket.isConnected()) {
            Log.e(TAG, "蓝牙连接未建立");
            return;
        }
    
        try {
            outputStream = bluetoothSocket.getOutputStream();
            // ... 发送指令
        } catch (IOException e) {
            Log.e(TAG, "获取输出流失败: ", e);
        }
    }
    

    第三步:确认打印指令格式和编码

    确保使用正确的编码(如 GBK)

    private static final Charset PRINT_CHARSET = Charset.forName("GBK"); // 打印编码
    

    注意: 某些打印机可能只支持 ASCIIUTF-8,如果使用 GBK 不行,可以尝试以下方式:

    // 尝试 UTF-8
    String zplCommand = "...";
    outputStream.write(zplCommand.getBytes("UTF-8"));
    

    第四步:检查打印机配置是否匹配

    确认标签尺寸、打印浓度等参数是否匹配

    private static final String LABEL_WIDTH = "60";    // 标签宽度(mm)
    private static final String LABEL_HEIGHT = "40";   // 标签高度(mm)
    private static final int PRINT_DENSITY = 30;       // 打印浓度(0-30,默认10)
    

    建议: 使用打印机自带的配置工具或说明书确认这些值。


    第五步:添加调试信息

    在关键位置添加日志,确保程序流程正确执行。

    Log.d(TAG, "蓝牙连接已建立");
    Log.d(TAG, "发送打印指令: " + zplCommand);
    

    三、完整修复建议(有序列表)

    1. 添加打印指令发送逻辑

      • 在打印按钮点击事件中发送正确的 ZPL 指令。
    2. 确保输出流可用

      • 在发送指令前检查 bluetoothSocket 是否已连接,并获取 OutputStream
    3. 验证打印指令格式

      • 使用标准的 ZPL 指令(如 ^XA 开始,^XZ 结束)。
    4. 检查编码是否正确

      • 确保使用打印机支持的字符集(如 GBK 或 UTF-8)。
    5. 添加日志输出

      • 在关键节点添加 Log.d(),便于排查问题。

    四、推荐测试指令(ZPL 示例)

    ^XA
    ^FO50,50^A0N,20,20^FDHello World^FS
    ^XZ
    

    解释:

    • ^XA:开始标签
    • ^FO50,50:设置文本起始位置(x=50, y=50)
    • ^A0N,20,20:字体设置(0号字体,20x20点)
    • ^FDHello World^FS:显示“Hello World”
    • ^XZ:结束标签

    五、常见问题排查清单

    | 问题 | 解决方案 | |------|----------| | 打印机不出内容 | 检查打印指令是否正确,是否使用 ZPL/EPL | | 连接正常但无内容 | 确认 OutputStream 是否正确写入 | | 编码不匹配 | 更换为打印机支持的编码(如 ASCII、UTF-8) | | 权限不足 | 确保申请了 BLUETOOTH, BLUETOOTH_ADMIN, ACCESS_FINE_LOCATION 权限 |


    六、最终建议

    如果你仍然遇到问题,建议:

    • 使用打印机自带的测试页功能,确认打印机本身工作正常。
    • 用手机或其他设备尝试连接并打印,排除设备问题。
    • 查看打印机日志(如果有),看是否有错误提示。

    如有需要,我可以为你提供完整的 ZPL 指令生成器或打印机配置工具。欢迎继续提问!

    评论

报告相同问题?

问题事件

  • 创建了问题 1月14日