Using Android Studio Kotlin, I'm using Zxing barcode scanner in my app. My app uses the fragment architecture. I am able to scan the barcode from my app from the fragment, but the scan result is returned to the activity. I believe intentionally since the signature requires the activity as input.
My question is, a) how can I get the scanned return value from the fragment call to execute onActivityResult in the fragment rather than in the activity? OR b) get the result received by the activity to be passed back to the fragment?
I'm using the following tutorial Barcode Scanning in Kotlin
The following java based post says to override the function, but that doesn't seem to actuall override the parent as the scanner function signature seems to refer to the activity.
I changed the code to use a nav_graph. Without using the nav_graph, I was getting a fragment not found
warning.
Log.d results showing the MainActivity function is called.
barcoderead D/MainActivity: Format: UPC_A
Contents: 630509790043
Manifest addition
<uses-feature android:name="android.hardware.camera.autoFocus" />
<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
build.gradle (app) addition
implementation 'com.google.zxing:core:3.3.3'
implementation 'com.journeyapps:zxing-android-embedded:3.2.0'
MainActivity
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.Navigation
import com.google.android.gms.ads.MobileAds
import com.google.zxing.integration.android.IntentIntegrator
import com.lightningbraingames.mytoybox.R
class MainActivity : AppCompatActivity() {
lateinit var btnBarcode: Button
lateinit var textView: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Navigation.findNavController(this,
R.id.nav_host_fragment
)
}
}
Fragment
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.fragment.app.Fragment
import com.google.zxing.integration.android.IntentIntegrator
class BarcodeRead : Fragment() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_barcode_read, container, false)
}
lateinit var btnBarcode: Button
lateinit var textView: TextView
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
btnBarcode = view.findViewById(R.id.button)
textView = view.findViewById(R.id.txtContent)
btnBarcode.setOnClickListener {
val intentIntegrator = IntentIntegrator(activity)
intentIntegrator.setBeepEnabled(false)
intentIntegrator.setCameraId(0)
intentIntegrator.setPrompt("SCAN")
intentIntegrator.setBarcodeImageEnabled(false)
intentIntegrator.initiateScan()
}
}
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
) {
val result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data)
if (result != null) {
if (result.contents == null) {
Toast.makeText(context, "cancelled", Toast.LENGTH_SHORT).show()
} else {
Log.d("Fragment", "Scanned from Fragment")
Toast.makeText(context, "Scanned -> " + result.contents, Toast.LENGTH_SHORT)
.show()
textView.text = String.format("Scanned Result: %s", result)
Log.d("Fragment", "$result")
}
} else {
super.onActivityResult(requestCode, resultCode, data)
}
}
}
Layouts Main Activity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:elevation="4dp"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"
app:navGraph="@navigation/nav_graph"/>
</LinearLayout>
Fragment
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/relativeLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="4dp">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="50dp"
android:padding="8dp"
android:text="Tutorials Point"
android:textColor="@android:color/holo_green_dark"
android:textSize="48sp"
android:textStyle="bold" />
<TextView
android:id="@+id/txtContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/button"
android:layout_centerInParent="true"
android:layout_marginBottom="10dp"
android:text=" code reader"
android:textSize="16sp"
android:textStyle="bold" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginTop="50dp"
android:text="Process" />
</RelativeLayout>
If your problem is that your fragment does not get the results, maybe you are missing something from your Fragment based from ZXing Documentation:
From you Activity it should
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
}
From you fragment BarcodeRead
//val intentIntegrator = IntentIntegrator(activity)
val intentIntegrator = IntentIntegrator.forSupportFragment(this) // use this instead
It is important to use IntentIntegrator.forSupportFragment()
instead of IntentIntegrator(getActivity())
because if you use the latter, the results will be available only in the activity page.