androidkotlinandroid-serviceandroid-alertdialogandroid-service-binding

How to retrieve messages from a service in an AlertDialog Android Kotlin


I have implemented a barcode scanning program which grabs barcodes from a barcode scanning service. Within this program I occasionally open a dialog box with an editText field for additional information, I would like to know how I could get the service to send the barcode to this alertDialog.

When this alertDialog is closed the barcode should then be sent to the open activity again.

Here is how I Send/Retrieve the messages

class SomeActivity : AppCompatActivity() {

/* variables to communicate with scanning services */
    private var mService: Messenger? = null
    private var mBound: Boolean = false
    private val mMessenger: Messenger = Messenger(IncomingHandler(this))

/* service connection which binds to the scanning SDK for IPC */
    private val connection: ServiceConnection = object: ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            /* connect to service*/
            mService = Messenger(service)
            /* Register to the scanner */
            val msg: Message = Message.obtain(null, MSG_REGISTER)
            msg.replyTo = mMessenger
            mService?.send(msg)

        }

        override fun onServiceDisconnected(name: ComponentName?) {
            /* In the case of unexpected disconnection */
            mService = null
        }
    }

    /* Handles inbound IPC messages and figures out what to do with them */
    inner class IncomingHandler(
        context: Context
    ) : Handler() {
        override fun handleMessage(msg: Message){
            when(msg.what) {
                MSG_BARCODE ->{
                    val bcodeBundle = msg.data
                    val bcodeData = bcodeBundle.getString("barcode")
                    val bcodeType = bcodeBundle.getString("type")
                    barcodeScanned(bcodeData!!,bcodeType!!)
                }
                else ->
                    super.handleMessage(msg)
            }
        }
    }

elsewhere in the activity

Message crafting function

private fun getMsg(msgCode: Int) : Message{
        val msg: Message = Message.obtain(null, msgCode)
        msg.replyTo = mMessenger
        return msg
    }

Sending Message example

val newmsg: Message = Message.obtain(null, MSG_REBARCODE, 0, 0)
            val bundle = Bundle()
            bundle.putString("barcode",dialog.manualBarcode)
            bundle.putString("type","MANUAL")
            newmsg.data = bundle
            mService?.send(newmsg)

Binding to service

if (!mBound){
            mBound = bindScanner(this,versionSDK, connection)
            mBound = true
            mService?.send(getMsg(MSG_START))
        }

Unbinding

unbindService(connection)

The Custom AlertDialog calling within the activity

val dialog = CustomDialog(variousVariables...)
dialog.show()

how the custom dialog is created

class CustomDialog (val theContext: Context, other data...)
    : AlertDialog(theContext) {

init{
        requestWindowFeature(Window.FEATURE_NO_TITLE)
        setCancelable(false)
    }

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val window = this.window
        val display = theActivity.windowManager.defaultDisplay
        val size = Point()
        display.getSize(size)
        val width = size.x
        val height = size.y
        window?.setLayout(width,(height/96)*100)
        setContentView(R.layout.dialog_enter_additional_data)
        this.window?.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
        this.window?.clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM)
        this.window?.setSoftInputMode(
            WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN)

//Etc...
}

Solution

  • Figured it out

    From my Activity I pass the values of my messenger to my Dialog

    val dialog = CustomDialog(mService, mMessenger, variousVariables...)
    dialog.show()
    

    In my AlertDialog Class I created a new messenger Handle and apply it to a new messenger variable

    private val newMessenger: Messenger = Messenger(IncomingHandler())
    
    /* Handles inbound IPC messages and figures out what to do with them */
        inner class IncomingHandler(
        ) : Handler() {
            override fun handleMessage(msg: Message){
                when(msg.what) {
                    MSG_BARCODE ->{
                        val bcodeBundle = msg.data
                        val bcodeData = bcodeBundle.getString("barcode")
                        dataInput?.setText(bcodeData)
                        capturedData = bcodeData!!
                    }
                    else ->
                        super.handleMessage(msg)
                }
            }
        }
    

    I then register the new messenger to my service using the already built messenger

    override fun onCreate(savedInstanceState: Bundle?) {
    //Code...
    
    val msg: Message = Message.obtain(null, MSG_REGISTER)
            msg.replyTo = newMessenger
            mService?.send(msg)
    
    //Code...
    }
    

    Once I am done with my alertDialog (i.e. when it closes), I give the activity back it's messenger

    /* Somewhere in the code */
    val msg: Message = Message.obtain(null, MSG_REGISTER)
                msg1.replyTo = mMessenger
                service?.send(msg)