onActivityResult не вызывается во фрагменте


878

Активность, в которой размещается этот фрагмент, вызывается, 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
Также убедитесь, что ваш Activity LauchMode не должен использовать singleInstance или singleTask. в противном случае onActivityResult не будет вызван
Джавад Зеб

Просмотр этой ссылки может вам помочь: androidtutorialonline.com/onactivityresult-in-fragment
Android,

Нам нужно перенаправить onActivityResult в Activity к фрагменту. Смотрите по этой ссылке: codexpedia.com/android/...
Reejesh PK

Ответы:


1240

Хостинговая активность переопределяет 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/issues/detail?id=15394
Ollie C

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

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

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. Пожалуйста, помогите мне в этом
Shreyash Mahajan

270

Опция 1:

Если вы вызываете startActivityForResult()из фрагмента, вам следует вызывать startActivityForResult(), а не так getActivity().startActivityForResult(), поскольку это приведет к фрагменту onActivityResult ().

Если вы не уверены, куда вы звоните startActivityForResult()и как будете вызывать методы.

Вариант 2:

Поскольку Activity получает результат onActivityResult(), вам нужно будет переопределить действие onActivityResult()и вызвать super.onActivityResult()для распространения на соответствующий фрагмент для необработанных кодов результатов или для всех.

Если вышеупомянутые два варианта не работают, обратитесь к варианту 3, поскольку он определенно будет работать.

Вариант 3:

Явный вызов фрагмента функции onActivityResult выглядит следующим образом.

В родительском классе Activity переопределите метод 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).
дасар

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

Это не работает, если фрагменты вложены, так как в списке будет только верхний фрагмент. Я считаю, что super.onActivityResult () уже вызывает onActivityResult () для всех фрагментов в списке, поэтому эта идея является избыточной.
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строки кода. Остальное можно оставить без изменений.
2013 г.

7
Думаю, я бы настоятельно рекомендовал не хранить фрагмент в качестве частного участника. У них есть свой жизненный цикл, поэтому вы никогда не узнаете, находится ли их в хорошем состоянии для взаимодействия, менеджер. Кроме того, они довольно здоровенные, и я был бы обеспокоен утечками памяти. Менеджер не был бы создан, если бы вам не нужно было его использовать.
MinceMan

67

Оригинальный пост.

FragmentActivityзаменяет requestCodeна измененный. После этого, когда onActivityResult()будет вызвано, FragmentActivityанализирует старшие 16 битов и восстанавливает индекс исходного фрагмента. Посмотрите на эту схему:

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

Если у вас есть несколько фрагментов на корневом уровне, проблем нет. Но если у вас есть вложенные фрагменты , например, Fragmentс несколькими вкладками внутри ViewPager, вы гарантированно столкнетесь с проблемой (или уже столкнулись с ней).

Потому что внутри хранится только один индексrequestCode . Это индекс Fragmentвнутри его FragmentManager. Когда мы используем вложенные фрагменты, есть дочерние элементы FragmentManager, у которых есть свой список фрагментов. Итак, необходимо сохранить всю цепочку индексов, начиная с root FragmentManager.

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

Как мы решаем эту проблему? В этом посте есть общее решение .

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


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

Я ответил на github, так что давайте уберем этот разговор отсюда github.com/shamanland/nested-fragment-issue/issues/…
Алексей К.

Спасибо! Если это не рекомендуемое решение, я предлагаю изменить ответ соответствующим образом, чтобы не тратить время на попытки выяснить, есть ли у него ошибки компиляции.
cgr

44

Это один из самых популярных номеров. Мы можем найти много веток по этой проблеме. Но ни один из них не полезен для меня.

Таким образом, я решил эту проблему, используя это решение.

Давайте сначала поймем, почему это происходит.

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

После того, как вы позвоните startActivityForResultиз фрагмента, requestCode будет изменен, чтобы прикрепить идентификатор фрагмента к коду. Это позволит Activity быть в состоянии отследить того, кто отправил этот запрос после получения результата.

После того, как Activity вернется назад, результат будет отправлен в onActivityResult Activity с измененным requestCode, который будет декодирован в исходный идентификатор requestCode + Fragment. После этого Activity отправит результат Activity этому фрагменту через onActivityResult. И все это сделано.

Проблема в:

Activity может отправить результат только фрагменту, который был прикреплен непосредственно к Activity, но не вложенному. Вот почему 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».


Прекрасно работает в Activity> Фрагмент (ViewPager)> Фрагмент
Александр Фирсов

14

Я могу добавить два совета, если кто-то все еще не может сделать это. В файле Manifest.xml убедитесь, что хостинг-операция не завершилась при обратном вызове, и для запускаемой активности стандартным является режим запуска. Подробности см. Ниже:

Для активности хостинга установите для свойства no history значение false, если

android:noHistory="false"

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

android:launchMode="standard"

13

Я также столкнулся с той же проблемой, как только переместил этот блок кода за пределы фрагмента в служебный класс , parentActivityпередав его в качестве аргумента :

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

Тогда я не получал никакого значения в onActivityResultметоде этого фрагмента. После этого я изменил аргумент на фрагмент , поэтому пересмотренное определение метода выглядело так:

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

В YourFragment (вложенный фрагмент):

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чтобы заставить его работать.

(Я адаптировал этот ответ из ответа @ Clevester.)


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.myFragmentчто Fragmentвы используете. Или используйте, FragmentManagerчтобы получить Fragmentвместо того, чтобы хранить ссылку на него в вашем HostActivity. Кроме того, проверьте, nullпрежде чем пытаться позвонить 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. Вы можете просто переопределить 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

Версия Kotlin (в вашей активности 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

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

Вызовите startActivityForResult (Intent, int) из фрагмента, содержащего Activity.

Смотрите: Android Fragment API

Таким образом, может показаться, что наиболее правильным и надежным подходом было бы на самом деле вызвать startActivityForResult () из действия хостинга, а также обработать итоговый onActivityResult () оттуда.


2
Я не думаю, что "вызывать startActivityForResult from Activity" - это рекомендация. Если вы посмотрите на реализацию внутри базового класса Fragment, то все, что он делает, mActivity.startActivityFromFragment(this, intent, requestCode)- это не что иное, как
вспомогательная

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, чтобы убедиться, что режим запуска вашей активности хоста не должен быть установлен 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.