zxing onActivityResult not called in Fragment only in Activity
Asked Answered
C

10

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

}
Comstockery answered 16/11, 2013 at 0:48 Comment(1)
Use Integrator.forSupportFragment(this) or Integrator.forFragment(this) depending on which Fragment you are using.Commence
C
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
}

}
Comstockery answered 17/11, 2013 at 16:10 Comment(3)
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.Ineducation
Get more about manipulating fragments and how they actually work from Google's documentation (developer.android.com/guide/components/fragments.html)Ineducation
Why you did not use previous anser. It's more elegant desision)Kafiristan
T
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);
    }
}
Tralee answered 11/3, 2014 at 8:25 Comment(3)
But how do you use this class?Kelikeligot
@PhilippLudwig just replace IntentIntegrator integrator = new IntentIntegrator(MyActivity.this); with FragmentIntentIntegrator integrator = new FragmentIntentIntegrator(MyFragment.this);Riverine
Use Integrator.forSupportFragment(this) or Integrator.forFragment(this) depending on which Fragment you are using.Commence
M
14
integrator.initiateScan();

Change the above line as

integrator.forSupportFragment(fragment_name.this).initiateScan();
Mabuse answered 8/11, 2017 at 16:12 Comment(2)
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 scannedRichmound
@Richmound 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.Religion
H
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

Howlond answered 12/7, 2015 at 15:31 Comment(0)
C
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
}

}
Comstockery answered 17/11, 2013 at 16:10 Comment(3)
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.Ineducation
Get more about manipulating fragments and how they actually work from Google's documentation (developer.android.com/guide/components/fragments.html)Ineducation
Why you did not use previous anser. It's more elegant desision)Kafiristan
S
3

I had this problem and resolved it with below codes:

IntentIntegrator integrator = new IntentIntegrator(getActivity());                
integrator.forSupportFragment(MyFragment.this).initiateScan();
Sophister answered 11/2, 2019 at 8:42 Comment(0)
J
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

Judas answered 14/5, 2019 at 8:13 Comment(0)
H
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.

Hydroxy answered 16/11, 2013 at 1:20 Comment(1)
Well I did solve the problem, by replacing the fragment. Here is the solution: androide-examples.blogspot.com/2013/11/…Comstockery
L
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()
Laminous answered 10/12, 2018 at 5:56 Comment(0)
P
1
public void scanCode() {
        IntentIntegrator.forSupportFragment(this).
        setCaptureActivity(CaptureAct.class).
        setOrientationLocked(false)
        .setDesiredBarcodeFormats(IntentIntegrator.PRODUCT_CODE_TYPES)
        .setPrompt("Scanning code")
        .initiateScan();
    }
Proliferation answered 18/7, 2020 at 19:32 Comment(0)
K
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) {
 }
Knowing answered 2/7, 2015 at 10:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.