I'm trying to use the zxing library inside a Fragment. I can get the scanner to work and capture a barcode but the onActivityResult method in the activity is always ran instead of the onActivityResult method in the Frament.
I've tried the different solutions mentionned in this post but with no success.
This the code of my activity:
package com.test01.test01_tp2;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import android.content.Intent;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import com.google.android.material.navigation.NavigationView;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
public class MainActivityLibrarian extends AppCompatActivity {
DrawerLayout drawerLayout;
String name;
TextView tvName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_librarian);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
drawerLayout = findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close);
drawerLayout.addDrawerListener(toggle);
toggle.syncState();
NavigationView nav_view = findViewById(R.id.nav_view);
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,new HomeLibrarianFragment()).commit();
//Get the username and update the name in the drawer
name = getIntent().getStringExtra("name");
View headerView = nav_view.getHeaderView(0);
tvName = headerView.findViewById(R.id.txtNameHeader);
tvName.setText(name);
nav_view.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
switch(menuItem.getItemId())
{
case R.id.nav_add_loan:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,new AddLoanFragment()).commit();
break;
case R.id.nav_list_loans:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ListLoansFragment()).commit();
break;
case R.id.nav_add_readers:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AddReadersFragment()).commit();
break;
case R.id.nav_list_readers:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ListReadersFragment()).commit();
break;
case R.id.nav_add_books:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new AddBooksFragment()).commit();
break;
case R.id.nav_list_books:
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ListBooksFragment()).commit();
break;
/*case R.id.close:
finish();
break;*/
}
drawerLayout.closeDrawer(GravityCompat.START);
return true;
}
});
}
@Override
public void onBackPressed() {
if(drawerLayout.isDrawerOpen(GravityCompat.START))
drawerLayout.closeDrawer(GravityCompat.START);
else
super.onBackPressed();
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
System.out.println("the code is catch");
}
}
And this is the code of my fragment where I'm trying to use the barcode reader:
package com.test01.test01_tp2;
import android.content.Intent;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
/**
* A simple {@link Fragment} subclass.
*/
public class AddLoanFragment extends Fragment {
//View Objects
private Button btnAdd, btnClear;
private EditText etBarcodeReader, etBarcodeBook;
private ImageButton imBtnBarcodeBook, imBtnBarcodeReader;
//barcode scanner Object
private IntentIntegrator barcodeScanner;
public AddLoanFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_add_loan, container, false);
//View Objects
btnAdd = root.findViewById(R.id.btn_add);
btnClear = root.findViewById(R.id.btn_clear);
imBtnBarcodeBook = root.findViewById(R.id.imageButtonBarcodeBook);
imBtnBarcodeReader = root.findViewById(R.id.imageButtonBarcodeReader);
etBarcodeBook = root.findViewById(R.id.editTextBookBarcode);
etBarcodeReader = root.findViewById(R.id.editTextReaderBarcode);
imBtnBarcodeReader.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
barcodeScanner = new IntentIntegrator(getActivity());
barcodeScanner.forSupportFragment(AddLoanFragment.this).initiateScan();
}
});
// Inflate the layout for this fragment
return root;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
System.out.println("never here");
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
if (scanResult != null) {
// handle scan result
}
// else continue with any other code you need in the method
}
}
When I look at the console I always see : the code is catch. And I don't get: never here.
It may be useful to note that I'm getting a warning at barcodeScanner.forSupportFragment(AddLoanFragment.this).initiateScan();
saying Static member 'com.google.zxing.integration.android.IntentIntegrator.forSupportFragment(androidx.fragment.app.Fragment)' accessed via instance reference. I'm not sure what it means and if that's the problem.
I think I've tried all the answers proposed in the upper-mentionned post with no success.
Thanks for your help.
I found what the problem was. When the camera starts to look for a barcode it starts in landscape mode. I wanted to use the scanner in portrait mode and rotated the phone which was restarting the activity (and leaving my fragment). I fixed my problem by starting the camera in portrait mode. To do that, I added this code in my AndroidManifest.xml file :
<activity
android:name="com.journeyapps.barcodescanner.CaptureActivity"
android:screenOrientation="portrait"
tools:replace="screenOrientation" />
And this is the code of my fragment:
package com.test01.test01;
import android.content.Intent;
import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Toast;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
/**
* A simple {@link Fragment} subclass.
*/
public class AddLoanFragment extends Fragment {
private int mode;
//View Objects
private Button btnAdd, btnClear;
private EditText etBarcodeReader, etBarcodeBook;
private ImageButton imBtnBarcodeBook, imBtnBarcodeReader;
public AddLoanFragment() {
// Required empty public constructor
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_add_loan, container, false);
//View Objects
btnAdd = root.findViewById(R.id.btn_add);
btnClear = root.findViewById(R.id.btn_clear);
imBtnBarcodeBook = root.findViewById(R.id.imageButtonBarcodeBook);
imBtnBarcodeReader = root.findViewById(R.id.imageButtonBarcodeReader);
etBarcodeBook = root.findViewById(R.id.editTextBookBarcode);
etBarcodeReader = root.findViewById(R.id.editTextReaderBarcode);
imBtnBarcodeReader.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mode = 1;
scanFromFragment();
}
});
imBtnBarcodeBook.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mode = 2;
scanFromFragment();
}
});
// Inflate the layout for this fragment
return root;
}
public void scanFromFragment() {
IntentIntegrator.forSupportFragment(this).initiateScan();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (result != null) {
if (result.getContents() == null) {
Toast.makeText(getContext(),"Cancelled from fragment", Toast.LENGTH_LONG).show();
} else {
if (mode == 1) {
etBarcodeReader.setText(result.getContents());
} else if (mode == 2) {
etBarcodeBook.setText(result.getContents());
}
}
}
}
}
And the OnActivityResult() method in my Activity can now be deleted.