up
This commit is contained in:
+32
-2
@@ -1,3 +1,6 @@
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.compose)
|
||||
@@ -15,10 +18,14 @@ android {
|
||||
applicationId = "com.example.ops_android"
|
||||
minSdk = 24
|
||||
targetSdk = 36
|
||||
versionCode = 1
|
||||
versionName = "1.0"
|
||||
versionCode = 2
|
||||
versionName = "1.1"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
|
||||
// 作者信息
|
||||
buildConfigField("String", "AUTHOR", "\"无闻风\"")
|
||||
buildConfigField("String", "BUILD_DATE", "\"${SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(Date())}\"")
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@@ -26,6 +33,15 @@ android {
|
||||
optimization {
|
||||
enable = false
|
||||
}
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
debug {
|
||||
applicationIdSuffix = ".debug"
|
||||
versionNameSuffix = "-debug"
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
@@ -34,6 +50,20 @@ android {
|
||||
}
|
||||
buildFeatures {
|
||||
compose = true
|
||||
aidl = true
|
||||
buildConfig = true
|
||||
}
|
||||
}
|
||||
|
||||
androidComponents {
|
||||
onVariants { variant ->
|
||||
variant.outputs.forEach { output ->
|
||||
val versionName = "1.1"
|
||||
val versionCode = "2"
|
||||
val buildType = variant.buildType
|
||||
val date = SimpleDateFormat("yyyyMMdd").format(Date())
|
||||
output.outputFileName.set("PDA_Printer_Test_v${versionName}_${versionCode}_${buildType}_${date}.apk")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user