今天写个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
这是我前端对应的效果:触发条件是点击按钮,开始依次往下进行



以下是相关代码:
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>
我想实现的效果是,程序正常运行,并且打印机正常输出我想要的文件