-1

I have a problem with barcode scanner on android. I tried to build an app, where is a button, which runs new activity, scans a code and then goes back to MainActivity with scanned code. But...

This is code of MainActivity:

import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.MenuItem;

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
    private DrawerLayout drawer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        drawer = findViewById(R.id.drawer_layout);

        NavigationView navigationView = findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);

        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ScanFragment()).commit();
            navigationView.setCheckedItem(R.id.nav_scan);
        }
    }

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
        switch (menuItem.getItemId()) {
            case R.id.nav_scan:
                getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ScanFragment()).commit();
                break;
            case R.id.nav_okruh:
                getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new OkruhFragment()).commit();
                break;
            case R.id.nav_kzavozu:
                getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new KZavozuFragment()).commit();
                break;
            case R.id.nav_zprava:
                getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new ZpravaFragment()).commit();
                break;
        }
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    @Override
    public void onBackPressed() {
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }
}

It is drawer layout with fragments. Every fragment is used for another action and in first one, there is a button:

import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import com.google.android.gms.vision.barcode.BarcodeDetector;

import static com.google.android.gms.vision.barcode.Barcode.ALL_FORMATS;

public class ScanFragment extends Fragment {

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_scan, container, false);
        Button button = (Button) view.findViewById(R.id.button2);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getActivity(), ScanOkno.class);
                startActivity(intent);
            }
        });
        return view;
    }
}

And here is the Activity for scanner, in code named ScanOkno.class:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.SparseArray;
import android.widget.Toast;

import com.google.android.gms.vision.barcode.Barcode;

import java.util.List;

import info.androidhive.barcode.BarcodeReader;

public class ScanOkno extends AppCompatActivity implements BarcodeReader.BarcodeReaderListener {

    private BarcodeReader barcodeReader;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scan_okno);
        barcodeReader = (BarcodeReader) getSupportFragmentManager().findFragmentById(R.id.barcode_fragment);
    }

    @Override
    public void onScanned(Barcode barcode) {
        // play beep sound
        barcodeReader.playBeep();
        barcodeReader.pauseScanning();
        finish();
    }

    @Override
    public void onScannedMultiple(List<Barcode> list) {

    }

    @Override
    public void onBitmapScanned(SparseArray<Barcode> sparseArray) {

    }

    @Override
    public void onScanError(String s) {

    }

    @Override
    public void onCameraPermissionDenied() {
        Toast.makeText(getApplicationContext(), "Camera permission denied!", Toast.LENGTH_LONG).show();
    }
}

My problem is with finish(); function in onScanned() part of code, because it won't close an activity ScanOkno. Window is showing frames around codes and if scanned, it beeps once, than I paused scanning and I wanted to end activity, but I can't find, why it don't want to close and go back to MainActivity.

Also I don't know, how to transfer scanned code to main activity, but I think, that is possible to use maybe global variable like: final code = barcode.rawValue;

Thanks for any reply.

mariuss
  • 1,177
  • 2
  • 14
  • 30
M. Cahyna
  • 40
  • 1
  • 8

2 Answers2

0

Not enough rep to comment, but is this method called on the main thread?

@Override
public void onScanned(Barcode barcode) {
    // play beep sound
    barcodeReader.playBeep();
    barcodeReader.pauseScanning();
    finish();
}

It's possible finish() is ignored if fired from a background thread (I can't seem to find any documentation specifying what happens if it's called from elsewhere though.)

-1

Update

Thanks for correcting me @Gabe Sechan

From you MainActivity call ScanOkno to startActivityForResult:

startActivityForResult(ScanOkno.class, REQUEST_CODE);

And to send the result back to MainActivity:

Intent resultIntent = new Intent();
// passing data back to result
resultIntent.putExtra("code", "some_string");
setResult(Activity.RESULT_OK, resultIntent);
finish();

and to receive the result:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {
        String code = data.getStringExtra("code");
    } 
}
Rodrigo Queiroz
  • 2,674
  • 24
  • 30
  • Thanks for fast and nice reply. I am very happy, that it works. Can I ask you for some advice, how to solve reply of scanned string? I found something here: https://stackoverflow.com/questions/1944656/android-global-variable , but maybe you see a better or easier way. – M. Cahyna Oct 17 '18 at 20:17
  • [@M.Cahyna](https://stackoverflow.com/users/9924942/m-cahyna) I'm guessing you want to pass the scanned string back to the `MainActivity`? For that, you can add an extra parameter to the `Intent` e.g `intent.putExtra("code", "some_string");` and then on the `MainActivity` you can grab that value with `String code = getIntent().getStringExtra("code");`. – Rodrigo Queiroz Oct 17 '18 at 20:24
  • So I finaly used `startActivityForResult()` and `public void onActivityResult` functions, but thanks for an idea. :-) – M. Cahyna Oct 17 '18 at 21:25
  • 1
    @RodrigoQueiroz This answer is wrong. You do not need to set any flag to go back to the previous activity. YOu're actually launching a new activity rather than going back. Finish does that for you. In addition, the right way to return a restult is to use startActivityForResult() and set the result in the activity that generates it. – Gabe Sechan Oct 17 '18 at 21:27