0

I'm currently developing a scanner app which uses the Zebra SDK.
In the samples and documentations that I found, an onTouchListener creates a new Intent (the scan) and broadcasts it. In the overridden onNewIntent method, the intent gets decoded and the scanned values are returned.

This all works great as long as I use 1 activity and no fragments, but for the app I'm creating I would like to have 1 activity and multiple fragments. At the moment everything happens in 1 activity (and one view), but this is getting a bit cluttered and isn't the ideal way to do things, so I would split up the activity eventually.

I tried creating the fragments and pass the data between them using safeargs. but I couldn't figure out how to start the intent and capture the result from within the fragments. I tried adding an onTouchListener in my fragment, which

Below is the current code in the activity. I don't have any fragments because all my attempts failed so far.

 override fun onTouch(view: View?, motionEvent: MotionEvent?): Boolean {
        if (view?.getId() == R.id.btnScanner) {
            if (motionEvent?.getAction() == MotionEvent.ACTION_DOWN) {
                //  Button pressed, start scan
                val dwIntent = Intent()
                dwIntent.action = "com.symbol.datawedge.api.ACTION"
                dwIntent.putExtra("com.symbol.datawedge.api.SOFT_SCAN_TRIGGER", "START_SCANNING")
                dwIntent.putExtra("Type", "START")
                sendBroadcast(dwIntent)
            } else if (motionEvent?.getAction() == MotionEvent.ACTION_UP) {
                //  Button released, end scan
                val dwIntent = Intent()
                dwIntent.action = "com.symbol.datawedge.api.ACTION"
                dwIntent.putExtra("com.symbol.datawedge.api.SOFT_SCAN_TRIGGER", "STOP_SCANNING")
                dwIntent.putExtra("Type", "END")
                sendBroadcast(dwIntent)
            }
        }
        return true
    }

 override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        if (intent.getStringExtra("Type") != "START") {
           //This would be for the first fragment
            if (personId.text.toString().isEmpty()) {
                val id = decodeScan((intent))
                personId.text = id
                lockId()
            } else {
              //This would be in the second fragment, after the user signed in by scanning his personal barcode
                if (productId.hasFocus() || productId.text.isEmpty()) {
                    val res = decodeScan(intent)
                    productId.text = res
                } else if (locationId.hasFocus() || (locationId.text.isEmpty() && productId.text.isNotEmpty())) {
                    val res = decodeScan(intent)
                    val location = (locations.filter { x -> x.contains(res) }).first()
                    locationId.setText(location)
                }
            }
        }
    }
Cevdam
  • 43
  • 1
  • 6

2 Answers2

1

onNewIntent is only available in the Activity, so you need to make the intent available to the fragments.

To do that, you can use MutableLiveData and ViewModel.

class MyViewModel: ViewModel() {
    val intent = MutableLiveData<Intent?>() 
}

Then

class MyActivity: AppCompatActivity() {
    private val  myViewModel by viewModels<MyViewModel>() 
    
    override fun onCreate( savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.my_activity)
        val myViewModel = myViewModel
        myViewModel.intent = intent
    }

    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        myViewModel.intent = intent
    } 
}

And

class MyFragment: Fragment() {
    private val MyViewModel by activityViewModels<MyViewModel>() 

    ... 
}

And you can observe the current intent in onCreate using this for lifecycle owner.

EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
0

Method onNewIntent belongs to Activity so you cannot use it in your fragment. What you can do is, pass the data to your fragment when it call in onNewIntent provided, you have the reference to the fragment.

var fragment; //assign default value to fragment

override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
// you can add fragment based checks in this method                                       
   to work as you want
 if (fragment is YourFragment) {

    if (intent.getStringExtra("Type") != "START") {
       //This would be for the first fragment
        if (personId.text.toString().isEmpty()) {
            val id = decodeScan((intent))
            personId.text = id
            lockId()
        }
     }
    }else if (fragment is YourSecondFragment) {{
            if (productId.hasFocus() || productId.text.isEmpty()) {
                val res = decodeScan(intent)
                productId.text = res
            } else if (locationId.hasFocus() || (locationId.text.isEmpty() && 
               productId.text.isNotEmpty())) {
                val res = decodeScan(intent)
                val location = (locations.filter { x -> x.contains(res) }).first()
                locationId.setText(location)
            }
        }
    }
}
Priyanka
  • 1,791
  • 1
  • 7
  • 12