onActivityResult nie jest wywoływany we fragmencie

877

Działanie, w którym znajduje się ten fragment, ma swoją onActivityResultnazwę, gdy powraca aktywność kamery.

Mój fragment rozpoczyna działanie dla rezultatu z zamiarem wysłania zdjęcia do aparatu. Aplikacja do obrazu ładuje się dobrze, robi zdjęcie i wraca. onActivityResultJednak nigdy nie jest trafiony. Ustawiłem punkty przerwania, ale nic się nie uruchamia. Czy fragment może mieć onActivityResult? Tak mi się wydaje, ponieważ jest to zapewniona funkcja. Dlaczego to się nie uruchamia?

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
źródło
2
sprawdź ten post, jest opis problemu i typowe rozwiązanie obejścia: stackoverflow.com/questions/6147884/...
Oleksii K.
5
Każdy, kto to czyta, upewnij się, że zdałeś requestCode >= 0!
Muhammad Babar
3
Upewnij się również, że twój Activity LauchMode nie może singleInstance lub singleTask. w przeciwnym razie onActivityResult nie zadzwoni
Jawad Zeb
Zobacz ten link może ci pomóc: androidtutorialonline.com/onactivityresult-in-fragment
Android Tutorial
Musimy przekierować onActivityResult w działaniu do fragmentu. Zobacz ten link: codexpedia.com/android/…
Reejesh PK

Odpowiedzi:

1239

Działalność hostingu zastępuje onActivityResult(), ale nie super.onActivityResult()wywołała nieobsługiwanych kodów wynikowych. Najwyraźniej, mimo że fragment jest tym, który wykonuje startActivityForResult()połączenie, aktywność otrzymuje pierwsze podejście do obsługi wyniku. Ma to sens, gdy weźmie się pod uwagę modułowość fragmentów. Kiedy zaimplementowałem super.onActivityResult()dla wszystkich nieobsługiwanych wyników, fragment miał szansę na obsługę wyniku.

A także z odpowiedzi @siqing:

Aby uzyskać wynik w swoim fragmencie, upewnij się, że dzwonisz startActivityForResult(intent,111);zamiast getActivity().startActivityForResult(intent,111);w swoim fragmencie.

Spidy
źródło
34
W swojej aktywności onActivityResult wywołaj super.onActivityResult ()
Spidy
167
@StErMi Upewnij się, że wywołujesz startActivityForResult (), a nie getActivity (). StartActivityForResult () ze swojego fragmentu. Zobacz odpowiedź siqing poniżej.
OferR
8
Wygląda na to, że występuje powiązany błąd, w którym używana jest biblioteka obsługi code.google.com/p/android/issues/detail?id=15394
Ollie C
82
Zauważ też, że jeśli używasz zagnieżdżonych fragmentów, fragment potomny powinien wywołać, getParentFragment().startActivityForResultaby fragment nadrzędny miał wywołaną metodę onActivityResult.
Eric Brynsvold,
7
@EricBrynsvold miał rację, startActivityForResult nie działa w zagnieżdżonych fragmentach. W tym celu lepiej wywołać getParentFragment (). StartActivityForResult (), a w tym fragmencie nadrzędnym można zaimplementować onActivityResult () i w tej metodzie dostarczyć wynik do fragmentów potomnych, tj .: childFragment.getParentFragment (). onActivityResult (requestCode, resultCode, data)
edrian
328

Myślę, że zadzwoniłeś getActivity().startActivityForResult(intent,111);. Powinieneś zadzwonić startActivityForResult(intent,111);.

siqing
źródło
3
Miałem również ten sam problem z RingtonePreferencelokalizacją w PreferenceFragment. Niestety RingtonePreferencedzwoni getActivity().startActivityForResult()i nie otrzymałem wyników, mimo że dzwonię super.onActivityResultdo działania onActivityResult. Byłem zmuszony stworzyć pochodną z RingtonePreferenceklasy, która wiąże się z PreferenceFragmentwywołaniami i fragment.startActivityForResult().
Stan
@siqing Nie jestem w stanie wywołać startActivitForResult z mojej metody statycznej. Jakieś rozwiązanie tego? Potrzebuję użyć activity.startActivityForResult. Proszę, pomóżcie mi w tym
Shreyash Mahajan,
269

Opcja 1:

Jeśli dzwonisz startActivityForResult()z fragmentu, powinieneś zadzwonić startActivityForResult(), niegetActivity().startActivityForResult() , ponieważ spowoduje to fragment onActivityResult ().

Jeśli nie masz pewności, gdzie dzwonisz startActivityForResult()i jak będziesz dzwonić metodami.

Opcja 2:

Ponieważ działanie otrzymuje wynik onActivityResult(), musisz zastąpić działanie onActivityResult()i wywołać super.onActivityResult()propagację do odpowiedniego fragmentu dla nieobsługiwanych kodów wyników lub dla wszystkich.

Jeśli powyższe dwie opcje nie działają, zapoznaj się z opcją 3, ponieważ na pewno zadziała.

Opcja 3:

Wyraźne wywołanie z fragmentu do funkcji onActivityResult jest następujące.

W nadrzędnej klasie Activity należy zastąpić metodę onActivityResult (), a nawet zastąpić ją w klasie Fragment i wywołać jako poniższy kod.

W klasie nadrzędnej:

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

W klasie dziecięcej:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // In fragment class callback
}
Vinayak
źródło
4
To zadziałało dla mnie. To paskudne obejście, ale nie mam lepszego pomysłu na rozwiązanie tego idiotycznego błędu ...
Bogdan Zurac,
@Vivky, Twoja odpowiedź zadziałała dla mnie. Ale mam jeszcze jeden problem, zamiast tego, setResult(); finish();kiedy odsuwam się od drugiej aktywności, wtedy onActivityResultzostaje również wywołany z pod warunkiem RESULT_CODE.
snehal_penurkar
doskonała odpowiedź. Wdrożyłem trzecie rozwiązanie, aby to zrobić.
Sash_KP
Wydaje mi się, że rozwiązanie 3 zadziałałoby dla mnie, ale onActivityResult()działanie zwraca wartość dziwną, requestCodektóra jest przekazywana do mojego fragmentu, a następnie ignorowana = /
E-Kami
1
@notGeek Masz rację. Wynik jest zawsze otrzymywany w Aktywności, nawet jeśli zadzwoniłeś z fragmentu lub aktywności.
Vinayak,
83

Jeśli nie znasz fragmentów swojej aktywności, po prostu wylicz je wszystkie i wyślij argumenty wyniku działania:

// 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
źródło
3
Cholera, myślałem, że właśnie znalazłem najprostsze rozwiązanie, ale nie ma takiej metody jak getFragments ().
WindRider
2
@WindRider Jest. Jeśli korzystasz z biblioteki obsługi Androida (AppCompat).
dasar
2
Nauczyłem się też na własnej skórze, że musisz sprawdzić, czy fragment w tablicy nie jest odniesieniem do siebie! `if (fragment! = this) {fragment.onActivityResult (requestCode, resultCode, data); `
reubenjohn
To nie działa, jeśli fragmenty są zagnieżdżone, ponieważ tylko górny fragment będzie na liście. Wierzę, że super.onActivityResult () już wywołuje onActivityResult () na wszystkich fragmentach listy, więc ten pomysł jest zbędny.
BeccaP,
83

Mam ten sam problem z ChildFragmentManager. Menedżer nie przekaże wyniku do zagnieżdżonego fragmentu, musisz to zrobić ręcznie we fragmencie podstawowym.

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
źródło
1
Jeśli posiadasz Fragment podrzędny jako członek prywatny, użyj przycisku, Fragment fragment = myChildFragment;aby zastąpić powyższą findFragmentByTaglinię kodu. Resztę można zachować bez zmian.
lcn
7
Chyba zdecydowanie odradzam trzymanie tego fragmentu jako członka prywatnego. Mają własny cykl życia, więc nigdy nie wiadomo, czy są w dobrym stanie do interakcji, robi to kierownik. Są też dość mocni i martwiłbym się o wycieki pamięci. Menedżer nie zostałby utworzony, gdybyś nie musiał go używać.
MinceMan,
67

Oryginalny post.

FragmentActivityzastępuje requestCodezmodyfikowanym. Następnie, kiedy onActivityResult()zostanie wywołany, FragmentActivityanalizuje wyższe 16 bitów i przywraca indeks oryginalnego fragmentu. Spójrz na ten schemat:

Wpisz opis zdjęcia tutaj

Jeśli masz kilka fragmentów na poziomie katalogu głównego, nie ma żadnych problemów. Ale jeśli masz zagnieżdżone fragmenty , na przykład Fragmentz kilkoma zakładkami w środku ViewPager, masz gwarancję , że napotkasz problem (lub już się z nim spotkałeś).

Ponieważ w środku jest przechowywany tylko jeden indeksrequestCode . To jest indeks Fragmentjego wnętrza FragmentManager. Kiedy używamy zagnieżdżonych fragmentów, istnieją dzieci FragmentManager, które mają własną listę fragmentów. Konieczne jest więc zapisanie całego łańcucha indeksów, poczynając od katalogu głównego FragmentManager.

Wpisz opis zdjęcia tutaj

Jak rozwiązujemy ten problem? W tym poście jest typowe rozwiązanie obejścia .

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

Oleksii K.
źródło
Mam taki sam problem, jak użyłem ViewPager we fragmencie nadrzędnym, który przechowuje inne fragmenty jako tabulatory. Próbowałem użyć problemu z zagnieżdżonym fragmentem, ale zakończyło się to błędami kompilacji. Czy możesz zasugerować mi rozwiązanie? Podniesiono także problem
cgr
Odpowiedziałem na github, więc przenieśmy stąd tę rozmowę github.com/shamanland/nested-fragment-issue/issues/…
Oleksii K.
Dzięki! Jeśli nie jest to zalecane rozwiązanie, proponuję odpowiednio zmodyfikować odpowiedź, aby nie trzeba było tracić czasu na próbę sprawdzenia, czy zawiera ona błędy kompilacji.
cgr
44

To jeden z najpopularniejszych problemów. Możemy znaleźć wiele wątków na ten temat. Ale żaden z nich nie jest użyteczny dla MNIE.

Rozwiązałem ten problem za pomocą tego rozwiązania.

Najpierw zrozummy, dlaczego tak się dzieje.

Możemy startActivityForResultsprawdzać bezpośrednio z Fragmentu, ale tak naprawdę mechanika z tyłu jest obsługiwana przez Aktywność.

Kiedy zadzwonisz startActivityForResult z fragmentu, requestCode zostanie zmieniony, aby dołączyć tożsamość fragmentu do kodu. Pozwoli to Activity śledzić, kto wysłał to żądanie po otrzymaniu wyniku.

Po cofnięciu działania, wynik zostanie wysłany do działania onActivityResult ze zmodyfikowanym kodem requestCode, który zostanie zdekodowany do pierwotnego kodu requestCode + fragmentu. Następnie działanie wyśle ​​wynik działania do tego fragmentu za pośrednictwem onActivityResult. I wszystko skończone.

Problemem jest:

Aktywność może wysłać wynik tylko do fragmentu, który został dołączony bezpośrednio do działania, ale nie do zagnieżdżonego. To jest powód, dla którego onActivityResult zagnieżdżonego fragmentu nigdy nie zostałby nazwany bez względu na wszystko.

Rozwiązanie:

1) Rozpocznij zamiar w swoim fragmencie, wykonując poniższy kod:

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

2) Teraz w zastąpieniu Aktywności nadrzędnej **onActivityResult() : **

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

Musisz wywołać to w działaniu nadrzędnym, aby to zadziałało.

3) W wywołaniu fragmentu:

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

       }
}

Otóż ​​to. Dzięki temu rozwiązaniu można go zastosować do każdego pojedynczego fragmentu, niezależnie od tego, czy jest zagnieżdżony czy nie. I tak, obejmuje to również całą sprawę! Co więcej, kody są również ładne i czyste.

KishuDroid
źródło
Prosiłam o zamiar systemu „aktywnością”, musiałem po prostu użyć fragmentu kontekstu.
Uzair
18

DLA WIELU ZNISZCZONYCH FRAGMENTÓW (na przykład podczas korzystania z ViewPager we fragmencie)

W swojej głównej działalności :

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

W twoim fragmencie:

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

W zagnieżdżonym fragmencie

Zadzwoń do aktywności

getParentFragment().startActivityForResult(intent, uniqueInstanceInt);

UniqueInstanceInt - zamień go na int, który jest unikalny wśród zagnieżdżonych fragmentów, aby zapobiec traktowaniu odpowiedzi przez inny fragment.

Otrzymać odpowiedź

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

Uwaga

Aby uniknąć błędu, należy użyć liczby od 0 do 65536 w unikatowejInstanceInt, aby uniknąć błędu „Można użyć tylko 16 mniejszych bitów dla kodu żądania”.

Luciano Marqueto
źródło
Działa świetnie w Aktywność> Fragment (ViewPager)> Fragment
Oleksandr Firsov
14

Mogę dodać dwie porady, jeśli ktoś nadal nie może tego zrobić. W pliku Manifest.xml upewnij się, że działanie hostingu nie zakończyło się po oddzwonieniu, a działanie do uruchomienia ma standardowo tryb uruchamiania. Zobacz szczegóły jak poniżej:

W przypadku działalności Hosting ustaw właściwość no history na false, jeśli tak

android:noHistory="false"

Aby rozpocząć działanie, ustaw tryb uruchamiania jako standard, jeśli masz

android:launchMode="standard"
Jowett
źródło
13

Miałem również ten sam problem, kiedy przeniosłem ten blok kodu poza fragment do klasy użyteczności , parentActivityprzekazując go jako argument ,

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

Wtedy nie otrzymałem żadnej wartości w onActivityResultmetodzie tego fragmentu , potem zmieniłem argument na Fragment , więc zmieniona definicja metody wyglądała następująco:

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

Potem udało mi się uzyskać wartość w onActivityResultsprawie Fragment

Shamsul Arefin Sajib
źródło
10

Problem ten spotkałem również we fragmencie. I zadzwoniłem startActivityForResultdo DialogFragment.

Ale teraz ten problem został rozwiązany:
FragmentClassname.this.startActivityForResult .

Courysky
źródło
Świetnie, działało dla mnie, ponieważ dzwoniłem startActivityForResult(...)z klasy abstrakcyjnej w kodzie fragmentu.
Vince,
9

DLA NESTED FRAGMENTS (na przykład podczas korzystania z ViewPager)

W swojej głównej działalności:

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

W głównym fragmencie najwyższego poziomu (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);
}

W YourFragment (zagnieżdżony fragment):

public void yourMethod(Intent data){
    // Do whatever you want with your data
}
Jyotman Singh
źródło
8

W moim przypadku był to błąd Androida ( http://technet.weblineindia.com/mobile/onactivityresult-not-get-getting-called-in-nested-fragments-android/ ), jeśli używasz obsługiwanego FragmentActivity, musisz użyć getSupportFragmentManagerzamiast getChildFragmentManager:

List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments != null) {
    for (Fragment fragment : fragments) {
        if(fragment instanceof UserProfileFragment) {
            fragment.onActivityResult(requestCode, resultCode, data);
        }
    }
}
Hazlo8
źródło
6

W skrócie,

We fragmencie deklaruj Fragment fragment = this;

po tym użyciu fragment.startActivityForResult.

Wynik powróci w activityResult.

Clevester
źródło
6

Rozwiązanie 1:

Zadzwoń startActivityForResult(intent, REQUEST_CODE);zamiast getActivity().startActivityForResult(intent, REQUEST_CODE);.

Rozwiązanie 2:

Kiedy startActivityForResult(intent, REQUEST_CODE);się nazywa, onActivityResult(requestCode,resultcode,intent)wywoływana jest aktywność , a następnie możesz zadzwonić fragments onActivityResult()stąd, przekazując requestCode, resultCode and intent.

Amey Haldankar
źródło
5

Zadzwoń do swojego fragmentu

this.startActivityForResult(intent, REQUEST_CODE);

gdzie thisodnosi się do fragmentu. W przeciwnym razie wykonaj, jak powiedział @Clevester:

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

Musiałem także zadzwonić

super.onActivityResult(requestCode, resultCode, data);

w działaniu nadrzędnym, onActivityResultaby działało.

(Dostosowałem tę odpowiedź z odpowiedzi @ Clevester.)

Suragch
źródło
5

Dla tych, którzy korzystają z Android Nawigacja Komponent powinien używać w aktywny na dostać to fragment odniesienia i na wezwanie fragment .onActivityResult(...)primaryNavigationFragmentfragment.onActivityResult(...)

Oto aktywność 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
źródło
4

Większość z tych odpowiedzi wciąż powtarzają, że trzeba zadzwonić super.onActivityResult(...)w hosta Activitydla TwojegoFragment . Ale to chyba nie działało dla mnie.

Więc w swoim hoście Activitypowinieneś zadzwonić Fragments onActivityResult(...)zamiast tego. Oto przykład.

public class HostActivity extends Activity {

    private MyFragment myFragment;

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

W pewnym momencie swojego HostActivitytrzeba będzie przypisać używasz. Lub użyj, aby uzyskać zamiast trzymać odniesienie do niego w swoim . Sprawdź także, zanim spróbujesz zadzwonić .this.myFragmentFragmentFragmentManagerFragmentHostActivitynullthis.myFragment.onActivityResult(...);

prolink007
źródło
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
źródło
3
  1. Możesz po prostu zastąpić BaseActivity onActivityResultna fragmencie baseActivity.startActivityForResult.

  2. W BaseActivity dodaj interfejs i przesłoń 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. Narzędzie Fragment 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();
      }
    }

To obejście załatwi sprawę.

Khaled Lela
źródło
3

Jeśli napotkasz powyższy problem przy logowaniu na Facebooku , możesz użyć poniższego kodu w czynności nadrzędnej swojego fragmentu, takiej jak:

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

Lub:

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

I dodaj poniższe wezwanie w swoim fragmencie ...

callbackManager.onActivityResult(requestCode, resultCode, data);
Ketan Patel
źródło
2

Kolejny przypadek użycia, który nie został jeszcze opisany w innych odpowiedziach:

onActivityResult()zadeklarowane we fragmencie nie jest wywoływane przy użyciu exception.startResolutionForResult():

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

W takim przypadku zastąp exception.startResolutionForResult()fragmentem startIntentSenderForResult():

if (exception is ResolvableApiException) {
    startIntentSenderForResult(exception.resolution.intentSender, MY_REQUEST_CODE, null, 0, 0, 0, null)
}
dominik
źródło
2

Wersja Kotlin (W twojej aktywności 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)
    }
 }
Ranjith Kumar
źródło
1

Mam głębokie podejrzenie, że wszystkie odpowiedzi tutaj są niczym innym jak hackami. Próbowałem ich wszystkich i wielu innych, ale bez żadnych wiarygodnych wniosków, ponieważ zawsze istnieje jakiś głupi problem. Nie mogę polegać na niespójnych wynikach. Jeśli spojrzysz na oficjalną dokumentację API Androida dla Fragmentów, zobaczysz, że Google wyraźnie stwierdza, co następuje:

Wywołaj startActivityForResult (Intent, int) z fragmentu zawierającego działanie.

Zobacz: Android Fragment API

Wydaje się więc, że najbardziej poprawnym i niezawodnym podejściem byłoby faktycznie wywołanie metody startActivityForResult () z działania hosta, a także obsłużenie wynikowej funkcji onActivityResult () .

Chris
źródło
2
Nie sądzę, aby „call startActivityForResult from Activity” było zaleceniem. Jeśli spojrzysz na implementację w klasie bazowej Fragment, to wszystko, co robi, to mActivity.startActivityFromFragment(this, intent, requestCode)- więc nie jest to nic innego, jak wygodne opakowanie
Anti Veeranna
1

Twój kod ma zagnieżdżony fragment. Wywołanie super.onActivityForResult nie działa

Nie chcesz modyfikować wszystkich działań, z których można wywoływać twój fragment, ani nie pracować nad wywołaniem każdego fragmentu w łańcuchu fragmentów.

Oto jedno z wielu działających rozwiązań. utwórz fragment w locie i połącz go bezpośrednio z działaniem za pomocą menedżera fragmentów wsparcia. Następnie wywołaj startActivityForResult z nowo utworzonego fragmentu.

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
źródło
To faktycznie działa i mam na to tylko jeden głos. Utwórz fragment w locie. Zbyt łatwe, ale to naprawdę działające rozwiązanie. Ktoś nawet próbował go dla mnie edytować.
danny117
1

Mój problem polegał na działaniu hosta. Znalazłem go z zestawem. android:launchMode="standard"Usunąłem go tymczasowo i działa!

Chulo
źródło
1

Nikt nie ma mentionpewności, że tryb uruchamiania działania hosta nie może być ustawiony na singleInstancelub singleTask.

onActivityResult nie będzie działać, jeśli tryb uruchamiania ustawiony jest na SingleInstance lub SingleTask. lub nazywasz swoją aktywność za pomocą IntentFilters

standardlub singleToptryb uruchamiania będzie działał dobrze.

Jawad Zeb
źródło
1

Jeśli używasz zagnieżdżonych fragmentów, działa to również:

getParentFragment().startActivityForResult(intent, RequestCode);

Oprócz tego musisz zadzwonić super.onActivityResultz aktywności rodzica i wypełnić onActivityResultmetodę fragmentu.

Oguz Ozcan
źródło
1

Poradziłem sobie z tym, pisząc klasę podstawową, która się rozszerza Fragment, aw onactivityresultramach działania zidentyfikowałem aktualnie działający fragment za pomocą fragmenttag. Następnie wywołuję metodę zdefiniowaną przez użytkownika w klasie fragmentbase. Spowoduje to uruchomienie zdarzenia w aktualnie uruchomionym fragmencie.

Kod bajtowy
źródło