This commit is contained in:
2026-06-24 18:50:26 +08:00
parent b557f8b904
commit de270fe1ac
8 changed files with 1082 additions and 25 deletions
@@ -0,0 +1,21 @@
package android.bld;
interface IPrintManager {
void initPrinter();
void closePrinter();
void printText(String text);
void printText2(String text);
void printQR(String content, int size);
void printBarcode(String content, int type, int width, int height);
void printBitmap(in byte[] bitmap, int width, int height);
void printLine(int lineCount);
void start();
void setFontSize(int size);
void setTextBold(boolean bold);
void setUnderLine(boolean underline);
void setConcentration(int level);
void setFeedPaperSpace(int space);
void setUnwindPaperLen(int length);
void printEnableMark(boolean enable);
void printGoToNextMark();
}
@@ -4,44 +4,389 @@ import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.example.ops_android.printer.PrinterManager
import com.example.ops_android.ui.theme.Ops_androidTheme
class MainActivity : ComponentActivity() {
private lateinit var printerManager: PrinterManager
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
printerManager = PrinterManager(this)
enableEdgeToEdge()
setContent {
Ops_androidTheme {
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Greeting(
name = "Android",
PrinterTestScreen(
printerManager = printerManager,
modifier = Modifier.padding(innerPadding)
)
}
}
}
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
Ops_androidTheme {
Greeting("Android")
override fun onDestroy() {
super.onDestroy()
printerManager.unbindService()
}
}
}
@Composable
fun PrinterTestScreen(
printerManager: PrinterManager,
modifier: Modifier = Modifier
) {
var statusMessage by remember { mutableStateOf("未连接打印服务") }
var isConnected by remember { mutableStateOf(false) }
Column(
modifier = modifier
.fillMaxSize()
.padding(16.dp)
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
// 标题
Text(
text = "PDA 打印机测试",
style = MaterialTheme.typography.headlineMedium,
modifier = Modifier.padding(bottom = 8.dp)
)
// 版本信息
Text(
text = "v${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE}) - ${BuildConfig.AUTHOR}",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.padding(bottom = 8.dp)
)
// 状态显示
Card(
colors = CardDefaults.cardColors(
containerColor = if (isConnected)
MaterialTheme.colorScheme.primaryContainer
else
MaterialTheme.colorScheme.errorContainer
)
) {
Text(
text = statusMessage,
modifier = Modifier.padding(16.dp),
style = MaterialTheme.typography.bodyMedium
)
}
Divider()
// 连接控制区
Text("连接控制", style = MaterialTheme.typography.titleMedium)
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Button(
onClick = {
val success = printerManager.bindService()
isConnected = success
statusMessage = if (success) "正在连接打印服务..." else "连接失败"
},
modifier = Modifier.weight(1f)
) {
Text("绑定服务")
}
Button(
onClick = {
printerManager.initPrinter().fold(
onSuccess = { statusMessage = "打印机初始化成功" },
onFailure = { statusMessage = "初始化失败: ${it.message}" }
)
},
modifier = Modifier.weight(1f)
) {
Text("初始化")
}
}
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Button(
onClick = {
printerManager.closePrinter().fold(
onSuccess = { statusMessage = "打印机已关闭" },
onFailure = { statusMessage = "关闭失败: ${it.message}" }
)
},
modifier = Modifier.weight(1f)
) {
Text("关闭打印机")
}
Button(
onClick = {
printerManager.unbindService()
isConnected = false
statusMessage = "服务已解绑"
},
modifier = Modifier.weight(1f)
) {
Text("解绑服务")
}
}
Divider()
// 基础打印测试
Text("基础打印测试", style = MaterialTheme.typography.titleMedium)
Button(
onClick = {
printerManager.quickPrintText("Hello Printer!\n测试打印\n").fold(
onSuccess = { statusMessage = "快速打印成功" },
onFailure = { statusMessage = "打印失败: ${it.message}" }
)
},
modifier = Modifier.fillMaxWidth()
) {
Text("快速打印测试")
}
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Button(
onClick = {
printerManager.printText("使用 printText\n").fold(
onSuccess = { statusMessage = "printText 调用成功" },
onFailure = { statusMessage = "失败: ${it.message}" }
)
},
modifier = Modifier.weight(1f)
) {
Text("printText")
}
Button(
onClick = {
printerManager.printText2("使用 printText2\n").fold(
onSuccess = { statusMessage = "printText2 调用成功" },
onFailure = { statusMessage = "失败: ${it.message}" }
)
},
modifier = Modifier.weight(1f)
) {
Text("printText2")
}
}
Button(
onClick = {
printerManager.start().fold(
onSuccess = { statusMessage = "开始打印(出纸)" },
onFailure = { statusMessage = "失败: ${it.message}" }
)
},
modifier = Modifier.fillMaxWidth()
) {
Text("start() - 提交打印")
}
Divider()
// 样式测试
Text("样式设置", style = MaterialTheme.typography.titleMedium)
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Button(
onClick = {
printerManager.setFontSize(24).fold(
onSuccess = { statusMessage = "字体大小已设置" },
onFailure = { statusMessage = "失败: ${it.message}" }
)
},
modifier = Modifier.weight(1f)
) {
Text("大字体")
}
Button(
onClick = {
printerManager.setTextBold(true).fold(
onSuccess = { statusMessage = "已设置粗体" },
onFailure = { statusMessage = "失败: ${it.message}" }
)
},
modifier = Modifier.weight(1f)
) {
Text("粗体")
}
}
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Button(
onClick = {
printerManager.setUnderLine(true).fold(
onSuccess = { statusMessage = "已设置下划线" },
onFailure = { statusMessage = "失败: ${it.message}" }
)
},
modifier = Modifier.weight(1f)
) {
Text("下划线")
}
Button(
onClick = {
printerManager.setConcentration(5).fold(
onSuccess = { statusMessage = "浓度已设置" },
onFailure = { statusMessage = "失败: ${it.message}" }
)
},
modifier = Modifier.weight(1f)
) {
Text("浓度")
}
}
Divider()
// 二维码/条形码测试
Text("二维码与条形码", style = MaterialTheme.typography.titleMedium)
Button(
onClick = {
printerManager.printQR("https://example.com", 6).fold(
onSuccess = { statusMessage = "二维码已加入队列" },
onFailure = { statusMessage = "失败: ${it.message}" }
)
},
modifier = Modifier.fillMaxWidth()
) {
Text("打印二维码")
}
Button(
onClick = {
printerManager.printBarcode("1234567890", 0, 2, 60).fold(
onSuccess = { statusMessage = "条形码已加入队列" },
onFailure = { statusMessage = "失败: ${it.message}" }
)
},
modifier = Modifier.fillMaxWidth()
) {
Text("打印条形码")
}
Divider()
// 走纸控制
Text("走纸控制", style = MaterialTheme.typography.titleMedium)
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Button(
onClick = {
printerManager.printLine(3).fold(
onSuccess = { statusMessage = "打印空行" },
onFailure = { statusMessage = "失败: ${it.message}" }
)
},
modifier = Modifier.weight(1f)
) {
Text("打印3空行")
}
Button(
onClick = {
printerManager.setFeedPaperSpace(100).fold(
onSuccess = { statusMessage = "走纸间距已设置" },
onFailure = { statusMessage = "失败: ${it.message}" }
)
},
modifier = Modifier.weight(1f)
) {
Text("走纸间距")
}
}
Divider()
// 综合测试
Text("综合测试", style = MaterialTheme.typography.titleMedium)
Button(
onClick = {
runComprehensiveTest(printerManager) { msg -> statusMessage = msg }
},
modifier = Modifier.fillMaxWidth(),
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.secondary
)
) {
Text("运行完整测试")
}
}
}
private fun runComprehensiveTest(
printerManager: PrinterManager,
onStatus: (String) -> Unit
) {
onStatus("开始综合测试...")
printerManager.initPrinter().onFailure {
onStatus("初始化失败: ${it.message}")
return
}
// 标题
printerManager.setFontSize(32)
printerManager.setTextBold(true)
printerManager.printText2("=== 打印测试 ===\n")
// 普通文本
printerManager.setFontSize(24)
printerManager.setTextBold(false)
printerManager.printText2("普通文本测试\n")
// 粗体文本
printerManager.setTextBold(true)
printerManager.printText2("粗体文本测试\n")
printerManager.setTextBold(false)
// 下划线文本
printerManager.setUnderLine(true)
printerManager.printText2("下划线文本测试\n")
printerManager.setUnderLine(false)
// 空行
printerManager.printLine(1)
// 二维码
printerManager.printText2("二维码测试:\n")
printerManager.printQR("https://example.com", 6)
printerManager.printLine(1)
// 条形码
printerManager.printText2("条形码测试:\n")
printerManager.printBarcode("123456789012", 0, 2, 60)
printerManager.printLine(3)
// 分隔线
printerManager.printText2("--------------------------------\n")
printerManager.printText2("测试完成\n")
printerManager.printLine(2)
// 提交打印
printerManager.start().fold(
onSuccess = { onStatus("综合测试完成,开始打印") },
onFailure = { onStatus("提交打印失败: ${it.message}") }
)
printerManager.closePrinter()
}
@@ -0,0 +1,136 @@
package com.example.ops_android.printer
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import android.util.Log
import android.bld.IPrintManager
class PrinterManager(private val context: Context) {
private var printService: IPrintManager? = null
private var isBound = false
companion object {
private const val TAG = "PrinterManager"
private const val PRINT_SERVICE_ACTION = "android.bld.PrintManager"
private const val PRINT_SERVICE_PACKAGE = "android.bld"
}
private val serviceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
printService = IPrintManager.Stub.asInterface(service)
isBound = true
Log.d(TAG, "Print service connected")
}
override fun onServiceDisconnected(name: ComponentName?) {
printService = null
isBound = false
Log.d(TAG, "Print service disconnected")
}
}
fun bindService(): Boolean {
return try {
val intent = Intent(PRINT_SERVICE_ACTION).apply {
setPackage(PRINT_SERVICE_PACKAGE)
}
context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
} catch (e: Exception) {
Log.e(TAG, "Failed to bind print service", e)
false
}
}
fun unbindService() {
if (isBound) {
context.unbindService(serviceConnection)
isBound = false
}
}
// 基础连接方法
fun initPrinter(): Result<Unit> = runCatching {
printService?.initPrinter() ?: throw Exception("Print service not connected")
}
fun closePrinter(): Result<Unit> = runCatching {
printService?.closePrinter() ?: throw Exception("Print service not connected")
}
// 打印方法
fun printText(text: String): Result<Unit> = runCatching {
printService?.printText(text) ?: throw Exception("Print service not connected")
}
fun printText2(text: String): Result<Unit> = runCatching {
printService?.printText2(text) ?: throw Exception("Print service not connected")
}
fun printQR(content: String, size: Int = 6): Result<Unit> = runCatching {
printService?.printQR(content, size) ?: throw Exception("Print service not connected")
}
fun printBarcode(content: String, type: Int = 0, width: Int = 2, height: Int = 60): Result<Unit> = runCatching {
printService?.printBarcode(content, type, width, height) ?: throw Exception("Print service not connected")
}
fun printBitmap(bitmap: ByteArray, width: Int, height: Int): Result<Unit> = runCatching {
printService?.printBitmap(bitmap, width, height) ?: throw Exception("Print service not connected")
}
fun printLine(lineCount: Int = 1): Result<Unit> = runCatching {
printService?.printLine(lineCount) ?: throw Exception("Print service not connected")
}
fun start(): Result<Unit> = runCatching {
printService?.start() ?: throw Exception("Print service not connected")
}
// 样式设置方法
fun setFontSize(size: Int): Result<Unit> = runCatching {
printService?.setFontSize(size) ?: throw Exception("Print service not connected")
}
fun setTextBold(bold: Boolean): Result<Unit> = runCatching {
printService?.setTextBold(bold) ?: throw Exception("Print service not connected")
}
fun setUnderLine(underline: Boolean): Result<Unit> = runCatching {
printService?.setUnderLine(underline) ?: throw Exception("Print service not connected")
}
fun setConcentration(level: Int): Result<Unit> = runCatching {
printService?.setConcentration(level) ?: throw Exception("Print service not connected")
}
// 走纸控制
fun setFeedPaperSpace(space: Int): Result<Unit> = runCatching {
printService?.setFeedPaperSpace(space) ?: throw Exception("Print service not connected")
}
fun setUnwindPaperLen(length: Int): Result<Unit> = runCatching {
printService?.setUnwindPaperLen(length) ?: throw Exception("Print service not connected")
}
// 标签纸控制
fun printEnableMark(enable: Boolean): Result<Unit> = runCatching {
printService?.printEnableMark(enable) ?: throw Exception("Print service not connected")
}
fun printGoToNextMark(): Result<Unit> = runCatching {
printService?.printGoToNextMark() ?: throw Exception("Print service not connected")
}
// 便捷组合方法
fun quickPrintText(text: String): Result<Unit> = runCatching {
initPrinter().getOrThrow()
printText2(text).getOrThrow()
start().getOrThrow()
closePrinter().getOrThrow()
}
fun isServiceConnected(): Boolean = isBound && printService != null
}