养乐多滋滋滋 2025-06-24 10:04 采纳率: 79.2%
浏览 10

关于#android#的问题:安卓无线连接打印机

今天写个demo,关于,安卓无线连接打印机,进行输出,打印机品牌 RIOCH MP1813L
遇到的问题:
1:日志提示(已经找到对应的打印机,并且打印任务也发送到打印机了,为什么打印机不输出?)

2025-02-09 06:05:58.735 32264-1118  MainActivity            com.jl.bluetoothprinter              I  开始找打印机
2025-02-09 06:05:58.766 32264-1120  MainActivity            com.jl.bluetoothprinter              I  找到打印机: 192.168.10.251
2025-02-09 06:06:00.755 32264-32264 MainActivity            com.jl.bluetoothprinter              I  当前打印任务列表:
                                                                                                    打印机 IP: 192.168.10.251,打印内容: 这是要打印的测试内容
2025-02-09 06:06:05.789 32264-1118  MainActivity            com.jl.bluetoothprinter              I  打印成功,数据已完整发送到 192.168.10.251


这是我前端对应的效果:触发条件是点击按钮,开始依次往下进行

img

img

img

以下是相关代码:
MainActivity

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private static final int PRINTER_PORT = 10001; // 假设打印机端口
    private static final int TIMEOUT = 5000; // 连接超时时间
    // 使用 Map 来记录打印机 IP 和对应的打印内容
    private Map<String, String> printTaskList = new HashMap<>();

    // 新增:定义打印纸格式枚举
    public enum PaperSize {
        A1, A2, A3, A4
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 第三步:在布局文件 activity_main.xml 中定义一个 id 为 btn_print 的按钮。
        // 打开 res/layout/activity_main.xml 文件,添加一个 Button 组件,并设置其 android:id="@+id/btn_print"。
        setContentView(R.layout.activity_main);

        Button printButton = findViewById(R.id.btn_print);
        if (printButton == null) {
            Log.e(TAG, "onCreate: 未找到打印按钮,请检查布局文件");
            return;
        }

        printButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        Log.d(TAG, "run: 开始扫描局域网打印机");
                        List<String> availablePrinters = scanLocalNetwork();
                        if (!availablePrinters.isEmpty()) {
                            for (String printerIp : availablePrinters) {
                                // 新增:指定打印纸格式为 A4
                                printWithIp(printerIp, PaperSize.A4);
                            }
                        } else {
                            Log.i(TAG, "未找到可用的打印机");
                            showToast("未找到可用的打印机");
                        }
                    }
                }).start();
            }
        });
    }

    // ... existing code ...
    // 第四步:根据局域网,搜索对应的打印机
    private List<String> scanLocalNetwork() {
        // 开始找打印机时输出日志和显示提示
        Log.i(TAG, "开始找打印机");
        showToast("开始找打印机");

        List<String> availablePrinters = Collections.synchronizedList(new ArrayList<>());
        // 增加线程池大小,可根据设备性能调整
        int threadCount = 254; // 每个 IP 一个线程
        ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
        String baseIp = "192.168.10.";
        int reducedTimeout = 1000; // 减少超时时间到 1 秒

        for (int i = 250; i <= 251; i++) {
            final int ipSuffix = i;
            executorService.submit(() -> {
                String ip = baseIp + ipSuffix;
                try {
                    InetAddress address = InetAddress.getByName(ip);
                    if (address.isReachable(reducedTimeout)) {
                        try (Socket socket = new Socket()) {
                            socket.connect(new InetSocketAddress(ip, PRINTER_PORT), reducedTimeout);
                            availablePrinters.add(ip);
                            Log.i(TAG, "找到打印机: " + ip);
                            // 在找到打印机时显示提示
                            showToast("找到打印机: " + ip);
                        } catch (Exception e) {
                            // 连接失败,忽略
                            Log.e("连接失败,请重新尝试", e.getMessage());
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }

        executorService.shutdown();
        try {
            // 等待最多 3 秒
            if (!executorService.awaitTermination(3, TimeUnit.SECONDS)) {
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            executorService.shutdownNow();
            Thread.currentThread().interrupt();
        }

        return availablePrinters;
    }
// ... existing code ...

    // 新增:修改打印方法,添加打印纸格式参数
    private void printWithIp(String printerIp, PaperSize paperSize) {
        String printContent = "这是要打印的测试内容";
        // 添加任务到列表
        printTaskList.put(printerIp, printContent);
        updateTaskListUI();

        Socket socket = null;
        OutputStream outputStream = null;
        try {
            socket = new Socket();
            socket.connect(new InetSocketAddress(printerIp, PRINTER_PORT), TIMEOUT);
            outputStream = socket.getOutputStream();

            // 常见初始化指令
            byte[] initCommand = {0x1B, 0x40};
            outputStream.write(initCommand);

            // 新增:根据打印纸格式发送相应指令
            switch (paperSize) {
                case A1:
                    // 示例指令,实际需参考打印机文档
                    byte[] a1Command = {0x1D, 0x57, 0x00, (byte)0xFF, (byte) 0xFF};
                    outputStream.write(a1Command);
                    break;
                case A2:
                    // 示例指令,实际需参考打印机文档
                    byte[] a2Command = {0x1D, 0x57, 0x00, (byte)0xAA, (byte) 0xAA};
                    outputStream.write(a2Command);
                    break;
                case A3:
                    // 示例指令,实际需参考打印机文档
                    byte[] a3Command = {0x1D, 0x57, 0x00, (byte)0x88, (byte) 0x88};
                    outputStream.write(a3Command);
                    break;
                case A4:
                    // 示例指令,实际需参考打印机文档
                    byte[] a4Command = {0x1D, 0x57, 0x00, (byte)0x68, 0x06};
                    outputStream.write(a4Command);
                    break;
            }

            //  UTF-8   ISO-8859-1   GBK 编码
            byte[] printData = printContent.getBytes("GBK");
            outputStream.write(printData);

            // 常见结束指令,包含换行和打印
            byte[] endCommand = {0x0A, 0x0D};
            outputStream.write(endCommand);

            outputStream.flush();
            try {
                // 延长等待时间到 5 秒
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.i(TAG, "打印成功,数据已完整发送到 " + printerIp);
            showToast("打印成功: " + printerIp);
        } catch (IOException e) {
            Log.e(TAG, "打印到 " + printerIp + " 失败: " + e.getMessage());
            showToast("打印到 " + printerIp + " 失败,请检查网络连接");
            e.printStackTrace();
        } finally {
            // 从列表中移除任务
            printTaskList.remove(printerIp);
            updateTaskListUI();

            try {
                if (outputStream != null) {
                    outputStream.close();
                }
                if (socket != null && !socket.isClosed()) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // 更新 UI 的方法
    private void updateTaskListUI() {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                // 这里可以添加更新 UI 显示任务列表的代码
                StringBuilder taskListText = new StringBuilder();
                taskListText.append("当前打印任务列表:\n");
                for (Map.Entry<String, String> entry : printTaskList.entrySet()) {
                    String printerIp = entry.getKey();
                    String content = entry.getValue();
                    taskListText.append("打印机 IP: ").append(printerIp).append(",打印内容: ").append(content).append("\n");
                }
                Log.i(TAG, taskListText.toString());
            }
        });
    }

    private void showToast(final String message) {
        new Handler(Looper.getMainLooper()).post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show();
            }
        });
    }


}

AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.jl.bluetoothprinter">

    <!-- 允许应用使用蓝牙功能 -->
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <!-- 允许应用管理蓝牙功能,如扫描设备、配对等 -->
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <!-- Android 6.0 及以上版本扫描蓝牙设备需要位置权限 -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

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

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


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

    <!-- ... existing code ... -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <!-- ... existing code ... -->

    <!-- 添加网络访问权限   -->
    <uses-permission android:name="android.permission.INTERNET" />


    <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"
        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="16dp">

    <Button
        android:id="@+id/btn_scan"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="扫描蓝牙设备" />

    <ListView
        android:id="@+id/list_devices"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1" />

    <EditText
        android:id="@+id/et_print_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="输入要打印的内容" />

    <Button
        android:id="@+id/btn_print"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="打印" />


</LinearLayout>

我想实现的效果是,程序正常运行,并且打印机正常输出我想要的文件

  • 写回答

5条回答 默认 最新

  • 阿里嘎多学长 2025-06-24 10:04
    关注

    阿里嘎多学长整理AIGC生成,因移动端显示问题导致当前答案未能完全显示,请使用PC端查看更加详细的解答过程

    关于安卓无线连接打印机的问题

    你遇到的问题是,使用 Android 无线连接 RIOCH MP1813L 打印机,但是打印机不输出。日志提示已经找到对应的打印机,并且打印任务也发送到打印机了。

    解决方案:

    1. 检查打印机是否正确连接:确保打印机已经正确连接到 Android 设备,并且打印机的网络设置正确。
    2. 检查打印机的网络状态:使用 PrintManagergetPrinters() 方法获取打印机列表,然后使用 PrinterInfogetState() 方法检查打印机的网络状态。如果状态为 STATE_IDLE,则表示打印机已经连接成功。
    3. 检查打印任务是否正确发送:使用 PrintJobsend() 方法发送打印任务到打印机。如果发送失败,检查日志是否有错误信息。
    4. 检查打印机的纸张状态:使用 PrintJobgetPaperStatus() 方法检查打印机的纸张状态。如果纸张状态为 PAPER_STATUS_EMPTY,则表示打印机没有纸张。

    核心代码:

    PrintManager printManager = (PrintManager) getSystemService(Context.PRINT_SERVICE);
    List<PrinterInfo> printers = printManager.getPrinters();
    for (PrinterInfo printer : printers) {
        if (printer.getName().equals("RIOCH MP1813L")) {
            PrinterInfo printerInfo = printer;
            if (printerInfo.getState() == PrinterInfo.STATE_IDLE) {
                // 发送打印任务
                PrintJob printJob = new PrintJob(printerInfo, "打印任务", new PrintJobCallback() {
                    @Override
                    public void onPrintJobSent(PrintJob printJob) {
                        Log.d("PrintJob", "打印任务发送成功");
                    }
                });
                printJob.send();
            }
        }
    }
    

    注意:上述代码只是示例代码,需要根据实际情况进行修改。

    评论

报告相同问题?

问题事件

  • 创建了问题 6月24日