onActivityResult non viene chiamato in Frammento


878

L'attività che ospita questo frammento viene onActivityResultchiamata quando ritorna l'attività della videocamera.

Il mio frammento avvia un'attività per un risultato con l'intento inviato alla fotocamera di scattare una foto. L'applicazione per immagini si carica bene, scatta una foto e ritorna. Il onActivityResultcomunque non è mai colpito. Ho impostato i punti di interruzione, ma non viene attivato nulla. Un frammento può avere onActivityResult? Credo di si, dato che è una funzione fornita. Perché questo non viene attivato?

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

2
controlla questo post, c'è una descrizione del problema e una soluzione alternativa: stackoverflow.com/questions/6147884/…
Oleksii K.

5
Chiunque legga questo assicurati di passare requestCode >= 0!
Muhammad Babar,

3
Assicurati inoltre che Activity LauchMode non deve singleInstance o singleTask. altrimenti onActivityResult non chiamerà
Jawad Zeb


Dobbiamo reindirizzare onActivityResult in Activity to the Fragment. Fai riferimento a questo link: codexpedia.com/android/…
Reejesh PK il

Risposte:


1240

L'attività di hosting ha la precedenza onActivityResult(), ma non ha richiesto chiamate super.onActivityResult()per codici risultato non gestiti. Apparentemente, anche se il frammento è quello che effettua la startActivityForResult()chiamata, l'attività ottiene il primo colpo nella gestione del risultato. Ciò ha senso se si considera la modularità dei frammenti. Una volta implementato super.onActivityResult()per tutti i risultati non gestiti, il frammento ha avuto una possibilità di gestire il risultato.

E anche dalla risposta di @siqing:

Per ottenere il risultato nel tuo frammento, assicurati di chiamare startActivityForResult(intent,111);anziché getActivity().startActivityForResult(intent,111);all'interno del tuo frammento.


34
In onActivityResult della tua attività, chiama super.onActivityResult ()
Spidy

167
@StErMi Assicurati di chiamare startActivityForResult () e non getActivity (). StartActivityForResult () dal tuo frammento. Vedi la risposta di Siqing sotto.
OferR,

8
Sembra che ci sia un bug correlato, in cui viene utilizzata la libreria di supporto code.google.com/p/android/issues/detail?id=15394
Ollie C

82
Si noti inoltre che se si utilizzano frammenti nidificati, il frammento figlio deve chiamare in getParentFragment().startActivityForResultmodo che il frammento padre disponga del metodo onActivityResult chiamato.
Eric Brynsvold,

7
@EricBrynsvold aveva ragione, startActivityForResult non funziona nei frammenti nidificati. Per questo, è meglio chiamare getParentFragment (). StartActivityForResult () e in quel frammento padre, quindi, è possibile implementare onActivityResult () e in quel metodo consegnare il risultato al figlio fragmen, cioè: childFragment.getParentFragment (). onActivityResult (requestCode, resultCode, data)
edrian

328

Penso che tu abbia chiamato getActivity().startActivityForResult(intent,111);. Dovresti chiamare startActivityForResult(intent,111);.


3
Ho anche avuto lo stesso problema con l' RingtonePreferenceubicazione in PreferenceFragment. Sfortunatamente, RingtonePreferencechiama getActivity().startActivityForResult()e non ho ottenuto risultati anche se chiamo super.onActivityResultl'attività onActivityResult. Sono stato costretto a creare un derivato dalla RingtonePreferenceclasse, che si lega alle PreferenceFragmentchiamate e fragment.startActivityForResult().
Stan,

@siqing Non riesco a chiamare startActivitForResult dal mio metodo statico. Qualche soluzione per quello? Devo usare use.startActivityForResult. Per favore, aiutatemi in questo
Shreyash Mahajan

270

Opzione 1:

Se stai chiamando startActivityForResult()dal frammento, dovresti chiamare startActivityForResult(), no getActivity().startActivityForResult(), poiché si tradurrà in frammento onActivityResult ().

Se non sei sicuro di dove stai chiamando startActivityForResult()e come chiamerai i metodi.

Opzione 2:

Poiché l'attività ottiene il risultato onActivityResult(), sarà necessario sovrascrivere l'attività onActivityResult()e chiamare super.onActivityResult()per propagare al rispettivo frammento per codici di risultati non gestiti o per tutti.

Se le due opzioni precedenti non funzionano, fai riferimento all'opzione 3 poiché funzionerà sicuramente.

Opzione 3:

Una chiamata esplicita dal frammento alla funzione onActivityResult è la seguente.

Nella classe Activity padre, sovrascrivi il metodo onActivityResult () e persino lo stesso nella classe Fragment e chiama come il seguente codice.

Nella classe genitore:

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

Nella classe del bambino:

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

4
Questo ha funzionato per me. È una brutta soluzione, ma non ho un'idea migliore per risolvere questo bug idiota ...
Bogdan Zurac,

@Vivky, la tua risposta ha funzionato per me. Ma c'è un altro problema che sto affrontando, invece di setResult(); finish();quando torno indietro dalla seconda attività e poi onActivityResultviene chiamato con fornito RESULT_CODE.
snehal_penurkar,

risposta superba. Ho implementato la terza soluzione per farlo.
Sash_KP,

Penso che la soluzione 3 funzionerebbe per me, ma l' onActivityResult()attività restituisce uno strano requestCodeche viene passato al mio frammento e quindi ignorato = /
E-Kami

1
@notGeek Hai ragione. Il risultato viene sempre ricevuto in Attività anche se è stato chiamato da un frammento o un'attività.
Vinayak,

83

Nel caso in cui non si conoscano frammenti nella propria attività, elencarli tutti e inviare argomenti dei risultati dell'attività:

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

3
Accidenti, pensavo di aver appena trovato la soluzione più semplice, ma non esiste un metodo come getFragments ().
WindRider

2
@WindRider C'è. Se si utilizza la libreria di supporto Android (AppCompat).
Dasar,

2
Inoltre, ho imparato a mie spese che devi verificare se il frammento nell'array non è un riferimento a se stesso! `if (fragment! = this) {fragment.onActivityResult (requestCode, resultCode, data); `
reubenjohn l'

Questo non funziona se i frammenti sono nidificati, poiché solo il frammento superiore sarà nell'elenco. Credo che super.onActivityResult () stia già chiamando onActivityResult () su tutti i frammenti dell'elenco, quindi questa idea è ridondante.
BeccaP


83

Sto riscontrando lo stesso problema con ChildFragmentManager. Il gestore non passerà il risultato al frammento nidificato, è necessario farlo manualmente nel frammento di 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);
    }
}

1
Se hai un frammento di tuo figlio come membro privato, usa Fragment fragment = myChildFragment;per sostituire la findFragmentByTagriga di codice sopra . Il resto può essere mantenuto invariato.
LCN

7
Immagino che raccomanderei caldamente di non conservare un frammento come membro privato. Hanno il loro ciclo di vita, quindi non puoi mai sapere se sono in buone condizioni con cui interagire, il manager lo fa. Inoltre sono piuttosto pesanti e sarei preoccupato per le perdite di memoria. Il gestore non sarebbe stato creato se non fosse necessario utilizzarlo.
MinceMan,

67

Posta originale

FragmentActivitysostituisce requestCodecon uno modificato. Successivamente, quando onActivityResult()verrà invocato, FragmentActivityanalizza i 16 bit superiori e ripristina l'indice del frammento originale. Guarda questo schema:

Inserisci qui la descrizione dell'immagine

Se hai alcuni frammenti a livello di radice non ci sono problemi. Ma se hai frammenti nidificati , ad esempio Fragmentcon alcune schede all'interno ViewPager, avrai sicuramente un problema (o già affrontato).

Perché al suo interno è memorizzato un solo indicerequestCode . Questo è l'indice Fragmental suo interno FragmentManager. Quando stiamo usando frammenti nidificati, ci sono dei figli FragmentManager, che hanno il loro elenco di frammenti. Quindi, è necessario salvare l'intera catena di indici, a partire dalla radice FragmentManager.

Inserisci qui la descrizione dell'immagine

Come risolviamo questo problema? C'è una soluzione alternativa comune in questo post .

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


Ho lo stesso problema che ho usato un ViewPager nel frammento padre che contiene altri frammenti come schede. Ho provato a usare il problema del frammento nidificato ma ho finito con errori di compilazione. Puoi suggerirmi la soluzione? Anche qui
ho

Ho risposto su github, quindi spostiamo questa conversazione fuori di qui github.com/shamanland/nested-fragment-issue/issues/…
Oleksii K.

Grazie! Se non è una soluzione consigliata, suggerisco di modificare la risposta di conseguenza in modo da non dover passare il tempo a provare questo per sapere che ha errori di compilazione.
cgr

44

Questo è uno dei problemi più popolari. Possiamo trovare molte discussioni su questo problema. Ma nessuno di questi è utile per me.

Quindi ho risolto questo problema usando questa soluzione.

Per prima cosa capiamo perché questo sta accadendo.

Possiamo chiamare startActivityForResultdirettamente dal frammento, ma in realtà i meccanici dietro sono tutti gestiti dall'attività.

Una volta che chiami startActivityForResult da un frammento, requestCode verrà modificato per allegare l'identità del frammento al codice. Ciò consentirà ad Activity di rintracciare chi ha inviato questa richiesta una volta ricevuto il risultato.

Dopo che l'attività è stata ripristinata, il risultato verrà inviato a onActivityResult di Activity con il requestCode modificato che verrà decodificato in requestCode originale + identità del frammento. Successivamente, Activity invierà il risultato dell'attività a quel frammento tramite onActivityResult. Ed è tutto fatto.

Il problema è:

L'attività può inviare il risultato solo al frammento che è stato attaccato direttamente all'attività ma non a quello nidificato. Questo è il motivo per cui onActivityResult di frammento nidificato non sarebbe mai stato chiamato, indipendentemente da cosa.

Soluzione:

1) Inizia Intent nel tuo frammento dal seguente codice:

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

2) Ora nella sostituzione Attività genitore **onActivityResult() : **

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

Devi chiamarlo nell'attività genitore per farlo funzionare.

3) Nel tuo frammento di chiamata:

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

       }
}

Questo è tutto. Con questa soluzione, potrebbe essere applicato per ogni singolo frammento, sia esso annidato o meno. E sì, copre anche tutto il caso! Inoltre, i codici sono anche belli e puliti.


Stavo richiedendo l'intento di sistema con "attività", dovevo solo usare il contesto dei frammenti.
Uzair

18

PER MOLTI FRAMMENTI NIDATI (ad esempio, quando si utilizza un ViewPager in un frammento)

Nella tua attività principale :

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

Nel tuo frammento:

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

Nel tuo frammento nidificato

Attività di chiamata

getParentFragment().startActivityForResult(intent, uniqueInstanceInt);

uniqueInstanceInt : sostituiscilo con un int univoco tra i frammenti nidificati per impedire a un altro frammento di trattare la risposta.

Ricevi risposta

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

Attenzione

È necessario utilizzare un numero compreso tra 0 e 65536 in uniqueInstanceInt per evitare errori "Può utilizzare solo 16 bit inferiori per requestCode".


Funziona alla grande in Attività> Frammento (ViewPager)> Frammento
Oleksandr Firsov

14

Posso aggiungere due consigli se qualcuno ancora non ce la fa. Nel file Manifest.xml, assicurati che l'attività di hosting non sia terminata quando la richiamata e che l'attività da avviare abbia la modalità di avvio standard. Vedi i dettagli come di seguito:

Per l'attività di hosting, impostare la proprietà no history su false se have

android:noHistory="false"

Per avviare l'attività, impostare la modalità di avvio come standard, se presente

android:launchMode="standard"

13

Stavo anche affrontando lo stesso problema una volta spostato questo blocco di codice fuori da un frammento in una classe di utilità , con parentActivitypassato come argomento ,

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

Quindi non ottenevo alcun valore nel onActivityResultmetodo di quel frammento , poi ho cambiato l' argomento in frammento , quindi la definizione rivista di metodo sembrava,

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

Dopo ciò, sono stato in grado di ottenere valore onActivityResultsul frammento


10

Ho anche riscontrato questo problema in un frammento. E ho chiamato startActivityForResulta DialogFragment.

Ma ora questo problema è stato risolto:
FragmentClassname.this.startActivityForResult .


Grande, ha funzionato per me, perché stavo chiamando startActivityForResult(...)da una classe astratta all'interno del codice del frammento.
Vince il

9

PER FRAMMENTI NIDATI (ad esempio, quando si utilizza un ViewPager)

Nella tua attività principale:

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

Nel frammento di livello principale principale (frammento 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);
}

In YourFragment (frammento nidificato):

public void yourMethod(Intent data){
    // Do whatever you want with your data
}

8

Nel mio caso si trattava di un bug Android ( http://technet.weblineindia.com/mobile/onactivityresult-not-getting-called-in-nested-fragments-android/ ), se usi supportati FragmentActivitydevi usare getSupportFragmentManagerinvece di getChildFragmentManager:

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

6

In breve,

In frammento, dichiarare Fragment fragment = this;

dopo quell'uso fragment.startActivityForResult.

Il risultato verrà restituito in activityResult.


6

Soluzione 1:

Chiama startActivityForResult(intent, REQUEST_CODE);invece di getActivity().startActivityForResult(intent, REQUEST_CODE);.

Soluzione 2:

Quando startActivityForResult(intent, REQUEST_CODE);viene chiamato l'attività onActivityResult(requestCode,resultcode,intent)viene invocata e quindi è possibile chiamare fragments onActivityResult()da qui, passando il requestCode, resultCode and intent.


5

All'interno del tuo frammento, chiama

this.startActivityForResult(intent, REQUEST_CODE);

dove thissi riferisce al frammento. Altrimenti, come ha detto @Clevester:

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

Ho anche dovuto chiamare

super.onActivityResult(requestCode, resultCode, data);

nelle attività dei genitori onActivityResultper farlo funzionare.

(Ho adattato questa risposta dalla risposta di @ Clevester.)


5

Per coloro che utilizzano Android di navigazione componente da usare in attività onActivityResult(...)della primaryNavigationFragmentper ottenere che sia di riferimento frammento e frammento di chiamata fragment.onActivityResult(...).

Ecco l'attività 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);
    }
}

4

La maggior parte di queste risposte continua a dire che devi chiamare il super.onActivityResult(...)tuo host Activityper il tuoFragment . Ma questo non sembrava funzionare per me.

Quindi, nel tuo host Activitydovresti chiamare Fragments onActivityResult(...)invece il tuo . Ecco un esempio

public class HostActivity extends Activity {

    private MyFragment myFragment;

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

Ad un certo punto HostActivity, dovrai assegnare this.myFragmentquello Fragmentche stai utilizzando. Oppure, usa il FragmentManagerper ottenere il Fragmentinvece di mantenere un riferimento ad esso nel tuo HostActivity. Inoltre, controlla nullprima di provare a chiamare il this.myFragment.onActivityResult(...);.


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

3
  1. Puoi semplicemente ignorare BaseActivity onActivityResultsul frammento baseActivity.startActivityForResult.

  2. Su BaseActivity aggiungere l'interfaccia e sovrascrivere 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. Sugli attrezzi per frammenti 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();
      }
    }

Questa soluzione risolverà il problema.


3

Se il problema sopra riportato si presenta all'accesso di Facebook, è possibile utilizzare il codice seguente in un'attività principale del frammento come:

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

O:

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

E aggiungi la chiamata sotto nel tuo frammento ...

callbackManager.onActivityResult(requestCode, resultCode, data);

2

Un altro caso d'uso non già descritto in altre risposte:

onActivityResult()dichiarato in frammento non viene invocato quando si utilizza exception.startResolutionForResult():

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

In questo caso sostituire exception.startResolutionForResult()con frammenti startIntentSenderForResult():

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

2

Versione di Kotlin (Nella tua attività onActivityResult ())

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


1

Ho il forte sospetto che tutte le risposte qui non siano altro che hack. Li ho provati tutti e molti altri, ma senza alcuna conclusione attendibile in quanto c'è sempre una sorta di stupido problema. Io per primo non posso fare affidamento su risultati incoerenti. Se guardi la documentazione ufficiale dell'API Android per Fragments vedrai che Google afferma chiaramente quanto segue:

Chiama startActivityForResult (Intent, int) dall'attività contenente il frammento.

Vedere: API per frammenti Android

Quindi, sembrerebbe che l'approccio più corretto e affidabile sarebbe effettivamente chiamare startActivityForResult () dall'attività di hosting e anche gestire il risultante onActivityResult () da lì.


2
Non credo che "call startActivityForResult from Activity" sia una raccomandazione. Se guardi l'implementazione all'interno della classe base di Fragment, allora tutto ciò che fa è mActivity.startActivityFromFragment(this, intent, requestCode)- quindi non è altro che un comodo wrapper
Anti Veeranna

1

Il tuo codice ha un frammento nidificato. Chiamare super.onActivityForResult non funziona

Non vuoi modificare tutte le attività da cui il tuo frammento può essere chiamato e / o fare un lavoro per chiamare ogni frammento nella catena di frammenti.

Ecco una delle tante soluzioni di lavoro. creare un frammento al volo e collegarlo direttamente all'attività con il gestore frammento di supporto. Quindi chiama startActivityForResult dal frammento appena creato.

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

In realtà funziona e ho solo un voto per questo. Crea un frammento al volo. Troppo facile ma la sua vera soluzione di lavoro. Qualcuno ha persino provato a modificarlo per me.
danny117,

1

Il mio problema era con l'attività dell'host L'ho trovato con un set L' android:launchMode="standard"ho rimosso temporaneamente e funzionava!


1

Un punto che nessuno ha mentionche si assicura che la modalità di avvio dell'attività dell'host non deve essere impostata su singleInstanceo singleTask.

onActivityResult non funzionerà se la modalità di avvio è impostata su SingleInstance o SingleTask. oppure chiami la tua attività usando questi IntentFilters

standardo la singleTopmodalità di avvio funzionerà bene.


1

Se stai usando frammenti nidificati, funziona anche:

getParentFragment().startActivityForResult(intent, RequestCode);

Inoltre, devi chiamare super.onActivityResultdall'attività principale e compilare il onActivityResultmetodo del frammento.


1

Ho risolto il problema scrivendo una classe base che si estende Fragmente onactivityresultnell'attività ho identificato il frammento attualmente in esecuzione usando il fragmenttag. Quindi chiamo un metodo definito dall'utente nella classe fragmentbase. Questo genererà un evento nel frammento attualmente in esecuzione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.