IntentIntegrator with android.support.v4.Fragment calls wrong onActivityResult

2,062 views
Skip to first unread message

Hartmut

unread,
Jan 6, 2012, 10:46:31 AM1/6/12
to zx...@googlegroups.com
Hi,
I am having a small issue when calling zxing on android with the IntentIntegrator from a Fragment.

In the process of converting a number of 'old' Activities to Fragments arranged in a FragmentTabsPager (which extends FragmentActivity from  android-support-v4), onActivityResult is called in the FragmentTabsPager, instead of in the Fragment that called initiateScan:

In the MyFragment, I do this:

                IntentIntegrator ii = new IntentIntegrator( getActivity() );
                ii.initiateScan( IntentIntegrator.QR_CODE_TYPES );

subsequently, IntentIntegrator calls

    activity.startActivityForResult(intentScan, REQUEST_CODE);


Because the activity (of the fragment) is called, the result is delivered to  FragmentTabsPager.onActivityResult(), and not MyFragment.onActivityResult().
(when calling startActivityForResult() in MyFragment, its super actually calls startActivityFromFragment(this...)).

A simple Fix I applied (thanks to making IntentIntegrator final I could not do this in a subclass)

import android.support.v4.app.Fragment;
....
  private Fragment fragment;
  public IntentIntegrator(Fragment fragment) {
    this(fragment.getActivity());
    this.fragment = fragment;
  }
...
  public AlertDialog initiateScan(Collection<String> desiredBarcodeFormats) {
...
    if(fragment==null) {
        activity.startActivityForResult(intentScan, REQUEST_CODE);
    }
    else {
        fragment.startActivityForResult(intentScan, REQUEST_CODE);
    }
    return null;
  }

This fix 'requires' android-support-v4 to be in the path, which is not ideal, and does not work for Apps that use android.app.Fragment...
This could perhaps be soved with 2 IntentIntegrator's:

IntentIntegrator implements the modification it with a android.app.Fragment
IntentIntegratorSupport extends IntentIntegrator implements it with the additional Fragment from android.support.v4.app

Or am I making some more fundamental mistake, here?

/Hartmut

Sean Owen

unread,
Jan 6, 2012, 11:58:43 AM1/6/12
to zx...@googlegroups.com
Why is it a problem to return the result to your Activity -- the Fragment can access it, right?

Hartmut

unread,
Jan 9, 2012, 2:58:39 AM1/9/12
to zx...@googlegroups.com
It is an problem (or perhaps better an inconvenience) because
  • it is unexpected behavior (at least to me),
If you callactivity.startActivityForResult(intentScan, REQUEST_CODE) in the Fragment yourself, the result is delivered to the Fragment, if I call the IntentIntegrator, the result ends up in the activity.
  • it distributes result processing (part in the Fragment, part in the Activity), and
  • I do not want the fragment to access the activity (separation of concerns, not binding F to A, etc.).

Lachezar Dobrev

unread,
Jan 9, 2012, 8:30:14 AM1/9/12
to zx...@googlegroups.com
I can see why this may be a problem.
I took a stab at the problem by replacing Activity references with a
mediator class that has an implementation for Activity and an
implementation for Fragment. I also reworked the Intent Integrator, so
that it works with the mediator.
This way developers that use Fragments need to check-out all files,
while the developers working only with Activities and/or earlier
Android versions can check-out all except for one implementation
class.

Please find a proposal patch as an attachment.

Hartmut: you could try to apply it to your local copy.


2012/1/9 Hartmut <hartmu...@ti-wmc.nl>:

IntentIntegrator.patch

Lachezar Dobrev

unread,
Jan 18, 2012, 10:36:58 AM1/18/12
to zx...@googlegroups.com
After some off-list discussions with Hartmut my initial proposals
seems overcomplicated and seriously redundant. My bad!

A new much simpler patch is attached.
Made IntentIntegrator non-final, re-factored-out the call to
startActivityForResult(...) as a protected method. Sub-classed the
integrator to support Android 3.0 Fragments, and Android Support v4
library.

Hartmut seems to consider this an appropriate solution.

2012/1/9 Lachezar Dobrev <l.do...@gmail.com>:

IntentIntegrator.patch

Sean Owen

unread,
Jan 18, 2012, 11:05:12 AM1/18/12
to zx...@googlegroups.com
I'm not against the patch though it introduces a compile-time dependency on this support jar, and a later Android SDK. (Shouldn't require a runtime dependency unless you're using these subclasses though.)
Hmm, maybe that's fine. At least, this is easy for anyone who needs it to use this way by just grabbing this patch.

Hartmut

unread,
Jan 18, 2012, 11:13:47 AM1/18/12
to zx...@googlegroups.com
I agree that the dependency is a slight nuisance showing a warning if you do not have the dependency in the path.
The alternative would be to create a second 'support' jar (or: even two) - matching Google's example with their support jar.

Sean Owen

unread,
Jan 18, 2012, 11:25:20 AM1/18/12
to zx...@googlegroups.com
OK well it's surely no problem to include the version supporting Android 3.0 as this just requires the end user to have a recent SDK installed, which that piece may already require. I'll add that much.

Lachezar Dobrev

unread,
Jan 19, 2012, 5:00:50 AM1/19/12
to zx...@googlegroups.com
Maybe I need to recap.
The Integrator is not used verbatim.
The user will either have to copy the classes into his project, or
add a .jar library to the project.

If the user needs to copy the integrator he can choose to copy the
needed classes only depending on their framework choices.

For those who choose to reference a .jar library the integrator can
be built in 3 (or 4) different flavours: «legacy», «honeycomb», and
«compatibility». Possibly a «complete» flavour can be build, but I see
no reason behind it. Every flavour .jar would contain only the
required classes.

The reason for the separation is my willingness to provide users
with the ability to check-out newer versions from the Subversion
repository without the need to modify any part of the code (so that
updates are easy on them).

Currently in Eclipse I have both the Android Honeycomb .jar and the
v4 compatibility .jar and it compiles all classes without a problem.

2012/1/18 Sean Owen <sro...@gmail.com>:

Sean Owen

unread,
Jan 19, 2012, 5:31:04 AM1/19/12
to zx...@googlegroups.com
Yes I understand all that, and I put in the 3.0 version already. I only hesitate as to whether it's worth including the version that uses the compatibility layer, as it's a stopgap, I don't know how many people use it, and it means distributing another .jar. None of which are a huge deal.

Sean Owen

unread,
Jan 19, 2012, 11:48:09 AM1/19/12
to zx...@googlegroups.com
OK I put in the V4 class too, in accordance with your off list suggestion and patch. It works nicely. I changed a few of the Android versions so we are at least consistently referring to the latest 2.x, 3.x, 4.x release, as I figure those are mostly like to exist on developer machines.

Too bad we can't use the properties file in Maven but I did at least duplicate the config inside the file, so it is a little easier to manage perhaps.
Reply all
Reply to author
Forward
0 new messages