onActivityResult не викликається у фрагменті


877

Активність, що розміщує цей фрагмент, onActivityResultназивається, коли активність камери повертається.

Мій фрагмент запускає активність для отримання результату із наміром, надісланим камерою зробити фотографування. Додаток для зображення завантажує чудово, робить знімок та повертається. onActivityResult, Однак , ніколи не бив. Я встановив точки прориву, але нічого не спрацьовує. Може фрагмент має onActivityResult? Я б так вважав, оскільки це передбачена функція. Чому це не спрацьовує?

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
Перевірте цю публікацію, є опис проблеми та поширене рішення вирішення: stackoverflow.com/questions/6147884/…
Олексій К.

5
Хто-небудь ще, хто читає це, переконайтеся, що ви пройшли requestCode >= 0!
Мухаммед Бабар

3
Також переконайтеся, що у вашій діяльності LauchMode не повинно діяти singleInstance або singleTask. в іншому випадку onActivityResult не називатиметься
Jawad Zeb

Переглянути це посилання може допомогти вам: androidtutorialonline.com/onactivityresult-in-fragment
Підручник для Android

Нам потрібно перенаправити onActivityResult у діяльності на Фрагмент. Перейдіть за цим посиланням: codexpedia.com/android/…
Reejesh PK

Відповіді:


1239

Активність хостингу переосмислюється onActivityResult(), але він не робив заклик до не super.onActivityResult()оброблених кодів результатів. Мабуть, незважаючи на те, що фрагмент є тим, хто здійснює startActivityForResult()дзвінок, активність отримує перший знімок при обробці результату. Це має сенс, якщо врахувати модульність фрагментів. Після того, як я реалізував super.onActivityResult()усі незроблені результати, фрагмент отримав знімок при обробці результату.

А також з відповіді @siqing:

Щоб отримати результат у своєму фрагменті, переконайтесь, що ви телефонуєте startActivityForResult(intent,111);замість getActivity().startActivityForResult(intent,111);його.


34
У програмі onActivityResult викличте super.onActivityResult ()
Spidy

167
@StErMi Переконайтеся, що ви викликаєте свій фрагмент startActivityForResult (), а не getActivity (). StartActivityForResult () зі свого фрагмента. Дивіться відповідь про занурення нижче.
OferR

8
Здається, пов’язана помилка, де використовується бібліотека підтримки code.google.com/p/android/isissue/detail?id=15394
Ollie C

82
Також зауважте, що якщо ви використовуєте вкладені фрагменти, дочірній фрагмент повинен викликати getParentFragment().startActivityForResultтак, щоб батьківський фрагмент називав його метод onActivityResult.
Ерік Брінсвольд

7
@EricBrynsvold мав рацію, startActivityForResult не працює у вкладених фрагментах. Для цього вам краще зателефонувати getParentFragment (). StartActivityForResult (), і в цьому батьківському фрагменті ви можете реалізувати onActivityResult () і в цьому методі доставити результат дочірнім фрагментам, тобто: childFragment.getParentFragment (). onActivityResult (requestCode, resultCode, data)
edrian

328

Я думаю, ти зателефонував getActivity().startActivityForResult(intent,111);. Вам слід зателефонувати startActivityForResult(intent,111);.


3
У мене також була така ж проблема, що RingtonePreferenceзнаходиться в PreferenceFragment. На жаль, RingtonePreferenceдзвінки getActivity().startActivityForResult(), і я не отримав результатів, хоча зателефонував super.onActivityResultу діяльність onActivityResult. Мене змусили створити похідне від RingtonePreferenceкласу, яке прив'язується до PreferenceFragmentі називає fragment.startActivityForResult().
Стен

@siqing Я не в змозі викликати startActivitForResult зі свого статичного методу. Будь-яке рішення для цього? Мені потрібно використовувати Activity.startActivityForResult. Будь ласка, допоможіть мені в цьому
Шреяш Махаджан

269

Варіант 1:

Якщо ви телефонуєте startActivityForResult()з фрагмента, тоді вам слід зателефонувати startActivityForResult(), а не getActivity().startActivityForResult(), оскільки це призведе до фрагменту onActivityResult ().

Якщо ви не впевнені, куди дзвоните startActivityForResult()та як будете телефонувати.

Варіант 2:

Оскільки Діяльність отримує результат onActivityResult(), вам потрібно буде переосмислити активність onActivityResult()і закликати super.onActivityResult()поширюватися на відповідний фрагмент для необроблених кодів результатів або для всіх.

Якщо вище два варіанти не працюють, зверніться до варіанту 3, оскільки він обов'язково спрацює.

Варіант 3:

Явний виклик з фрагмента до функції onActivityResult полягає в наступному.

У батьківському класі активності замініть метод onActivityResult () і навіть замініть той самий у класі Fragment та зателефонуйте як наступний код.

У батьківському класі:

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

У дитячому класі:

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

4
Це працювало для мене. Це неприємне рішення, але я не маю кращої ідеї вирішити цю ідіотську помилку ...
Богдан Зурак

@Vivky, твоя відповідь працювала на мене. Але є ще одне питання, з яким я стикаюсь, замість того, setResult(); finish();коли я натискаю назад від другого заняття, то також onActivityResultвикликається за умови RESULT_CODE.
snehal_penurkar

чудова відповідь. Я реалізував третє рішення, щоб його виконати.
Sash_KP

Я думаю, що рішення 3 допоможе мені, але ця onActivityResult()діяльність повертається дивно, requestCodeяка передається моєму фрагменту, а потім ігнорується = /
E-Kami

1
@notGeek Ви маєте рацію. Результат завжди отримується в діяльності, навіть якщо ви подзвонили з фрагмента чи активності.
Виняк

83

Якщо ви не знаєте фрагментів у своїй діяльності, просто перелічіть їх усі та надішліть аргументи результатів діяльності:

// 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
Блін, я думав, що я просто знайшов найпростіше рішення, але немає такого методу, як getFragments ().
WindRider

2
@WindRider Є. Якщо ви використовуєте бібліотеку підтримки Android (AppCompat).
dasar

2
Крім того, я дізнався важкий спосіб, який вам доведеться перевірити, чи фрагмент у масиві не є посиланням на себе! `if (фрагмент! = це) {fragment.onActivityResult (requestCode, resultCode, дані); `
reubenjohn

Це не працює, якщо фрагменти вкладені, так як у списку буде лише верхній фрагмент. Я вважаю, що super.onActivityResult () вже викликаєActivityResult () на всіх фрагментах списку, тому ця ідея є зайвою.
BeccaP


83

У мене є ця сама проблема з ChildFragmentManager. Менеджер не передасть результат вкладеному фрагменту, це потрібно зробити вручну в базовому фрагменті.

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
Якщо у вас є фрагмент дитини як приватний член, використовуйте Fragment fragment = myChildFragment;для заміни вищевказаного findFragmentByTagрядка коду. Решту можна зберігати без змін.
lcn

7
Напевно, я б настійно не рекомендував зберігати фрагмент як приватного члена. У них є власний життєвий цикл, так що ви ніколи не знаєте, чи добре у них взаємодіяти, робить менеджер. Крім того, вони досить здоровенні, і мене б хвилювали витоки пам'яті. Менеджер не був би створений, якби не потрібно було ним користуватися.
MinceMan

67

Оригінальна публікація.

FragmentActivityзамінює requestCodeмодифікованим. Після цього, коли onActivityResult()буде викликано, FragmentActivityаналізує вищі 16 біт і відновлює індекс початкового фрагмента. Подивіться на цю схему:

Введіть тут опис зображення

Якщо у вас є кілька фрагментів на рівні кореня, проблем немає. Але якщо ви вклали фрагменти , наприклад, Fragmentкілька вкладок всередині ViewPager, ви гарантовано зіткнетеся з проблемою (або вже зіткнулися з нею).

Тому що всередині зберігається лише один індексrequestCode . Це показник Fragmentвсередині нього FragmentManager. Коли ми використовуємо вкладені фрагменти, є дочірні FragmentManagers, які мають власний список фрагментів. Отже, потрібно зберегти весь ланцюжок індексів, починаючи від кореня FragmentManager.

Введіть тут опис зображення

Як ми вирішуємо це питання? Існує поширений спосіб вирішення цій посаді .

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


У мене така ж проблема, як я використовував ViewPager у батьківському фрагменті, який містить інші фрагменти як вкладки. Спробували за допомогою випуску вкладеного фрагмента, але закінчилися помилками компіляції. Чи можете ви запропонувати мені рішення? Питання порушено і
cgr

Я відповів на github, тож давайте перенести цю розмову звідси github.com/shamanland/nested-fragment-issue/isissue/…
Олексій К.

Дякую! Якщо це не рекомендоване рішення, я пропоную відредагувати відповідь відповідно, щоб не потрібно витрачати час на тестування, щоб знати, чи є помилки компіляції.
cgr

44

Це одне з найпопулярніших питань. Про цю проблему ми можемо знайти багато тем. Але жоден з них не корисний для мене.

Тому я вирішив цю проблему, використовуючи це рішення.

Давайте спочатку розберемося, чому це відбувається.

Ми можемо зателефонувати startActivityForResultбезпосередньо з Fragment, але насправді механіка позаду все обробляє діяльність.

Як тільки ви телефонуєте startActivityForResult з фрагмента, codeCode буде змінено, щоб приєднати особу фрагмента до коду. Це дозволить Діяльності мати можливість відстежувати, хто надсилає цей запит, коли результат буде отриманий.

Після повернення Діяльність назад результат буде відправлений на onActivityResult діяльності з модифікованим кодом request, який буде декодований до оригінального ідентифікатора requestCode + фрагмента. Після цього активність надішле результат цього фрагмента через onActivityResult. І це все зроблено.

Проблема полягає в наступному:

Діяльність може надіслати результат лише тому Фрагменту, який був приєднаний безпосередньо до Діяльності, але не вкладеному. Ось чому причина onActivityResult вкладеного фрагмента ніколи б не називалася незалежно від того.

Рішення:

1) Почніть наміри у своєму фрагменті нижче за кодом:

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

2) Тепер у вашій батьківській активності переосмислюється **onActivityResult() : **

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

Ви повинні викликати це у батьківській діяльності, щоб він працював.

3) У дзвінку за фрагментом:

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

       }
}

Це воно. За допомогою цього рішення він може бути застосований для будь-якого окремого фрагмента, вкладений він чи ні. І так, це також охоплює всю справу! Більше того, коди також приємні та чисті.


Я запитував наміри системи з «активністю», я просто повинен був використовувати контекст фрагмента.
Uzair

18

ДЛЯ МНОГО ГОЛОВИХ ФРАГМЕНТІВ (наприклад, при використанні ViewPager у фрагменті)

У вашій основній діяльності :

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

У вашому фрагменті:

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

У вашому вкладеному фрагменті

Виклик активності

getParentFragment().startActivityForResult(intent, uniqueInstanceInt);

uniqueInstanceInt - замініть його на int, який є унікальним серед вкладених фрагментів, щоб запобігти обробці відповіді іншим фрагментом.

Отримати відповідь

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

Увага

Число від 0 до 65536 потрібно використовувати в uniqueInstanceInt, щоб помилка уникала "Можна використовувати лише нижчі 16 біт для requestCode".


Чудово працює в активності> Фрагмент (ViewPager)> Фрагмент
Олександр Фірсов

14

Я можу додати два поради, якщо хтось досі не може його зробити. У файлі Manifest.xml переконайтесь, що діяльність хостингу не закінчилася, коли передзвоніть, і активність, яку слід розпочати, має стандартний режим запуску. Деталі див. Нижче:

Для хостингової активності встановіть властивість no history як хибну, якщо є

android:noHistory="false"

Для активності для запуску встановіть режим запуску як стандартний, якщо є

android:launchMode="standard"

13

Я також зіткнувся з тією ж проблемою, як тільки я перемістив цей блок коду за межі фрагмента на клас утиліти , parentActivityпереданий як аргумент ,

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

Тоді я не отримував жодного значення в onActivityResultметоді цього фрагмента. Потім я змінив аргумент на Fragment , тому переглянуте визначення методу виглядало так,

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

Після цього я був в змозі отримати значення в onActivityResultна фрагменті


10

Я також зустрів цю проблему у Фрагменті. І я подзвонив startActivityForResultу DialogFragment.

Але тепер ця проблема вирішена:
FragmentClassname.this.startActivityForResult .


Чудово, працювали для мене, бо я телефонував startActivityForResult(...)із абстрактного класу всередині коду фрагмента.
Вінс

9

ДЛЯ ВНУТРЕННИХ ФРАГМЕНТІВ (наприклад, при використанні ViewPager)

У вашій основній діяльності:

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

У головному фрагменті верхнього рівня (фрагмент 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);
}

У вашомуFragment (вкладений фрагмент):

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

8

У моєму випадку це була помилка Android ( http://technet.weblineindia.com/mobile/onactivityresult-not-getting-called-in-nested-fragments-android/ ), якщо ви користуєтесь підтримкою, FragmentActivityви повинні використовувати getSupportFragmentManagerзамість getChildFragmentManager:

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

6

Коротко,

У фрагменті заявіть Fragment fragment = this;

після цього використання fragment.startActivityForResult.

Результат повернеться у ActivityResult.


6

Рішення 1:

Телефонуйте startActivityForResult(intent, REQUEST_CODE);замість getActivity().startActivityForResult(intent, REQUEST_CODE);.

Рішення 2:

Коли startActivityForResult(intent, REQUEST_CODE);викликається активність, onActivityResult(requestCode,resultcode,intent)викликається, а потім ви можете зателефонувати fragments onActivityResult()звідси, передаючи поле requestCode, resultCode and intent.


5

Всередині вашого фрагмента зателефонуйте

this.startActivityForResult(intent, REQUEST_CODE);

де thisпосилається на фрагмент. Інакше зробіть так, як сказав @Clevester:

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

Мені також довелося зателефонувати

super.onActivityResult(requestCode, resultCode, data);

в батьківській діяльності, onActivityResultщоб змусити його працювати.

(Я адаптував цю відповідь з відповіді @ Клівестра.)


5

Для тих , хто використовує Android навігація компоненти слід використовувати в даному виді діяльності , щоб отримати його фрагмент посилання і виклику осколка .onActivityResult(...)primaryNavigationFragmentfragment.onActivityResult(...)

Ось активність 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

Більшість з цих відповідей продовжують говорити , що ви повинні зателефонувати super.onActivityResult(...)в хост Activityдля вашого Fragment. Але це, схоже, не працювало на мене.

Тож у своєму хості Activityслід Fragments onActivityResult(...)замість цього зателефонувати . Ось приклад.

public class HostActivity extends Activity {

    private MyFragment myFragment;

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

В якій - то момент у вашому HostActivityвам потрібно буде призначити ви використовуєте. Або скористайтеся, щоб отримати замість того, щоб зберігати посилання на нього у своєму . Також перевірте, перш ніж спробувати зателефонувати .this.myFragmentFragmentFragmentManagerFragmentHostActivitynullthis.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. Ви можете просто замінити BaseActivity onActivityResultна фрагменті baseActivity.startActivityForResult.

  2. На BaseActivity додайте інтерфейс та замініть 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. На фрагментах реалізує 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();
      }
    }

Цей спосіб вирішить трюк.


3

Якщо вищевказана проблема зіткнулася при вході в Facebook, то ви можете використовувати наведений нижче код у батьківській діяльності вашого фрагмента, наприклад:

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

Або:

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

І додайте виклик нижче у свій фрагмент ...

callbackManager.onActivityResult(requestCode, resultCode, data);

2

Ще один випадок використання, який вже не описаний в інших відповідях:

onActivityResult()декларований у фрагменті не викликається при використанні exception.startResolutionForResult():

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

У цьому випадку замініть exception.startResolutionForResult()фрагмент startIntentSenderForResult():

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

2

Версія Котліна (У вашій діяльності 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

У мене є сильні підозри, що всі відповіді тут - це не що інше, як хакі. Я спробував їх усіх та багатьох інших, але без надійного висновку, оскільки завжди є якась дурна проблема. Я не можу розраховувати на непослідовні результати. Якщо ви подивитеся на офіційну документацію API для Android щодо фрагментів, ви побачите, що Google чітко визначає наступне:

Виклик startActivityForResult (Intent, int) з фрагмента, що містить Activity.

Подивитися: Android Fragment API

Отже, здавалося б, що найбільш правильним і надійним підходом було б насправді викликати startActivityForResult () з хостингової діяльності, а також обробляти отриманий onActivityResult () звідти.


2
Я не думаю, що "виклик startActivityForResult з діяльності" є рекомендацією. Якщо ви подивитесь на реалізацію всередині базового класу Fragment, то все, що це робиться, mActivity.startActivityFromFragment(this, intent, requestCode)- тож це не що інше, як обгортка зручності
Anti Veeranna

1

Ваш код має вкладений фрагмент. Виклик super.onActivityForResult не працює

Ви не хочете змінювати будь-яку діяльність, з якої може бути викликаний ваш фрагмент, або виконувати роботу щодо виклику кожного фрагмента в ланцюзі фрагментів.

Ось одне з багатьох робочих рішень. створіть фрагмент під час руху та підключіть його безпосередньо до діяльності за допомогою диспетчера підтримки фрагментів. Потім викличте startActivityForResult з новоствореного фрагмента.

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

1

Моя проблема була в хост-діяльності, я знайшов її набором, android:launchMode="standard"я видалив її тимчасово, вона працює!


1

Ніхто не має жодного пункту, mentionщоб переконатися, що для режиму запуску Host Activity не повинен бути встановлений singleInstanceабо singleTask.

onActivityResult не буде працювати, якщо для вашого режиму запуску встановлено SingleInstance або SingleTask. або ви називаєте свою діяльність за допомогою цих IntentFilters

standardабо singleTopрежим запуску буде добре працювати.


1

Якщо ви використовуєте вкладені фрагменти, це також працює:

getParentFragment().startActivityForResult(intent, RequestCode);

Крім цього, вам потрібно зателефонувати super.onActivityResultз батьківської діяльності та заповнити onActivityResultметод фрагмента.


1

Я вирішив проблему, написавши базовий клас, який розширюється Fragment, і в onactivityresultході діяльності я визначив фрагмент, що працює в даний час, використовуючи fragmenttag. Тоді я називаю визначений користувачем метод у класі фрагментів. Це призведе до запуску події в поточному фрагменті.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.