onActivityResult n'est pas appelé dans Fragment

878

L'activité hébergeant ce fragment a son onActivityResultnom lorsque l'activité de la caméra revient.

Mon fragment démarre une activité pour un résultat avec l'intention envoyée à l'appareil photo de prendre une photo. L'application d'image se charge correctement, prend une photo et revient. Le onActivityResultcependant n'est jamais touché. J'ai défini des points d'arrêt, mais rien n'est déclenché. Un fragment peut-il avoir onActivityResult? Je pense que oui car c'est une fonction fournie. Pourquoi cela n'est-il pas déclenché?

ImageView myImage = (ImageView)inflatedView.findViewById(R.id.image);
myImage.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
        startActivityForResult(cameraIntent, 1888);
    }
});

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if( requestCode == 1888 ) {
        Bitmap photo = (Bitmap) data.getExtras().get("data");
        ((ImageView)inflatedView.findViewById(R.id.image)).setImageBitmap(photo);
    }
}
Spidy
la source
2
consultez cet article, il existe une description du problème et une solution de contournement commune: stackoverflow.com/questions/6147884/…
Oleksii K.
5
Quiconque lisant ceci s'assure que vous réussissez requestCode >= 0!
Muhammad Babar
3
Assurez-vous également que votre Activity LauchMode ne doit pas singleInstance ou singleTask. sinon onActivityResult ne sera pas appelé
Jawad Zeb
Voir ce lien peut vous aider: androidtutorialonline.com/onactivityresult-in-fragment
Tutoriel Android
Nous devons rediriger le onActivityResult de l'activité vers le fragment. Reportez-vous à ce lien: codexpedia.com/android/…
Reejesh PK

Réponses:

1240

L'activité d'hébergement est prioritaire onActivityResult(), mais n'a pas appelé pour super.onActivityResult()des codes de résultat non gérés. Apparemment, même si le fragment est celui qui fait l' startActivityForResult()appel, l'activité obtient le premier coup pour gérer le résultat. Cela a du sens lorsque vous considérez la modularité des fragments. Une fois que j'ai implémenté super.onActivityResult()tous les résultats non gérés, le fragment a réussi à gérer le résultat.

Et aussi de la réponse @siqing:

Pour obtenir le résultat dans votre fragment, assurez-vous d'appeler startActivityForResult(intent,111);au lieu de l' getActivity().startActivityForResult(intent,111);intérieur de votre fragment.

Spidy
la source
34
Dans onActivityResult de votre activité, appelez super.onActivityResult ()
Spidy
167
@StErMi Assurez-vous d'appeler startActivityForResult () et non getActivity (). StartActivityForResult () à partir de votre fragment. Voir la réponse siqing ci-dessous.
OferR
8
Il semble y avoir un bogue connexe, où la bibliothèque de support est utilisée code.google.com/p/android/issues/detail?id=15394
Ollie C
82
Notez également que si vous utilisez des fragments imbriqués, le fragment enfant doit appeler getParentFragment().startActivityForResultpour que le fragment parent ait sa méthode onActivityResult appelée.
Eric Brynsvold
7
@EricBrynsvold avait raison, startActivityForResult ne fonctionne pas dans les fragments imbriqués. Pour cela, vous feriez mieux d'appeler getParentFragment (). StartActivityForResult (), et dans ce fragment parent, alors, vous pouvez implémenter onActivityResult () et dans cette méthode livrer le résultat aux enfants fragmen, à savoir: childFragment.getParentFragment (). onActivityResult (requestCode, resultCode, data)
edrian
328

Je pense que vous avez appelé getActivity().startActivityForResult(intent,111);. Tu devrais appeler startActivityForResult(intent,111);.

siqing
la source
3
J'ai également eu le même problème avec la RingtonePreferencelocalisation de PreferenceFragment. Malheureusement, les RingtonePreferenceappels getActivity().startActivityForResult()et je n'ai pas obtenu de résultats même si j'appelle super.onActivityResultles activités onActivityResult. J'ai été obligé de créer un dérivé de la RingtonePreferenceclasse, qui se lie aux PreferenceFragmentappels et fragment.startActivityForResult().
Stan
@siqing Je ne peux pas appeler startActivitForResult depuis ma méthode statique. Une solution pour ça? Je dois avoir besoin d'utiliser activity.startActivityForResult. S'il vous plaît, aidez-moi à ce sujet
Shreyash Mahajan
270

Option 1:

Si vous appelez à startActivityForResult()partir du fragment, vous devez appeler startActivityForResult()non getActivity().startActivityForResult(), car cela entraînera un fragment onActivityResult ().

Si vous ne savez pas où vous appelez startActivityForResult()et comment vous appellerez les méthodes.

Option 2:

Étant donné que l'activité obtient le résultat de onActivityResult(), vous devrez remplacer l'activité onActivityResult()et appeler super.onActivityResult()pour se propager au fragment respectif pour les codes de résultats non gérés ou pour tous.

Si les deux options ci-dessus ne fonctionnent pas, reportez-vous à l'option 3 car cela fonctionnera certainement.

Option 3:

Un appel explicite de fragment à la fonction onActivityResult est le suivant.

Dans la classe Activity parent, substituez la méthode onActivityResult () et même remplacez-la dans la classe Fragment et appelez comme le code suivant.

Dans la classe parent:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.dualPane);
    fragment.onActivityResult(requestCode, resultCode, data);
}

En classe enfant:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // In fragment class callback
}
Vinayak
la source
4
Cela a fonctionné pour moi. C'est une mauvaise solution de contournement, mais je n'ai pas de meilleure idée pour résoudre ce bug idiot ...
Bogdan Zurac
@Vivky, votre réponse a fonctionné pour moi. Mais il y a un autre problème auquel je suis confronté, au lieu de setResult(); finish();lorsque j'appuie sur la deuxième activité, puis je suis également onActivityResultappelé avec fourni RESULT_CODE.
snehal_penurkar
superbe réponse. J'ai implémenté la troisième solution pour le faire.
Sash_KP
Je pense que la solution 3 fonctionnerait pour moi mais l' onActivityResult()activité retourne un étrange requestCodequi est passé à mon fragment puis ignoré = /
E-Kami
1
@notGeek Vous avez raison. Le résultat est toujours reçu dans l'activité même si vous avez appelé à partir d'un fragment ou d'une activité.
Vinayak
83

Dans le cas où vous ne connaissez pas de fragments dans votre activité, énumérez-les tous et envoyez des arguments de résultat d'activité:

// In your activity
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    for (Fragment fragment : getSupportFragmentManager().getFragments()) {
        fragment.onActivityResult(requestCode, resultCode, data);
    }
}
ruX
la source
3
Merde, je pensais que je venais de trouver la solution la plus simple, mais il n'y a pas de méthode telle que getFragments ().
WindRider
2
@WindRider Il y en a. Si vous utilisez la bibliothèque de support Android (AppCompat).
2014
2
De plus, j'ai appris à la dure que vous devez vérifier si le fragment dans le tableau n'est pas une référence à lui-même! `if (fragment! = this) {fragment.onActivityResult (requestCode, resultCode, data); `
reubenjohn
Cela ne fonctionne pas si les fragments sont imbriqués, car seul le fragment supérieur sera dans la liste. Je crois que super.onActivityResult () appelle déjà onActivityResult () sur tous les fragments de la liste, donc cette idée est redondante.
BeccaP
83

J'ai ce même problème avec le ChildFragmentManager. Le gestionnaire ne transmettra pas le résultat au fragment imbriqué, vous devez le faire manuellement dans votre fragment de base.

public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    super.onActivityResult(requestCode, resultCode, intent);
    Fragment fragment = (Fragment) getChildFragmentManager().findFragmentByTag(childTag);
    if (fragment != null) {
        fragment.onActivityResult(requestCode, resultCode, intent);
    }
}
MinceMan
la source
1
Si vous avez votre enfant Fragment en tant que membre privé, utilisez-le Fragment fragment = myChildFragment;pour remplacer la findFragmentByTagligne de code ci-dessus . Le reste peut rester inchangé.
lcn
7
Je suppose que je recommanderais fortement de ne pas conserver un fragment en tant que membre privé. Ils ont leur propre cycle de vie, donc vous ne savez jamais s'ils sont en bon état pour interagir avec, le gestionnaire en a. De plus, ils sont assez lourds et je serais préoccupé par les fuites de mémoire. Le gestionnaire n'aurait pas été créé si vous n'aviez pas besoin de l'utiliser.
MinceMan
67

Poste d'origine.

FragmentActivityremplace requestCodepar un modèle modifié. Après cela, lorsque onActivityResult()sera invoqué, FragmentActivityanalyse les 16 bits supérieurs et restaure l'index du fragment d'origine. Regardez ce schéma:

Entrez la description de l'image ici

Si vous avez quelques fragments au niveau racine, il n'y a aucun problème. Mais si vous avez des fragments imbriqués , par exemple Fragmentavec quelques onglets à l'intérieur ViewPager, vous aurez sûrement face à un problème (ou déjà rencontré).

Parce qu'un seul index est stocké à l'intérieur requestCode. C'est l'indice de l' Fragmentintérieur de son FragmentManager. Lorsque nous utilisons des fragments imbriqués, il y a des enfants FragmentManager, qui ont leur propre liste de fragments. Il est donc nécessaire de sauvegarder toute la chaîne des indices, à partir de la racine FragmentManager.

Entrez la description de l'image ici

Comment pouvons-nous résoudre ce problème? Il existe une solution de contournement courante dans ce message .

GitHub: https://github.com/shamanland/nested-fragment-issue

Oleksii K.
la source
J'ai le même problème que j'ai utilisé un ViewPager dans le fragment parent qui contient d'autres fragments sous forme d'onglets. J'ai essayé d'utiliser le problème des fragments imbriqués, mais j'ai fini avec des erreurs de compilation. Pouvez-vous me suggérer la solution? A également soulevé un problème ici github.com/shamanland/nested-fragment-issue/issues/2
cgr
J'ai répondu sur github, alors déplaçons cette conversation d'ici github.com/shamanland/nested-fragment-issue/issues/…
Oleksii K.
Merci! Si ce n'est pas une solution recommandée, je suggère d'éditer la réponse en conséquence afin qu'il ne soit pas nécessaire de passer du temps à essayer pour savoir qu'il contient des erreurs de compilation.
cgr
44

C'est l'un des problèmes les plus populaires. Nous pouvons trouver beaucoup de discussions sur ce problème. Mais aucun d'eux n'est utile pour MOI.

J'ai donc résolu ce problème en utilisant cette solution.

Voyons d'abord pourquoi cela se produit.

Nous pouvons appeler startActivityForResultdirectement à partir de Fragment mais en fait, les mécaniciens derrière sont tous gérés par Activity.

Une fois que vous appelez startActivityForResult partir d'un fragment, requestCode sera modifié pour attacher l'identité du fragment au code. Cela permettra à Activity de retracer celui qui envoie cette demande une fois le résultat reçu.

Une fois que l'activité a été parcourue, le résultat sera envoyé à onActivityResult de l'activité avec le requestCode modifié qui sera décodé en l'identité de requestCode + Fragment d'origine. Après cela, Activity enverra le résultat de l'activité à ce fragment via onActivityResult. Et tout est terminé.

Le problème est:

L'activité pourrait envoyer le résultat uniquement au fragment qui a été attaché directement à l'activité mais pas à l'imbrication. C'est la raison pour laquelle onActivityResult du fragment imbriqué ne sera jamais appelé quoi qu'il arrive.

Solution:

1) Commencez l'intention dans votre fragment par le code ci-dessous:

       /** Pass your fragment reference **/
       frag.startActivityForResult(intent, REQUEST_CODE); // REQUEST_CODE = 12345

2) Maintenant dans votre remplacement d'activité parentale **onActivityResult() : **

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
    }

Vous devez l'appeler dans l'activité parent pour que cela fonctionne.

3) Dans votre appel de fragment:

@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {

       }
}

C'est ça. Avec cette solution, elle pourrait être appliquée à tout fragment unique, qu'il soit imbriqué ou non. Et oui, il couvre également tout le cas! De plus, les codes sont également agréables et propres.

KishuDroid
la source
Je demandais l'intention du système avec «activité», je devais simplement utiliser le contexte de fragment.
Uzair
18

POUR DE NOMBREUX FRAGMENTS IMPLIQUÉS (par exemple, lors de l'utilisation d'un ViewPager dans un fragment)

Dans votre activité principale :

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
}

Dans votre fragment:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    for (Fragment fragment : getChildFragmentManager().getFragments()) {
        fragment.onActivityResult(requestCode, resultCode, data);
    }
}

Dans votre fragment imbriqué

Activité d'appel

getParentFragment().startActivityForResult(intent, uniqueInstanceInt);

uniqueInstanceInt - remplacez-le par un unique parmi les fragments imbriqués pour éviter qu'un autre fragment ne traite la réponse.

Recevoir une réponse

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == uniqueInstanceInt ) {
        // TODO your code
    }
}

Attention

Un nombre compris entre 0 et 65536 doit être utilisé dans uniqueInstanceInt pour éviter les erreurs "Ne peut utiliser que les 16 bits inférieurs pour requestCode".

Luciano Marqueto
la source
Fonctionne très bien dans Activité> Fragment (ViewPager)> Fragment
Oleksandr Firsov
14

Je peux ajouter deux conseils si quelqu'un ne peut toujours pas le faire. Dans le fichier Manifest.xml, assurez-vous que l'activité d'hébergement ne s'est pas terminée lors du rappel et que l'activité à démarrer a le mode de lancement en standard. Voir les détails ci-dessous:

Pour l'activité d'hébergement, définissez la propriété no history sur false si vous avez

android:noHistory="false"

Pour que l'activité démarre, définissez le mode de lancement comme standard si

android:launchMode="standard"
jowett
la source
13

J'étais également confronté au même problème une fois que j'ai déplacé ce bloc de code en dehors d'un fragment vers une classe utilitaire , avec un argumentparentActivity passé ,

Intent intent = new Intent(parentActivity, CameraCaptureActivity.class);
parentActivity.startActivityForResult(intent,requestCode);

Ensuite, je n'obtenais aucune valeur dans la onActivityResultméthode de ce fragment . Ensuite, j'ai changé l' argument en Fragment , de sorte que la définition révisée de la méthode ressemblait,

Intent intent = new Intent(fragment.getContext(), CameraCaptureActivity.class);
fragment.startActivityForResult(intent,requestCode);

Après cela, j'ai pu valoriser onActivityResultle Fragment

Shamsul Arefin Sajib
la source
10

J'ai également rencontré ce problème dans un fragment. Et j'ai appelé startActivityForResultdans un DialogFragment.

Mais maintenant , ce problème a été résolu:
FragmentClassname.this.startActivityForResult .

Courysky
la source
Super, ça a marché pour moi, parce que j'appelais startActivityForResult(...)depuis une classe abstraite à l'intérieur du code du fragment.
Vince
9

POUR LES FRAGMENTS IMPRIMÉS (par exemple, lors de l'utilisation d'un ViewPager)

Dans votre activité principale:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
}

Dans votre fragment principal de premier niveau (fragment ViewPager):

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    YourFragment frag = (YourFragment) getChildFragmentManager().getFragments().get(viewPager.getCurrentItem());
    frag.yourMethod(data);  // Method for callback in YourFragment
    super.onActivityResult(requestCode, resultCode, data);
}

Dans YourFragment (fragment imbriqué):

public void yourMethod(Intent data){
    // Do whatever you want with your data
}
Jyotman Singh
la source
8

Dans mon cas, c'était un bug Android ( http://technet.weblineindia.com/mobile/onactivityresult-not-getting-called-in-nested-fragments-android/ ), si vous utilisez un support, FragmentActivityvous devez utiliser à la getSupportFragmentManagerplace de getChildFragmentManager:

List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments != null) {
    for (Fragment fragment : fragments) {
        if(fragment instanceof UserProfileFragment) {
            fragment.onActivityResult(requestCode, resultCode, data);
        }
    }
}
Hazlo8
la source
6

En bref,

En fragment, déclarez Fragment fragment = this ;

après cette utilisation fragment.startActivityForResult .

Le résultat retournera dans activityResult.

Clevester
la source
6

Solution 1:

Appeler startActivityForResult(intent, REQUEST_CODE);au lieu degetActivity().startActivityForResult(intent, REQUEST_CODE); .

Solution 2:

Quand startActivityForResult(intent, REQUEST_CODE);est appelé l'activité onActivityResult(requestCode,resultcode,intent)est invoquée, puis vous pouvez appeler fragments onActivityResult()d'ici en passant le requestCode, resultCode and intent.

Amey Haldankar
la source
5

À l'intérieur de votre fragment, appelez

this.startActivityForResult(intent, REQUEST_CODE);

thisfait référence au fragment. Sinon, faites comme @Clevester a dit:

Fragment fragment = this;
....
fragment.startActivityForResult(intent, REQUEST_CODE);

J'ai aussi dû appeler

super.onActivityResult(requestCode, resultCode, data);

dans l'activité parentale onActivityResultpour le faire fonctionner.

(J'ai adapté cette réponse de la réponse de @ Clevester.)

Suragch
la source
5

Pour ceux qui utilisent le composant de navigation Android, utilisez dans Activity's onActivityResult(...)le primaryNavigationFragmentpour obtenir sa référence de fragment et appeler fragment fragment.onActivityResult(...).

Voici les activités onActivityResult(...)

@Override
public void onActivityResult(int requestCode, int resultCode, Intent imageData)
{
    super.onActivityResult(requestCode, resultCode, imageData);

    for (Fragment fragment : getSupportFragmentManager().getPrimaryNavigationFragment().getChildFragmentManager().getFragments())
    {
            fragment.onActivityResult(requestCode, resultCode, imageData);
    }
}
Mohit Mehta
la source
4

La plupart de ces réponses continuent de dire que vous devez appeler super.onActivityResult(...)votre hôte ActivitypourFragment . Mais cela ne semblait pas fonctionner pour moi.

Donc, chez votre hôte, Activityvous devriez Fragments onActivityResult(...)plutôt appeler votre . Voici un exemple.

public class HostActivity extends Activity {

    private MyFragment myFragment;

    protected void onActivityResult(...) {
        super.onActivityResult(...);
        this.myFragment.onActivityResult(...);
    }
}

À un moment donné de votre, HostActivityvous devrez attribuer this.myFragmentcelui que Fragmentvous utilisez. Ou, utilisez le FragmentManagerpour obtenir le Fragmentau lieu de conserver une référence à celui-ci dans votre HostActivity. Vérifiez également nullavant d'appeler le this.myFragment.onActivityResult(...);.

prolink007
la source
3
public class takeimage extends Fragment {

    private Uri mImageCaptureUri;
    private static final int PICK_FROM_CAMERA = 1;
    private static final int PICK_FROM_FILE = 2;
    private String mPath;
    private ImageView mImageView;
    Bitmap bitmap = null;
    View view;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.activity_send_image, container, false);
        final String[] items = new String[] { "From Camera", "From SD Card" };
        mImageView = (ImageView)view.findViewById(R.id.iv_pic);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.select_dialog_item, items);
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        builder.setTitle("Select Image");

        builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int item) {
                if (item == 0) {
                    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                    File file = new File(Environment.getExternalStorageDirectory(), "tmp_avatar_"
                        + String.valueOf(System.currentTimeMillis())
                        + ".jpg");
                    mImageCaptureUri = Uri.fromFile(file);

                    try {
                        intent.putExtra(
                            android.provider.MediaStore.EXTRA_OUTPUT,
                            mImageCaptureUri);
                        intent.putExtra("return-data", true);

                        getActivity().startActivityForResult(intent,
                            PICK_FROM_CAMERA);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    dialog.cancel();
                } else {
                    Intent intent = new Intent();

                    intent.setType("image/*");
                    intent.setAction(Intent.ACTION_GET_CONTENT);

                    getActivity().startActivityForResult(
                        Intent.createChooser(intent,
                            "Complete action using"), PICK_FROM_FILE);
                }
            }
        });
        final AlertDialog dialog = builder.create();

        Button show = (Button) view.findViewById(R.id.btn_choose);
        show.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // Switch the tab content to display the list view.
                dialog.show();
            }
        });

    return view;
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (resultCode != Activity.RESULT_OK)
            return;

        if (requestCode == PICK_FROM_FILE) {
            mImageCaptureUri = data.getData();
            // mPath = getRealPathFromURI(mImageCaptureUri); //from Gallery

            if (mPath == null)
                mPath = mImageCaptureUri.getPath(); // from File Manager

            if (mPath != null)
                bitmap = BitmapFactory.decodeFile(mPath);
        } else {
            mPath = mImageCaptureUri.getPath();
            bitmap = BitmapFactory.decodeFile(mPath);
        }
        mImageView.setImageBitmap(bitmap);  
    }

    public String getRealPathFromURI(Uri contentUri) {
        String [] proj = {MediaStore.Images.Media.DATA};
        Cursor cursor = managedQuery(contentUri, proj, null, null,null);

        if (cursor == null) return null;

        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        return cursor.getString(column_index);
    }
} 
shakirullah orakzai
la source
3
  1. Vous pouvez simplement remplacer BaseActivity onActivityResultsur un fragment baseActivity.startActivityForResult.

  2. Sur BaseActivity, ajoutez l'interface et remplacez onActivityResult.

    private OnBaseActivityResult baseActivityResult;
    public static final int BASE_RESULT_RCODE = 111;
    public interface OnBaseActivityResult{
        void onBaseActivityResult(int requestCode, int resultCode, Intent data);
       }
    }
    
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(getBaseActivityResult() !=null && requestCode == BASE_RESULT_RCODE){
        getBaseActivityResult().onBaseActivityResult(requestCode, resultCode, data);
        setBaseActivityResult(null);
    }
  3. Sur les instruments fragmentés OnBaseActivityResult

    @Override
    public void onBaseActivityResult(int requestCode, int resultCode, Intent data) {
    Log.d("RQ","OnBaseActivityResult");
    if (data != null) {
        Log.d("RQ","OnBaseActivityResult + Data");
        Bundle arguments = data.getExtras();
      }
    }

Cette solution de contournement fera l'affaire.

Khaled Lela
la source
3

Si le problème ci-dessus est rencontré lors de la connexion à Facebook, vous pouvez utiliser le code ci-dessous dans une activité parent de votre fragment comme:

Fragment fragment = getFragmentManager().findFragmentById(android.R.id.tabcontent);
fragment.onActivityResult(requestCode, resultCode, data);

Ou:

Fragment fragment = getFragmentManager().findFragmentById("fragment id here");
fragment.onActivityResult(requestCode, resultCode, data);

Et ajoutez l'appel ci-dessous dans votre fragment ...

callbackManager.onActivityResult(requestCode, resultCode, data);
Ketan Patel
la source
2

Un autre cas d'utilisation non déjà décrit dans d'autres réponses:

onActivityResult()déclaré dans fragment n'est pas invoqué lors de l'utilisation exception.startResolutionForResult():

if (exception is ResolvableApiException) {
    exception.startResolutionForResult(activity!!, MY_REQUEST_CODE)
}

Dans ce cas, remplacez exception.startResolutionForResult()par fragment startIntentSenderForResult():

if (exception is ResolvableApiException) {
    startIntentSenderForResult(exception.resolution.intentSender, MY_REQUEST_CODE, null, 0, 0, 0, null)
}
dominik
la source
2

Version Kotlin (Dans votre activité surActivityResult ())

 override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    //add following lines in your activity
    if(supportFragmentManager?.fragments!=null && supportFragmentManager?.fragments!!.size>0)
     for (i in 0..supportFragmentManager?.fragments!!.size-1) {
         val fragment= supportFragmentManager?.fragments!!.get(i)
         fragment.onActivityResult(requestCode, resultCode, data)
    }
 }
Ranjith Kumar
la source
1

J'ai une forte suspicion que toutes les réponses ici ne sont rien d'autre que des hacks. Je les ai tous essayés et bien d'autres, mais sans aucune conclusion fiable car il y a toujours une sorte de problème stupide. Pour ma part, je ne peux pas compter sur des résultats incohérents. Si vous consultez la documentation officielle de l'API Android pour les fragments, vous verrez que Google indique clairement ce qui suit:

Appelez startActivityForResult (Intent, int) à partir de l'activité contenant le fragment.

Voir: API Android Fragment

Ainsi, il semblerait que l'approche la plus correcte et la plus fiable serait d'appeler réellement startActivityForResult () à partir de l'activité d'hébergement et de gérer également le onActivityResult () résultant à partir de là.

Chris
la source
2
Je ne pense pas que "appeler startActivityForResult from Activity" soit une recommandation. Si vous regardez l'implémentation à l'intérieur de la classe de base Fragment, alors tout ce qu'elle fait est mActivity.startActivityFromFragment(this, intent, requestCode)- donc ce n'est rien d'autre qu'un emballage pratique
Anti Veeranna
1

Votre code a un fragment imbriqué. L'appel de super.onActivityForResult ne fonctionne pas

Vous ne voulez pas modifier chaque activité à partir de laquelle votre fragment peut être appelé et ou contourner l'appel de chaque fragment de la chaîne de fragments.

Voici l'une des nombreuses solutions de travail. créez un fragment à la volée et connectez-le directement à l'activité avec le gestionnaire de fragments de support. Appelez ensuite startActivityForResult à partir du fragment nouvellement créé.

private void get_UserEmail() {

    if (view == null) {
        return;
    }
    ((TextView) view.findViewById(R.id.tvApplicationUserName))
            .setText("Searching device for user accounts...");

    final FragmentManager fragManager = getActivity().getSupportFragmentManager();

    Fragment f = new Fragment() {
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            startActivityForResult(AccountPicker.newChooseAccountIntent(null, null,
                    new String[]{"com.google"}, false, null, null, null, null), REQUEST_CODE_PICK_ACCOUNT);
        }

        @Override
        public void onActivityResult(int requestCode, int resultCode,
                                     Intent data) {
            if (requestCode == REQUEST_CODE_PICK_ACCOUNT) {
                String mEmail = "";
                if (resultCode == Activity.RESULT_OK) {
                    if (data.hasExtra(AccountManager.KEY_ACCOUNT_NAME)) {
                        mEmail = data
                                .getStringExtra(AccountManager.KEY_ACCOUNT_NAME);
                    }
                }
                if (mActivity != null) {
                    GoPreferences.putString(mActivity, SettingApplication.USER_EMAIL, mEmail);
                }
                doUser();
            }
            super.onActivityResult(requestCode, resultCode, data);
            fragManager.beginTransaction().remove(this).commit();
        }
    };
    FragmentTransaction fragmentTransaction = fragManager
            .beginTransaction();
    fragmentTransaction.add(f, "xx" + REQUEST_CODE_PICK_ACCOUNT);
    fragmentTransaction.commit();
}
danny117
la source
Cela fonctionne réellement et je n'ai qu'un seul vote pour. Créez un fragment à la volée. Trop facile mais sa vraie solution de travail. Quelqu'un a même essayé de le modifier pour moi.
danny117
1

Mon problème était lié à l'activité de l'hôte. Je l'ai trouvé avec un ensemble. android:launchMode="standard"Je l'ai supprimé temporairement et cela a fonctionné!

Chulo
la source
1

Un point que personne n'a mentionqui s'assure que le mode de lancement de votre activité hôte ne doit pas être défini sur singleInstanceou singleTask.

onActivityResult ne fonctionnera pas si votre mode de lancement est défini sur SingleInstance ou SingleTask. ou vous appelez votre activité en utilisant ces IntentFilters

standardou le singleTopmode de lancement fonctionnera bien.

Jawad Zeb
la source
1

Si vous utilisez des fragments imbriqués, cela fonctionne également:

getParentFragment().startActivityForResult(intent, RequestCode);

En plus de cela, vous devez appeler super.onActivityResultdepuis l'activité parent et remplir la onActivityResultméthode du fragment.

Oguz Ozcan
la source
1

J'ai géré le problème en écrivant une classe de base qui s'étend Fragment, et dans onactivityresultl'activité, j'ai identifié le fragment en cours d'exécution à l'aide de fragmenttag. Ensuite, j'appelle une méthode définie par l'utilisateur dans la classe fragmentbase. Cela déclenchera un événement dans le fragment en cours d'exécution.

Bytecode
la source