Android: 使用zxing扫描条码并返回片段中的结果

Android: Barcode scanning with zxing and returning result in fragment

我正在尝试在 Fragment 中使用 zxing 库。我可以让扫描仪工作并捕获条形码,但 activity 中的 onActivityResult 方法始终是 运行 而不是 Frament 中的 onActivityResult 方法。

我已经尝试了post中提到的不同解决方案,但没有成功。

这是我的代码 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");
    }
}

这是我尝试使用条形码的片段代码 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
    }

}

当我查看控制台时,我总是看到:代码被捕获。我不明白:从来没有在这里。

请注意,我在 barcodeScanner.forSupportFragment(AddLoanFragment.this).initiateScan(); 收到一条警告,提示静态成员 'com.google.zxing.integration.android.IntentIntegrator.forSupportFragment(androidx.fragment.app.Fragment)' 通过实例引用访问。我不确定这是什么意思,是否是问题所在。

我想我已经尝试了上面提到的 post 中提出的所有答案,但没有成功。

感谢您的帮助。

我找到问题所在了。当相机开始寻找条形码时,它会以横向模式启动。我想在纵向模式下使用扫描仪并旋转 phone 以重新启动 activity(并留下我的片段)。我通过以纵向模式启动相机解决了我的问题。为此,我在 AndroidManifest.xml 文件中添加了这段代码:

<activity
        android:name="com.journeyapps.barcodescanner.CaptureActivity"
        android:screenOrientation="portrait"
        tools:replace="screenOrientation" />

这是我的片段的代码:

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());
                }
            }
        }
    }

}

现在可以删除我 Activity 中的 OnActivityResult() 方法。