android main - onActivityResult n'est pas appelé dans Fragment




15 Answers

L'activité d'hébergement remplace onActivityResult() , mais n'a pas appelé super.onActivityResult() pour les codes de résultat non super.onActivityResult() . Apparemment, même si le fragment est celui qui effectue l'appel startActivityForResult() , l'activité obtient la première prise en charge du résultat. Cela a du sens quand on considère la modularité des fragments. Une fois que j'ai implémenté super.onActivityResult() pour tous les résultats non super.onActivityResult() , le fragment a eu une chance de gérer le résultat.

Et aussi de @siqing répondre:

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

thread

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

Mon fragment commence une activité pour un résultat avec l'intention envoyée à la caméra de prendre une photo. L'application d'image se charge bien, prend une photo et revient. Le onActivityResult n'est cependant jamais atteint. J'ai défini des points d'arrêt, mais rien n'est déclenché. Un fragment peut-il avoir onActivityResult ? Je le pense 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);
    }
}



Option 1:

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

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

Option 2:

Etant donné que Activity obtient le résultat de onActivityResult() , vous devrez remplacer le onActivityResult() et appeler super.onActivityResult() pour le propager au fragment respectif pour les codes de résultats non super.onActivityResult() ou pour tous.

Si au-dessus de deux options ne fonctionnent pas, alors référez-vous à l'option 3 car cela fonctionnera certainement.

Option 3:

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

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

Dans la classe parente:

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

Dans la classe des enfants:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // In fragment class callback
}



Dans le cas où vous ne connaissez pas les fragments de votre activité, il vous suffit de tous les énumérer et d'envoyer 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);
    }
}



C'est l'un des problèmes les plus populaires. Nous pouvons trouver beaucoup de fil à propos de 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 passe.

Nous pouvons appeler startActivityForResult directement à partir de Fragment, mais en réalité les mécanismes 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é de Fragment au code. Cela permettra à l'activité d'être en mesure de retracer qui envoie cette demande une fois le résultat reçu.

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

Le problème est:

L'activité peut envoyer le résultat uniquement au fragment qui a été attaché directement à l'activité, mais pas à l'imbriqué. C'est la raison pour laquelle onActiveResult du fragment imbriqué n'a jamais été 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 le remplacement de votre activité parent ** onActivityResult() : **

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

Vous devez appeler cela dans l'activité parentale pour le faire fonctionner.

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 tout. Avec cette solution, il pourrait être appliqué à n'importe quel fragment, qu'il soit imbriqué ou non. Et oui, ça couvre aussi tout le cas! De plus, les codes sont aussi beaux et propres.




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é à lancer possède le mode de lancement standard. Voir les détails ci-dessous:

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

android:noHistory="false"

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

android:launchMode="standard"



Solution 1:

Appelez startActivityForResult(intent, REQUEST_CODE); au lieu de getActivity().startActivityForResult(intent, REQUEST_CODE); .

Solution 2:

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




En bref,

Dans le fragment, déclare Fragment fragment = this ;

Après cela, utilisez fragment.startActivityForResult .

Le résultat retournera dans activityResult.




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

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



  1. Vous pouvez simplement remplacer BaseActivity onActivityResult sur le fragment baseActivity.startActivityForResult .

  2. Sur BaseActivity, ajoutez une 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 Fragment implémente 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.




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 parentActivity passé en argument ,

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

Ensuite, je n'obtenais aucune valeur dans la méthode onActivityResult de ce Fragment . Ensuite, j'ai changé l' argument en Fragment , donc 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 obtenir de la valeur dans onActivityResult sur le fragment




L'un des moyens les plus simples est de démarrer une activité à partir de votre fragment.

startActivity(ActivityName);

Ensuite, ajoutez vous appelez startActivityForResult(intent,"1"); de votre activité et ajoutez le onActivityResult de l'activité dans votre activité

startActivityForResult(intent,"1");

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.dualPane);
    fragment.onActivityResult(requestCode, resultCode, data);
// perform other activity result like fetching from Uris or handling cursors

finish(); // finish the activity will  get to back to your fragment.
}



J'ai un fort soupçon que toutes les réponses ici ne sont rien de plus que des hacks. Je les ai essayés tous et beaucoup 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 regardez 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 startActivityForResult () à partir de l'activité d'hébergement et de gérer le résultat onActivityResult () à partir de là.




Mon problème était avec l'activité de l'hôte que je l'ai trouvé avec un ensemble android:launchMode="standard" Je l'ai supprimé temporaire et ça marche!




Utilisez simplement le code ci-dessous pour le fragment.

@Override
public void onOtherButtonClick(ActionSheet actionSheet, int index) {

    if (index == 1)
    {
        Intent intent = new Intent(Intent.ACTION_PICK,
                                   android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        intent.setType("image/*");
        startActivityForResult(Intent.createChooser(intent,
                                                    "Select Picture"), 1);
     }
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == 1) {
        if (requestCode == 1) {
            Uri selectedImageUri = data.getData();
            //selectedImagePath = getPath(selectedImageUri);
        }
    }
}

onActivityResult appellera sans appeler son parent.




S'il y a un problème avec la méthode onActivityResult qui se trouve dans la classe fragment, et que vous voulez mettre à jour quelque chose qui se trouve aussi dans la classe fragment, utilisez:

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

    if(resultCode == Activity.RESULT_OK)
    {
        // If the user had agreed to enabling Bluetooth,
        // populate the ListView with all the paired devices.
        this.arrayDevice = new ArrayAdapter<String>(this.getContext(), R.layout.device_item);
        for(BluetoothDevice bd : this.btService.btAdapater.getBondedDevices())
        {
            this.arrayDevice.add(bd.getAddress());
            this.btDeviceList.setAdapter(this.arrayDevice);
        }
    }
    super.onActivityResult(requestCode, resultCode, data);
}

Ajoutez simplement this.variable comme indiqué dans le code ci-dessus. Sinon, la méthode sera appelée dans l'activité parente et la variable ne sera pas mise à jour de l'instance en cours.

Je l'ai également testé en plaçant ce bloc de code dans MainActivity , en le remplaçant par la classe HomeFragment et en ayant les variables statiques. J'ai obtenu des résultats comme je m'y attendais.

Donc, si vous voulez que la classe de fragment ait sa propre implémentation de onActivityResult , l'exemple de code ci-dessus est la réponse.




Related

android android-fragments android-activity