19

I'm having some issue with zxing onActivityResult().

As you can see in the code I did properly invoke new intent as described in https://code.google.com/p/zxing/wiki/ScanningViaIntent.

The question is how can I catch onActivityResult() in Fragment, since I need this data in my Fragmnet and not in Activity?

package com.example.testingcodereading;

import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

public class MainFragment extends Fragment {

private Button mButtonXZing;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle     savedInstanceState){
    View v = inflater.inflate(R.layout.fragment_main, parent, false);

    mButtonXZing = (Button) v.findViewById(R.id.button_xzing);
    mButtonXZing.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            IntentIntegrator integrator = new IntentIntegrator(getActivity());
            integrator.initiateScan();

        }
    });

    return v;
}


@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
    }

}

public class MainActivity extends FragmentActivity {

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

FragmentManager fm = getSupportFragmentManager();
Fragment f = fm.findFragmentById(R.id.fragmentContainer);

if(f == null){
  f = new MainFragment();
  fm.beginTransaction()
    .add(R.id.fragmentContainer, f)
    .commit();
}
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);
    System.out.println("the code is catch");
}

}
5er
  • 2,506
  • 7
  • 32
  • 49
  • Use `Integrator.forSupportFragment(this)` or `Integrator.forFragment(this)` depending on which `Fragment` you are using. – NecipAllef May 23 '18 at 21:18

10 Answers10

36

As Martynnw pointed out the issue is to call fragment.startActivityForResult instead of activity.startActivityForResult. So just use next wrapper:

import android.content.Intent;
import android.support.v4.app.Fragment;

import com.google.zxing.integration.android.IntentIntegrator;

public final class FragmentIntentIntegrator extends IntentIntegrator {

    private final Fragment fragment;

    public FragmentIntentIntegrator(Fragment fragment) {
        super(fragment.getActivity());
        this.fragment = fragment;
    }

    @Override
    protected void startActivityForResult(Intent intent, int code) {
        fragment.startActivityForResult(intent, code);
    }
}
Sergii Pechenizkyi
  • 22,227
  • 7
  • 60
  • 71
14
integrator.initiateScan();

Change the above line as

integrator.forSupportFragment(fragment_name.this).initiateScan();
AskNilesh
  • 67,701
  • 16
  • 123
  • 163
Eldho Shaji
  • 547
  • 5
  • 8
  • 3
    I've tried using this in a fragment. It's able to display the QR camera, however, onActivityResult is not called when a code is scanned – user1872384 Nov 28 '18 at 04:06
  • @user1872384 I had the same problem until I realized that the scanner was starting in landscape mode and I was rotating the phone which was restarting the activity. It works for me if you don't rotate the phone. I ended up setting the camera in portrait mode to avoid that. – sims Mar 10 '20 at 12:27
4

Alternative ZXing Android Embedded, implementation:

import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    new IntentIntegrator(this).initiateScan(); // `this` is the current Activity

}

Use from a Fragment:

IntentIntegrator.forFragment(this).initiateScan(); // `this` is the current Fragment

// If you're using the support library, use: 
// IntentIntegrator.forSupportFragment(this) instead.

Get the results:

@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(this, "Cancelled", Toast.LENGTH_LONG).show();
        } else {
        Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
    }
    } else {
        super.onActivityResult(requestCode, resultCode, data);
    }
}

more info and options

Hpsaturn
  • 2,702
  • 31
  • 38
3

If any one have the same issue here is my solution.

package com.example.testingcodereading;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;

public class MainActivity extends FragmentActivity {

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

FragmentManager fm = getSupportFragmentManager();
Fragment f = fm.findFragmentById(R.id.fragmentContainer);

if (f == null) {
  f = MainFragment.newInstance("Start Application");
  fm.beginTransaction().add(R.id.fragmentContainer, f).commit();
}
}

@Override
protected void onActivityResult(int requestCode, int resultCode,
  Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
System.out.println("the code is catch");

IntentResult scanResult = IntentIntegrator.parseActivityResult(
    requestCode, resultCode, intent);
// handle scan result
if (scanResult != null) {
  FragmentManager fm = getSupportFragmentManager();

  Fragment newFrame = MainFragment.newInstance(scanResult.toString());

  fm.beginTransaction().replace(R.id.fragmentContainer, newFrame).commit();
}

}

}

package com.example.testingcodereading;

import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.test.suitebuilder.annotation.MediumTest;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

public class MainFragment extends Fragment {

private static final String EXTRA_CODE = "com.example.testingcodereading.code";
private Button mButtonXZing;
private TextView mTextView;


public static MainFragment newInstance(String code) {
Bundle args = new Bundle();
args.putSerializable(EXTRA_CODE, code);

MainFragment fragment = new MainFragment();
fragment.setArguments(args);

return fragment;
}


@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle    savedInstanceState){
View v = inflater.inflate(R.layout.fragment_main, parent, false);

mTextView = (TextView) v.findViewById(R.id.text_code);
mTextView.setText((String) getArguments().getSerializable(EXTRA_CODE));

mButtonXZing = (Button) v.findViewById(R.id.button_xzing);
mButtonXZing.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {

    IntentIntegrator integrator = new IntentIntegrator(getActivity());
    integrator.initiateScan();
  }
});

return v;
}


@Override 
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, 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
}

}
5er
  • 2,506
  • 7
  • 32
  • 49
  • 1
    Good enough. One thing to watch for is the context since the context used by a fragment is inherited from the parent Activity hosting the fragment then once the fragment is instantiated, it takes on this context and works in it's own space. – Akah Mar 30 '16 at 12:08
  • 1
    Get more about manipulating fragments and how they actually work from Google's documentation (http://developer.android.com/guide/components/fragments.html) – Akah Mar 30 '16 at 12:10
  • Why you did not use previous anser. It's more elegant desision) – Denis Makovsky Oct 20 '17 at 09:39
3

I had this problem and resolved it with below codes:

IntentIntegrator integrator = new IntentIntegrator(getActivity());                
integrator.forSupportFragment(MyFragment.this).initiateScan();
2

Shall call the scan in this way:

IntentIntegrator.forSupportFragment(YourFragment.this)
                    .setDesiredBarcodeFormats(IntentIntegrator.QR_CODE)
                    .setBeepEnabled(true/false)
                    .setPrompt("blahblahblah")
                    .initiateScan();

Then you can get the scan result in Fragment's onActivityResult

Amos
  • 2,222
  • 1
  • 26
  • 42
1

Make sure OnActivityResult in your Activity is calling super.OnActivityResult(). That should ensure it's called on the Fragment as well.

Alternatively, you could modify the IntentIntegrator code so it calls StartActivityResult on the Fragment, either by passing the fragment to the constructor, or passing it to initiateScan.

Ragunath Jawahar
  • 19,513
  • 22
  • 110
  • 155
Martynnw
  • 10,625
  • 5
  • 28
  • 27
  • Well I did solve the problem, by replacing the fragment. Here is the solution: http://androide-examples.blogspot.com/2013/11/zxing-onactivityresult-called-only-in.html – 5er Nov 16 '13 at 02:51
1

Try creating IntentIntegrator object in Fragment as below.

        val scanIntegrator = IntentIntegrator.forSupportFragment(this@HomeFragment)
        scanIntegrator.setPrompt("Scan")
        scanIntegrator.setBeepEnabled(true)
        //The following line if you want QR code
        scanIntegrator.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE_TYPES)
        scanIntegrator.captureActivity = CaptureActivityAnyOrientation::class.java
        scanIntegrator.setOrientationLocked(true)
        scanIntegrator.setBarcodeImageEnabled(true)
        scanIntegrator.initiateScan()
Dipali Shah
  • 3,742
  • 32
  • 47
1
public void scanCode() {
        IntentIntegrator.forSupportFragment(this).
        setCaptureActivity(CaptureAct.class).
        setOrientationLocked(false)
        .setDesiredBarcodeFormats(IntentIntegrator.PRODUCT_CODE_TYPES)
        .setPrompt("Scanning code")
        .initiateScan();
    }
0

A solution : A basic example of how you can manage it

Main Activity

public static int tapTrick = 0;

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    //super.onActivityResult(requestCode, resultCode, data);
    if(tapTrick!=0 && tapTrick==1) {
        Tab1.onActivityResult(requestCode, resultCode, data, MainActivity.this);
    }else if (tapTrick!=0 && tapTrick==2){
        //Tab2.onActivityResult(requestCode, resultCode, data, MainActivity.this);
    }
}

Fragment 1

MainActivity.tapTrick=1; // onCreateView  or onClick (load images/files)

 public static void onActivityResult(int requestCode, int resultCode, Intent intent, Context context) {
 }

Fragment 2

MainActivity.tapTrick=2;
 public static void onActivityResult(int requestCode, int resultCode, Intent intent, Context context) {
 }

Fragment x

MainActivity.tapTrick=x;
 public static void onActivityResult(int requestCode, int resultCode, Intent intent, Context context) {
 }