Search code examples
androidkotlinzebra-scanners

How to use Zebra EMDK in release build?


So I Have a Zebra MC330M device.

I created earliar an application, and I would like to use the PDA built in barcode scanner.

If is run my app in debug mode, everything working well, I can read the barcodes, but If I create an staged or relase version apk, the barcode reader inactive, so the red light doesn't light if I press the button.

I created a simple,to demonstrate the problem, but you can reproduce the problem if you device has EMDK, else you get an exception. Project

I implemented all of stuff by this tutorial: https://techdocs.zebra.com/emdk-for-android/11-0/tutorial/tutBasicScanningAPI

So I added this into gradle: compileOnly 'com.symbol:emdk:7.6.+' I added thease two lines to the manfest:

<uses-permission android:name="com.symbol.emdk.permission.EMDK" />
<uses-library android:name="com.symbol.emdk" android:required="false"/>

I tried to add the dependency with implementation instead of compileOnly , but after that I got an Exception in this line: EMDKManager.getEMDKManager(context,object : EMDKManager.EMDKListener...

[UPDATE] When I push the scanner button, I get this error:

E/ActivityManager: Sending non-protected broadcast com.symbol.button.R1 from system 1208:system/1000 pkg android
    java.lang.Throwable
        at com.android.server.am.ActivityManagerService.checkBroadcastFromSystem(ActivityManagerService.java:18150)
        at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:18728)
        at com.android.server.am.ActivityManagerService.broadcastIntent(ActivityManagerService.java:18819)
        at android.app.ContextImpl.sendBroadcastAsUser(ContextImpl.java:1040)
        at com.android.server.RemoteKeyEventService.broadcastPublicKeyIntent(RemoteKeyEventService.java:672)
        at com.android.server.RemoteKeyEventService.handleKeyEvent(RemoteKeyEventService.java:526)
        at com.android.server.wm.InputMonitor.interceptKeyBeforeQueueing(InputMonitor.java:464)
        at com.android.server.input.InputManagerService.interceptKeyBeforeQueueing(InputManagerService.java:1874)

My app is targeting API Level 30, and I put the permission inside the manifest.


I also tried to log the error, but there is no error, it seems the two listeners (status, and data) not triggered, or can not enable the scanner, but in this case I should get an error message. 

Barcode Reader Class:
class ZebraBarcodeReader(
    private val context: Context
){
    private var emdkManager: EMDKManager? = null
    private var barcodeManager: BarcodeManager? = null
    private val barcodeLiveData = MutableLiveData<EventWrapper<String?>>()

    init {
        val result = EMDKManager.getEMDKManager(context,object : EMDKManager.EMDKListener{

            override fun onOpened(p0: EMDKManager?) {
                opened(p0)
            }

            override fun onClosed() {
                closed()
            }
        })

        if(result.statusCode != EMDKResults.STATUS_CODE.SUCCESS) {
            Timber.d("$TIMBER_TAG ZebraBarcodeReader failed to connect")
        }else{
            Timber.d("$TIMBER_TAG EMDKManager object initialization in progress...")
        }
    }

    fun getData(): LiveData<EventWrapper<String?>> = barcodeLiveData

    private fun opened(manager: EMDKManager?){
        emdkManager = manager

        initBarcodeManager()
        initScanner()
    }

    private var scanner: Scanner? = null

    private fun initScanner() {
        scanner = barcodeManager?.getDevice(BarcodeManager.DeviceIdentifier.DEFAULT)

        if(scanner == null){
            Timber.d("$TIMBER_TAG Scanner not found")
        }else{
            scanner?.addDataListener {scanDataCollection->
                if(scanDataCollection != null && (scanDataCollection.result) == ScannerResults.SUCCESS){
                    val scanData = scanDataCollection.scanData

                    scanData.forEach {
                        val barcode = it.data

                        barcodeLiveData.postValue(EventWrapper(barcode))
                    }
                }
            }

            scanner?.addStatusListener { statusData->
                val state = statusData.state
                var statusString = ""

                when(state){
                    StatusData.ScannerStates.IDLE-> {
                        statusString = statusData.friendlyName + "is enabled and IDLE"
                        setConfig()

                        try {
                            scanner?.read()
                        }catch (e: ScannerException){
                            Timber.d(e)
                        }
                    }

                    StatusData.ScannerStates.WAITING-> {
                        statusString = "Scanner is waiting for trigger press"
                    }

                    StatusData.ScannerStates.SCANNING-> {
                        statusString = "Scanning"
                    }

                    StatusData.ScannerStates.DISABLED-> {
                        statusString = "Scanner is disabled"
                    }

                    StatusData.ScannerStates.ERROR-> {
                        statusString="An error occured"
                    }

                    else -> {
                        statusString="Another thing in else branch"
                    }
                }

                Timber.d("$TIMBER_TAG $statusString")
            }

            try {
                scanner?.enable()
            } catch (e: ScannerException) {
                Timber.d("$TIMBER_TAG Scanner can not be enabled")
            }
        }
    }

    private fun setConfig() {
        scanner?.let { s->
            try {
                val config = s.config

                if(config.isParamSupported("config.scanParams.decodeHapticFeedback"))
                    config.scanParams.decodeHapticFeedback = true

                s.config = config
            }catch (e: Exception){
                Timber.d(e)
            }
        }
    }

    private fun initBarcodeManager() {
        barcodeManager = emdkManager?.getInstance(EMDKManager.FEATURE_TYPE.BARCODE) as BarcodeManager?

        if(barcodeManager == null){
            Timber.d("$TIMBER_TAG Barcode scanning not supported")
        }
    }

    private fun closed(){
        emdkManager?.let { m->
            m.release()
            emdkManager = null
        }

        Timber.d("$TIMBER_TAG : closed unexpectedly!")
    }

    fun destroy(){
        emdkManager?.let { m->
            m.release()
            emdkManager = null
        }
    }


Solution

  • Little bit weird for me, but I solved this problem.

    I don't know why, but firstly I installed a debug version of my apk, after that I deleted it, and then I installed the staged/release version. I didn't work.

    After that when I deleted the debug version, I restarted the device, and then installed release version, and it is works. I don't no why it was necessary, but I'm happy.