Android连接蓝牙打印机

前言

在之前写过一篇Android操作蓝牙打印机(上),当时也是因为自己在工作中确实走了许多弯路,所以当时计划着用两篇文章详细阐述蓝牙打印的整个流程,也是对工作的一种总结,其次也可以给蓝牙打印方面感觉困惑的同学做一些参考,后来由于接近年底,任务比较多,所以就暂且搁置了。后来在阅读之前的代码时发现是相当繁琐(甚至感觉有些地方考虑的很复杂),最明显的复杂就是通过广播去监听蓝牙的状态,操作起来相当繁琐,久而久之,随着业务场景的增多,就出了bug,最头疼的就是与业务代码参杂在一起,不够解耦,也包括后来测试也给我提了bug,导致在bug系统挂了很久,前几天的一天早上项目经理也问我什么时候把这个bug处理一下,其实早在五一之前我就对此次重构做了一个大概了,只是一些周边细节未完善,这几天也是抽了许多时间优化,测试,把项目相关模块重构,将蓝牙部分抽取出来以依赖的方式集成在项目中。

git地址

传送门(https://github.com/zhuhuitao/printer)
在你的app build.gradle 中添加如下代码:


dependencies {
    ...
    implementation "com.github.zhuhuitao:printer:1.0.9"
}

在上一篇文章之后,有好几个小伙伴私信我,能不能把源码放到git,参考一下,这里我统一回复,当时由于整个蓝牙部分与业务参杂在一起,并没有一个完整的demo,后来也没有上传,所以给之前带来不便的小伙伴,说一声抱歉。

功能介绍

在之前的文章中从头到尾是阐述了如何扫描,连接蓝牙,大都与蓝牙相关,此次与之前大为不同,这里我们只需要将相关依赖导入项目中,我们可以将所有精力放到我们业务代码中,不需要在关心蓝牙部分,依赖已将所有蓝牙部分做了封装,我们只管调用接口完成打印就好。并且这次重构简化了许多代码,结构清晰,也去掉了广播监听,等等许多繁琐的地方。

在阐述使用之前我还是将整个依赖的大体功能做一些介绍:
1,核心接口IMyBinder类,这个类主要是与我们业务打交道的接口,包括我们连接蓝牙,往蓝牙打印机写入数据,断开蓝牙等相关功能,代码如下:

/**
 *author  : huitao
 *e-mail  : pig.huitao@gmail.com
 *date    : 2021/4/13 10:42
 *desc    :
 *version :
 */
interface IMyBinder {
    fun connectBtPort(var1: String, var2: TaskCallback)

    fun disconnectCurrentPort(var1: TaskCallback)

    fun clearBuffer()

    fun checkLinkedState(var1: TaskCallback)

    fun onDiscovery(
        var1: Context,
        portType: PrinterDev.PortType,
        callback: DeviceFoundCallback
    ): MutableList<String>?

    fun getBtAvailableDevice(): MutableList<String>

    fun write(var1: ByteArray?, var2: TaskCallback)

    fun writeSendData(var1: TaskCallback, var2: ProcessData)

    fun acceptDataFromPrinter(var1: TaskCallback?, var2: Int)

    fun readBuffer(): RoundQueue<ByteArray?>?

    fun read(var1: TaskCallback)
}

2,核心服务PrinterService类,在这个类中,实现了上述提到的IMyBinder接口,主要是对上一步IMyBinder接口做了进一步描述,代码如下:

class PrinterService : Service() {
    private val mMyBinder = MyBinder()
    private lateinit var mPrinterDev: PrinterDev
    private lateinit var mReturnMsg: ReturnMessage
    private var mIsConnected = false
    private var mQueue: RoundQueue<ByteArray>? = null
    private var mDeviceFoundCallback: DeviceFoundCallback? = null
    private fun getInstanceRoundQueue(): RoundQueue<ByteArray> {
        if (this.mQueue == null) {
            mQueue = RoundQueue(500)
        }
        return this.mQueue!!
    }

    override fun onCreate() {
        super.onCreate()
        this.mQueue = this.getInstanceRoundQueue()
    }


    private val mViewModelScope = CoroutineScope(Dispatchers.IO)
    override fun onBind(p0: Intent?): IBinder {
        return this.mMyBinder
    }


    inner class MyBinder : Binder(), IMyBinder {
        private var mBluetoothAdapter: BluetoothAdapter? = null
        private var mFond: MutableList<String>? = null
        private var mBond: MutableList<String>? = null
        private var mPortType: PrinterDev.PortType? = null
        private val mReceiver = object : BroadcastReceiver() {
            override fun onReceive(p0: Context?, p1: Intent?) {
                if (p1?.action == "android.bluetooth.device.action.FOUND") {

                    val device =
                        p1.getParcelableExtra<BluetoothDevice>("android.bluetooth.device.extra.DEVICE")
                            ?: return
                    if (!device.name.isNullOrEmpty()) {
                        mFond?.forEach {
                            if (it.split("\n").last() == device.address) {
                                return
                            }
                        }
                        mFond?.add("${device.name}\n${device.address}")
                        mDeviceFoundCallback?.deviceFoundCallback("${device.name} \n ${device.address}")

                    }
                }
            }
        }

        override fun connectBtPort(var1: String, var2: TaskCallback) {
            mViewModelScope.launch {
                mPrinterDev = PrinterDev(PrinterDev.PortType.Bluetooth, var1)
                mReturnMsg = this@PrinterService.mPrinterDev.open()
                mPortType = PrinterDev.PortType.Bluetooth
                mViewModelScope.launch(Dispatchers.Main) {
                    when (mReturnMsg.getErrorCode()) {
                        PrinterDev.ErrorCode.OpenPortSucceed -> {
                            mIsConnected = true
                            var2.onSucceed()
                        }
                        else -> {
                            var2.onFailed()
                        }
                    }
                }
            }
        }

        override fun disconnectCurrentPort(var1: TaskCallback) {
            mViewModelScope.launch {
                mReturnMsg = mPrinterDev.close()
                mViewModelScope.launch(Dispatchers.Main) {
                    when (mReturnMsg.getErrorCode()) {
                        PrinterDev.ErrorCode.ClosePortSucceed -> {
                            mIsConnected = false
                            if (mQueue != null) {
                                mQueue?.clear()
                            }
                            var1.onSucceed()
                        }
                        else -> {
                            var1.onFailed()
                        }
                    }
                }
            }.start()
        }

        override fun clearBuffer() {
            mQueue?.clear()
        }

        override fun checkLinkedState(var1: TaskCallback) {
            mViewModelScope.launch {
                if (mPrinterDev.getPortInfo().isOpened) var1.onSucceed() else var1.onFailed()
            }.start()
        }

        override fun onDiscovery(
            var1: Context,
            portType: PrinterDev.PortType,
            callback: DeviceFoundCallback
        ): MutableList<String>? {
            this.mFond = mutableListOf()
            this.mBond = mutableListOf()
            mDeviceFoundCallback = callback
            if (portType == PrinterDev.PortType.Bluetooth) {
                this.mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
                if (mBluetoothAdapter == null) {
                    Toast.makeText(
                        this@PrinterService,
                        "Device didn't support bluetooth !\n",
                        Toast.LENGTH_SHORT
                    ).show()
                    return null
                }
                if (mBluetoothAdapter!!.isEnabled) {
                    if (mBluetoothAdapter!!.enable()) {
                        if (!mBluetoothAdapter!!.isDiscovering) {
                            mBluetoothAdapter!!.startDiscovery()
                        }
                        val filter = IntentFilter("android.bluetooth.device.action.FOUND")
                        registerReceiver(mReceiver, filter)
                        val pairedDevice = mBluetoothAdapter!!.bondedDevices
                        if (!pairedDevice.isNullOrEmpty()) {
                            val it = pairedDevice.iterator()
                            while (it.hasNext()) {
                                val device = it.next()
                                mBond?.add("${device.name}\n${device.address}")
                            }
                        } else {
                            Looper.prepare()
                            Toast.makeText(
                                this@PrinterService,
                                "no paired device",
                                Toast.LENGTH_SHORT
                            ).show()
                            Looper.loop()
                        }
                    } else {
                        Toast.makeText(
                            this@PrinterService,
                            "Bluetooth is not enable !\n",
                            Toast.LENGTH_SHORT
                        ).show()
                    }
                } else {
                    Toast.makeText(
                        this@PrinterService,
                        "Bluetooth adapter is not enabled !\n",
                        Toast.LENGTH_SHORT
                    ).show()
                }

            }
            return this.mBond
        }

        override fun getBtAvailableDevice(): MutableList<String> {
            this.mBluetoothAdapter?.cancelDiscovery()
            return this.mFond!!
        }

        override fun write(var1: ByteArray?, var2: TaskCallback) {
            if (var1 != null) {
                mViewModelScope.launch {
                    mReturnMsg = mPrinterDev.write(var1)
                    mViewModelScope.launch(Dispatchers.Main) {
                        when (mReturnMsg.getErrorCode()) {
                            PrinterDev.ErrorCode.WriteDataSucceed -> {
                                mIsConnected = true
                                var2.onSucceed()
                            }
                            else -> {
                                mIsConnected = false
                                var2.onFailed()
                            }
                        }
                    }
                }
            }
        }

        override fun writeSendData(var1: TaskCallback, var2: ProcessData) {
            val list = var2.processDataBeforeSend()
            if (list == null) {
                var1.onFailed()
            } else {
                mViewModelScope.launch {
                    list.forEach {
                        mReturnMsg = mPrinterDev.write(it)
                    }
                    when (mReturnMsg.getErrorCode()) {
                        PrinterDev.ErrorCode.WriteDataSucceed -> {
                            mIsConnected = true
                            var1.onSucceed()
                        }
                        else -> {
                            mIsConnected = false
                            var1.onFailed()
                        }
                    }
                }.start()
            }
        }

        override fun acceptDataFromPrinter(var1: TaskCallback?, var2: Int) {
            val buffer = ByteArray(var2)
            mViewModelScope.launch {
                kotlin.runCatching {
                    mQueue = getInstanceRoundQueue()
                    mQueue?.clear()
                    mQueue?.addLast(buffer)
                    Log.i("frank", "acceptDataFromPrinter: " + Arrays.toString(mQueue!!.last))
                }.onSuccess {

                }.onFailure {

                }
            }
        }

        override fun readBuffer(): RoundQueue<ByteArray?>? {
            return null
        }

        override fun read(var1: TaskCallback) {
            mViewModelScope.launch {
                val msg = mPrinterDev.read()
                Log.d("frank", "read: $msg")
            }
        }

    }
}

在我们使用的时候仅和这两个类做了相关调用,由于我主要想讲述如何使用此依赖,所以暂且介绍了这两个类,如果感兴趣可以直接阅读源码,这样更快捷。

使用

一般我们都是将蓝牙部分运用在项目中,并不像我们写个demo学习那样简单,我也思考着怎么把demo写的更贴实际,但是终究demo功能还是很单一,没有实际业务那么复杂,所以建议只是做参考。

1,创建服务MyService类继承android 中的Service,其实为了简单,也可以不创建服务,为了更贴实际项目,所以创建了MyService,这个服务主要是用来启动我们蓝牙模块中的PrinterService,以及启动另外一个辅助服务AncillaryService,辅助服务接下来我再另外介绍,最后也就是与我们业务做交互,比如与Activity做交互发送接收数据。MyService主要是我们业务的Activity与PrintService中间的桥梁,详细代码如下:

/**
 *author  : huitao
 *e-mail  : pig.huitao@gmail.com
 *date    : 2021/5/17 18:07
 *desc    :
 *version :
 */
class MyService : Service() {
    private var mIMyBinder: IMyBinder? = null
    private val mServiceConnect = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            mIMyBinder = service as IMyBinder
            val mac = ""
            connectByMac(mac, object : TaskCallback {
                override fun onSucceed() {

                }

                override fun onFailed() {

                }
            })
        }

        override fun onServiceDisconnected(name: ComponentName?) {
        }
    }

    fun getBondDeviceList(): MutableList<String>? {
        return mIMyBinder?.onDiscovery(
            this,
            PrinterDev.PortType.Bluetooth,
            object : DeviceFoundCallback {
                override fun deviceFoundCallback(device: String) {
                    //这里接收扫描的周围蓝牙设备
                }
            })
    }


    fun writeData(bean: OrderBean, task: TaskCallback) {
        printOrderDetail(mMyBinder = mIMyBinder!!, order = bean, taskCallback = task)
    }

    fun connectByMac(mac: String, task: TaskCallback) {
        if (mac.isNotEmpty()) {
            mIMyBinder?.connectBtPort(mac, task)
        }
    }

    fun disconnect(task: TaskCallback) {
        mIMyBinder?.disconnectCurrentPort(task)
    }

    override fun onCreate() {
        super.onCreate()
        val intent = Intent(this, AncillaryService::class.java)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            AncillaryService.startForeground(this)
            startForegroundService(intent)
        } else {
            startService(intent)
        }

        val service = Intent(this, PrinterService::class.java)
        bindService(service, mServiceConnect, BIND_AUTO_CREATE)
    }

    override fun onBind(p0: Intent?): IBinder {
        return MyBinder()
    }


    inner class MyBinder : Binder() {
        fun getService(): MyService {
            return this@MyService
        }
    }
}

2,关于辅助服务AncillaryService,也是继承android Service,这个类主要是用来在手机通知栏弹出一个应用正在运行的功能,因为实际项目中可以尽可能的减少被系统杀死的概率,由于我们主要任务不在此处,包括8.0之前与之后系通知栏的变化,如果你感兴趣,还是建议收集资料详细的了解,比如实际代码中,我在onCreate直接停止了服务 stopSelf(),这个主要是在7.0之前有效,就是可以做一个假象,通知栏不会存在通知。详细代码如下:

/**
 *author  : huitao
 *e-mail  : pig.huitao@gmail.com
 *date    : 2021/5/17 18:39
 *desc    :
 *version :
 */
class AncillaryService:Service() {
    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    override fun onCreate() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            startForeground(this)
        }
        stopSelf()
    }

    override fun onDestroy() {
        super.onDestroy()
        stopForeground(true)
    }

    companion object{
        fun startForeground(ctx: Service) {
            try {
                val CHANNEL_ONE_ID = "CHANNEL_ONE_ID"
                val CHANNEL_ONE_NAME = "CHANNEL_ONE_ID"
                val SERVICE_ID = 802
                val notificationChannel: NotificationChannel
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    notificationChannel = NotificationChannel(
                        CHANNEL_ONE_ID, CHANNEL_ONE_NAME, NotificationManager.IMPORTANCE_HIGH
                    )
                    notificationChannel.enableLights(true)
                    notificationChannel.lightColor = R.color.app_them
                    notificationChannel.setShowBadge(true)
                    notificationChannel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
                    val nm = ctx.getSystemService(NOTIFICATION_SERVICE) as NotificationManager
                    nm.createNotificationChannel(notificationChannel)
                }
                val intent = Intent()
                val className = Class.forName("com.huitao.printerdemo.printer.PrinterActivity")
                intent.setClassName(ctx, className.name)
                val pendingIntent = PendingIntent.getActivity(ctx, 0, intent, 0)
                val builder = NotificationCompat.Builder(ctx, CHANNEL_ONE_ID)
                builder.setContentTitle(ctx.getString(R.string.pending_title))
                    .setContentText(ctx.getString(R.string.pending_content))
                    .setWhen(System.currentTimeMillis())
                    .setPriority(Notification.PRIORITY_MIN)
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentIntent(pendingIntent)
                    .setAutoCancel(true)
                val notification = builder.build()
                ctx.startForeground(SERVICE_ID, notification)
            } catch (e: ClassNotFoundException) {
                e.printStackTrace()
            }
        }
    }
}

3,业务层的PrinterActivity,这个类中的主要功能就是绑定我们前面提到的MyService,布局中写了两个textView和一个RecyclerView,用来获取绑定设备,测试打印,以及展示已绑定的设备列表。绑定服务以及列表展示就不做相关详细介绍,重点介绍一下连接,断开,获取设备列表功能。

a,获取已绑定的设备:

mBinder?.getService()?.getBondDeviceList()

这行代码就会帮我们返回手机已绑定的蓝牙设备,具体获取是在PrinterService中实现的,前面有相关代码,看到这里我想你大概会存在疑问,如何获取周围的蓝牙设备,这可不必大有担心,也有实现,在PrinterService中,有以下代码:

    fun getBondDeviceList(): MutableList<String>? {
        return mIMyBinder?.onDiscovery(
            this,
            PrinterDev.PortType.Bluetooth,
            object : DeviceFoundCallback {
                override fun deviceFoundCallback(device: String) {
                    //这里接收扫描的周围蓝牙设备
                }
            })
    }

我们可以在此处理扫描的周围蓝牙设备,也可以直接将集合回调到Activity层。

b,连接蓝牙,实际是一个耗时操作,底层已使用协程做了耗时处理,所以此处我们不必关心耗时相关代码,只关心回调给我们的连接状态,处理业务就好,详细代码如下:

     mBinder?.getService()?.connectByMac(mList[obj].name.split("\n").last().trim(),
                    object : TaskCallback {
                        override fun onSucceed() {
                            Toast.makeText(
                                this@PrinterActivity,
                                getString(R.string.connect_success),
                                Toast.LENGTH_SHORT
                            ).show()
                            mIsConnect = true
                            mList[obj].isConnected = true
                            mAdapter.notifyItemChanged(obj)
                        }

                        override fun onFailed() {
                            Toast.makeText(
                                this@PrinterActivity,
                                getString(R.string.connect_failure),
                                Toast.LENGTH_SHORT
                            ).show()
                        }
                    })

c,断开连接,实际调用接口和连接一样,详细代码如下,不做过多介绍:

 mBinder?.getService()?.disconnect(object : TaskCallback {
                    override fun onSucceed() {
                        Toast.makeText(
                            this@PrinterActivity,
                            getString(R.string.disconnect_success),
                            Toast.LENGTH_SHORT
                        ).show()
                        mList[obj].isConnected = false
                        mAdapter.notifyItemChanged(obj)
                        mIsConnect = false
                    }

                    override fun onFailed() {
                        Toast.makeText(
                            this@PrinterActivity,
                            getString(R.string.disconnect_failure),
                            Toast.LENGTH_SHORT
                        ).show()
                    }
                })

d,最后介绍以下启动app后自动连接的功能,此方法在MyService中有实现,由于demo中没有使用数据库或者sp等存储功能,所以只写了一个样板,我们可以将上一次连接蓝牙mac,缓存在本地或者数据库中,下次在启动服务时,直接调用连接蓝牙功能连接蓝牙,代码如下:

    private val mServiceConnect = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            mIMyBinder = service as IMyBinder
            val mac = ""
            connectByMac(mac, object : TaskCallback {
                override fun onSucceed() {

                }

                override fun onFailed() {

                }
            })
        }

        override fun onServiceDisconnected(name: ComponentName?) {
        }
    }

e,最后就是向蓝牙打印机写入数据,写入数据也是耗时操作,不过我们完全不用关心此问题,我们直接调用writeSendData就可以发送数据,完成打印功能,这里做了一个巧妙的设计,将我们的所有要打印的byte字节装入一个list集合,传给下层服务,可以直接完成打印,并且下层还将打印结果成功或者失败状态返回来,demo中的相关代码如下:

fun printOrderDetail(mMyBinder: IMyBinder, order: OrderBean, taskCallback: TaskCallback) {
    mMyBinder.writeSendData(taskCallback, object : ProcessData {
        override fun processDataBeforeSend(): MutableList<ByteArray> {
            val list = ArrayList<ByteArray>()
            list.add(DataForSendToPrinter.initializePrinter())
            list.add(DataForSendToPrinter.selectAliment(0x01))
            list.add(DataForSendToPrinter.selectFontSize(0x11))
            list.add(strToBytes("#${order.pickUpCode} 测试外卖")!!)
            list.add(DataForSendToPrinter.printAndFeedLine())
            list.add(DataForSendToPrinter.printAndFeedLine())

            list.add(DataForSendToPrinter.initializePrinter())
            list.add(DataForSendToPrinter.selectAliment(0x01))
            list.add(DataForSendToPrinter.selectFontSize(0x01))
            list.add(strToBytes("*${order.shopName}*")!!)
            list.add(DataForSendToPrinter.printAndFeedLine())
            list.add(DataForSendToPrinter.printAndFeedLine())

            list.add(DataForSendToPrinter.initializePrinter())
            list.add(DataForSendToPrinter.selectFontSize(0x11))
            list.add(DataForSendToPrinter.selectAliment(0x01))
            list.add(strToBytes("--已在线支付--")!!)
            list.add(DataForSendToPrinter.printAndFeedLine())
            list.add(DataForSendToPrinter.printAndFeedLine())

            list.add(DataForSendToPrinter.initializePrinter())
            list.add(DataForSendToPrinter.printBothColumns("配送方式:", order.deliveryTypeStr))
            list.add(DataForSendToPrinter.printAndFeedLine())
            list.add(DataForSendToPrinter.printAndFeedLine())

            list.add(DataForSendToPrinter.initializePrinter())
            list.add(DataForSendToPrinter.printBothColumns("下单时间:", order.createTime))
            list.add(DataForSendToPrinter.printAndFeedLine())
            list.add(DataForSendToPrinter.printAndFeedLine())

            val onTime = order.receiveTime
            if (onTime != null) {
                list.add(DataForSendToPrinter.initializePrinter())
                list.add(DataForSendToPrinter.printBothColumns("预计送达时间:", onTime))
                list.add(DataForSendToPrinter.printAndFeedLine())
                list.add(DataForSendToPrinter.printAndFeedLine())
            }

            list.add(DataForSendToPrinter.initializePrinter())
            list.add(DataForSendToPrinter.selectOrCancelBoldModel(0x01))
            list.add(strToBytes("客户留言:")!!)
            list.add(DataForSendToPrinter.printAndFeedLine())
            list.add(DataForSendToPrinter.printAndFeedLine())
            if (order.remarks == null) {
                list.add(DataForSendToPrinter.printAndFeedLine())
                list.add(DataForSendToPrinter.printAndFeedLine())
            } else {
                list.add(strToBytes(order.remarks)!!)
            }
            list.add(DataForSendToPrinter.printAndFeedLine())
            list.add(DataForSendToPrinter.printAndFeedLine())

            list.add(DataForSendToPrinter.initializePrinter())
            if (order.receiver != null && order.receiver.isNotEmpty()) {
                list.add(
                    DataForSendToPrinter.printBothColumns(
                        "收货人:",
                        "${order.receiver.substring(0, 1)}**"
                    )
                )
                list.add(DataForSendToPrinter.printAndFeedLine())
                list.add(DataForSendToPrinter.printAndFeedLine())
            }
            if (order.receiverMobile != null) {
                list.add(DataForSendToPrinter.printBothColumns("电话:", order.receiverMobile))
                list.add(DataForSendToPrinter.printAndFeedLine())
                list.add(DataForSendToPrinter.printAndFeedLine())
            }
            if (order.riderName != null) {
                list.add(DataForSendToPrinter.printBothColumns("骑手:", order.riderName))
                list.add(DataForSendToPrinter.printAndFeedLine())
                list.add(DataForSendToPrinter.printAndFeedLine())
            }
            if (order.riderMobile != null) {
                list.add(DataForSendToPrinter.printBothColumns("电话:", order.riderMobile))
                list.add(DataForSendToPrinter.printAndFeedLine())
                list.add(DataForSendToPrinter.printAndFeedLine())
            }
            if (order.address != null) {
                list.add(strToBytes("收货地址:${order.address}")!!)
                list.add(DataForSendToPrinter.printAndFeedLine())
                list.add(DataForSendToPrinter.printAndFeedLine())
            }
            list.add(DataForSendToPrinter.printThreeColumns("名称", "数量", "售价"))
            list.add(DataForSendToPrinter.printAndFeedLine())
            list.add(DataForSendToPrinter.printAndFeedLine())
            order.orderDetailList.forEach {
                val price = when (it.isDiscount) {
                    1 -> numberFormat(it.amount)
                    else -> numberFormat(it.shopPrice)
                }
                list.add(DataForSendToPrinter.initializePrinter())
                list.add(DataForSendToPrinter.selectOrCancelBoldModel(0x01))
                list.add(strToBytes(it.goodsName)!!)
                list.add(DataForSendToPrinter.printAndFeedLine())
                list.add(DataForSendToPrinter.printThreeColumns("", "${it.buyCount}", "¥$price"))
                list.add(DataForSendToPrinter.printAndFeedLine())
                list.add(DataForSendToPrinter.printAndFeedLine())
            }

            list.add(DataForSendToPrinter.initializePrinter())
            list.add(
                DataForSendToPrinter.printBothColumns(
                    "订单原价:",
                    "¥${numberFormat(order.money)}"
                )
            )
            list.add(DataForSendToPrinter.printAndFeedLine())
            list.add(DataForSendToPrinter.printAndFeedLine())
            list.add(
                DataForSendToPrinter.printBothColumns(
                    "配送费:",
                    "¥${numberFormat(order.freight)}"
                )
            )
            list.add(DataForSendToPrinter.printAndFeedLine())
            list.add(DataForSendToPrinter.printAndFeedLine())
            list.add(
                DataForSendToPrinter.printBothColumns(
                    "实付金额:",
                    "¥${numberFormat(order.payMoney)}"
                )
            )
            list.add(DataForSendToPrinter.printAndFeedLine())
            list.add(DataForSendToPrinter.printAndFeedLine())
            list.add(DataForSendToPrinter.printBothColumns("订单类型:", order.orderTypeStr))
            list.add(DataForSendToPrinter.printAndFeedLine())
            list.add(DataForSendToPrinter.printAndFeedLine())
            if (order.orderTypeStr.contains("预约")) {
                list.add(DataForSendToPrinter.printBothColumns("预约时间:", order.appointmentTime))
                list.add(DataForSendToPrinter.printAndFeedLine())
                list.add(DataForSendToPrinter.printAndFeedLine())
            }
            list.add(DataForSendToPrinter.printBothColumns("订单号:", order.orderCode))
            list.add(DataForSendToPrinter.printAndFeedLine())
            list.add(DataForSendToPrinter.printAndFeedLine())
            list.add(DataForSendToPrinter.printAndFeedLine())
            return list
        }

    })
}

至此,介绍了整个依赖的详细使用,由于篇幅原因,不能贴入全部代码,如果感兴趣,还是建议直接查看源码。

总结

以上仅是对工作的一种总结,我也将一直持续维护此项目,由于个人经验能力不足,可能还存在些许问题,如果你觉得不合理,欢迎留言讨论,或者直接提出你的建议,我直接将你的想法写进项目中。

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: Android蓝牙通信APP是一种用于在Android手机上实现蓝牙通信的应用程序。通过该应用程序,用户可以方便地与其他支持蓝牙功能的设备进行数据传输和通信。 Android蓝牙通信APP可以用于多种场景,比如蓝牙耳机、蓝牙音箱、蓝牙打印机等设备的连接和控制。用户可以通过该应用程序连接并配对这些蓝牙设备,并实现数据的传输和通话功能。此外,用户还可以通过该应用程序与其他手机或平板电脑进行蓝牙文件传输,快速共享照片、音乐、视频等多媒体文件。 Android蓝牙通信APP具有简单易用的用户界面,用户可以通过该界面进行设备的搜索和选择、配对、连接和断开连接等操作。同时,该应用程序还提供了简单的设置选项,用户可以根据自己的需求调整连接方式和传输速度等参数。 此外,Android蓝牙通信APP还支持多种蓝牙通信协议,比如串行端口协议(SPP)、对象交换协议(OBEX)等,用户可以根据实际需要选择合适的协议进行通信。同时,该应用程序还支持多种数据格式的传输,包括文本、图片、音频、视频等,用户可以根据实际需求选择合适的数据格式进行传输。 总之,Android蓝牙通信APP是一种方便实用的应用程序,通过它,用户可以轻松地实现与其他蓝牙设备的连接和通信,满足各种数据传输和通话的需求。 ### 回答2: Android蓝牙通信app是一种用于Android设备的应用程序,用于在不同设备之间进行蓝牙通信。通过蓝牙通信,用户可以实现文件传输、语音通话、数据同步等功能。 该app的主要功能包括: 1. 设备搜索和配对:用户可以使用该app搜索附近的蓝牙设备,并与选定的设备进行配对。配对后,设备之间可以建立蓝牙连接。 2. 文件传输:用户可以使用该app从一个设备向另一个设备发送文件。通过选择要发送的文件,并选择接收设备,用户可以快速实现文件共享。 3. 语音通话:用户可以使用该app与配对设备进行蓝牙语音通话。这对于在没有手机网络信号的地方或需要保持静音的环境中进行通话非常有用。 4. 数据同步:用户可以使用该app将设备之间的数据进行同步。例如,可以将联系人、日历等信息从一个设备传输到另一个设备。 该app还可以通过添加更多功能来扩展其功能,例如蓝牙打印、蓝牙键盘控制等。 总结来说,Android蓝牙通信app可以使用户在Android设备之间实现快速、便捷、安全的蓝牙通信,从而满足用户的不同需求。 ### 回答3: Android蓝牙通信app是一款在Android操作系统上运行的应用程序,用于实现设备间的蓝牙通信。蓝牙通信是一种无线通信技术,可以用于设备之间的数据传输和交互。 Android蓝牙通信app可以通过蓝牙模块与其他支持蓝牙协议的设备进行通信,如蓝牙耳机、蓝牙音箱、蓝牙打印机等。它具有以下功能和特点: 1. 连接设备:通过蓝牙搜索功能,找到附近的蓝牙设备并与其建立连接。这样,用户可以在Android设备上与其他设备进行数据传输和控制。 2. 发送和接收数据:Android蓝牙通信app可以发送任意类型的数据,如文本、图片、音乐等。同时,它也可以接收其他设备发送的数据,并进行处理和展示。 3. 文件传输:通过蓝牙通信app,用户可以将本地的文件发送给其他设备,也可以接收其他设备发送的文件。这样,用户可以方便地在设备间共享数据和文件。 4. 远程控制:Android蓝牙通信app还可以实现蓝牙设备的远程控制。例如,用户可以通过连接蓝牙耳机来控制音乐播放,或者通过连接蓝牙游戏手柄来进行游戏操作。 5. 简单易用:Android蓝牙通信app通常具有简洁直观的用户界面,用户可以轻松地完成各种操作,如连接设备、发送数据和文件,以及远程控制设备等。 总结来说,Android蓝牙通信app为用户提供了一种便捷的方式来实现设备间的蓝牙通信。通过它,用户可以方便地进行数据传输、文件共享和远程控制等操作,丰富了手机和其他蓝牙设备之间的互动方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值