关于android:在Fragment中没有调用onActivityResult

onActivityResult is not being called in Fragment

当相机活动返回时,托管此片段的活动将调用其onActivityResult

我的片段开始一个结果的活动,目的是让相机拍照。图片应用程序加载良好,拍照,然后返回。然而,onActivityResult从未被击中。我已经设置了断点,但没有触发任何操作。一个片段能有onActivityResult吗?我想是的,因为它是一个提供的函数。为什么不触发?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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);
    }
}


托管活动覆盖onActivityResult(),但它没有为未处理的结果代码调用super.onActivityResult()。显然,尽管片段是进行startActivityForResult()调用的片段,但该活动在处理结果时得到了第一枪。当您考虑片段的模块化时,这是有意义的。一旦我为所有未处理的结果实现了super.onActivityResult(),片段就可以处理结果了。

还有来自@Siqing的回复:

要在片段中得到结果,请确保在片段中调用startActivityForResult(intent,111);而不是getActivity().startActivityForResult(intent,111);


我想你打电话给getActivity().startActivityForResult(intent,111);。你应该打电话给startActivityForResult(intent,111);


选项1:

如果您从片段调用startActivityForResult(),那么您应该调用startActivityForResult(),而不是getActivity().startActivityForResult(),因为它将导致片段onActivityResult()。

如果您不确定在哪里调用startActivityForResult(),以及如何调用方法。

选项2:

由于activity得到onActivityResult()的结果,因此需要重写该活动的onActivityResult()并调用super.onActivityResult()以传播到未处理结果代码或所有未处理结果代码的各自片段。

如果上述两个选项不起作用,则参考选项3,因为它肯定会起作用。

选项3:

从fragment到onActivityResult函数的显式调用如下。

在父Activity类中,重写onActivityResult()方法,甚至重写fragment类中的方法,并调用以下代码。

在父类中:

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

在儿童班:

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


如果您不知道活动中的片段,只需枚举它们并发送活动结果参数:

1
2
3
4
5
6
7
8
// 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);
    }
}


我和ChildFragmentManager有同样的问题。管理器不会将结果传递给嵌套片段,您必须在基本片段中手动执行该操作。

1
2
3
4
5
6
7
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);
    }
}


原来的职位。

一个FragmentActivityreplaces requestCode)改性。在这样的,当两个竞争的剖析器将被onActivityResult()FragmentActivity的高16位的索引和恢复原来的片段。看看这个计划:

Enter image description here

如果你有一个片段在几个层次的根有问题。如果你有一个嵌套的片段,例如Fragment与几个标签在ViewPager保证,你将面对的问题(或已经接待了它)。

由于只有一个索引是存储在requestCode。这是在其FragmentManagerFragment指数。当我们使用嵌套的片段,有他们自己的孩子FragmentManagers列表,这一片段。操作系统,它是必要的拯救整个链FragmentManager指数从根开始。

Enter image description here

我们如何解决这个问题的?有一个解决方案,在这一篇普通的workaround。

GitHub的https://://shamanland github.com嵌套的片段。


这是一个最受欢迎的问题。关于这个问题,我们可以找到很多线索。但这些都对我没用。

所以我用这个方法解决了这个问题。

让我们先了解一下为什么会发生这种情况。

我们可以直接从片段中调用startActivityForResult,但实际上后面的机制都是由活动处理的。

一旦从片段调用startActivityForResult,请求代码将被更改为将片段的标识附加到代码。这将使活动能够跟踪在收到结果后发送此请求的人。

一旦活动被导航回,结果将与修改后的请求代码一起发送到活动的OnActivityResult,该代码将被解码为原始请求代码+片段的标识。之后,活动将通过onActivityResult将活动结果发送到该片段。一切都结束了。

问题是:

活动只能将结果发送到直接附加到活动的片段,而不能发送到嵌套的片段。这就是为什么嵌套片段的onActivityResult永远不会被调用的原因。

解决方案:

1)通过以下代码开始片段中的意图:

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

2)现在在您的父活动中覆盖**onActivityResult():**

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

您必须在父活动中调用它才能使其工作。

3)在片段调用中:

1
2
3
4
5
6
7
@Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {

       }
}

就是这样。有了这个解决方案,无论是否嵌套,它都可以应用于任何单个片段。是的,它也涵盖了所有的情况!此外,这些代码也很好而且很干净。


对于许多嵌套片段(例如,在片段中使用viewpager时)

在您的主要活动中:

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

在你的片段中:

1
2
3
4
5
6
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    for (Fragment fragment : getChildFragmentManager().getFragments()) {
        fragment.onActivityResult(requestCode, resultCode, data);
    }
}

在嵌套片段中

通话活动

1
getParentFragment().startActivityForResult(intent, uniqueInstanceInt);

uniqueinstanceint-用嵌套片段中唯一的int替换它,以防止另一个片段处理答案。

接收响应

1
2
3
4
5
6
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == uniqueInstanceInt ) {
        // TODO your code
    }
}

敬告

uniqueinstanceint中需要使用一个介于0和65536之间的数字,以避免"只能对请求代码使用16位以下的数字"。


如果还是有人做不到,我可以加两条建议。在manifest.xml文件中,确保在回调时宿主活动没有完成,并且要启动的活动具有标准的启动模式。具体如下:

对于托管活动,如果有,则将no history属性设置为false

1
android:noHistory="false"

对于要启动的活动,将启动模式设置为标准(如果有)

1
android:launchMode="standard"


我也遇到这个问题,在片段。我叫startActivityForResultDialogFragment中。

现在这个问题已得到解决:
FragmentClassname.this.startActivityForResult


我也面临同样的问题,当我将这段代码从一个片段转移到一个实用程序类中时,parentActivity作为参数传递,

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

然后我没有得到该片段的onActivityResult方法的任何值,后来,我把论点改成了片段,所以修改后的方法定义看起来像,

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

在那之后,我可以在onActivityResult中得到片段的价值。


Solution 1:

Call startActivityForResult(intent, REQUEST_CODE); instead of getActivity().startActivityForResult(intent, REQUEST_CODE);.

Solution 2:

When startActivityForResult(intent, REQUEST_CODE); is called the activity's onActivityResult(requestCode,resultcode,intent) is invoked, and then you can call fragments onActivityResult() from here, passing the requestCode, resultCode and intent.


总之,

在宣布Fragment fragment = this片段;

这是fragment.startActivityForResult后使用。

在activityresult将返回的结果。


Inside your fragment, call

1
this.startActivityForResult(intent, REQUEST_CODE);

this是referring的片段。另有的说:"clevester

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

我也不得不呼叫

1
super.onActivityResult(requestCode, resultCode, data);

在父母的onActivityResult活性使它工作。

一本从"适应clevester答案的答案。)


在我的例子中,这是一个Android错误(http://technet.weblineindia.com/mobile/onactivityresult not getting called in nested fragments android/),如果您使用支持的FragmentActivity,则必须使用getSupportFragmentManager,而不是getChildFragmentManager

1
2
3
4
5
6
7
8
List<Fragment> fragments = getSupportFragmentManager().getFragments();
if (fragments != null) {
    for (Fragment fragment : fragments) {
        if(fragment instanceof UserProfileFragment) {
            fragment.onActivityResult(requestCode, resultCode, data);
        }
    }
}

对于嵌套片段(例如,使用viewpager时)

在您的主要活动中:

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

在主顶级片段(viewpager片段)中:

1
2
3
4
5
6
@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);
}

在片段(嵌套片段)中:

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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);
    }
}

这些答案中的大多数都说,你必须在你的主机中打电话给super.onActivityResult(...),给你的Activity,给你的Fragment。但这似乎对我不起作用。

所以,在你的主机Activity中,你应该改为叫你的FragmentsonActivityResult(...)。下面是一个例子。

1
2
3
4
5
6
7
8
9
public class HostActivity extends Activity {

    private MyFragment myFragment;

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

在您的HostActivity中的某个时刻,您需要将您正在使用的this.myFragment分配给Fragment。或者,使用FragmentManager获取Fragment,而不是在你的HostActivity中保留对它的引用。另外,在打电话给this.myFragment.onActivityResult(...);之前,先检查一下null


如果以上的问题是当你在Facebook的登录使用下面的代码可以在你的父的片段样活性。

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

或:

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

添加下面的呼叫和在你的片段……

1
callbackManager.onActivityResult(requestCode, resultCode, data);


  • 你可以简单地重写baseactivity onActivityResult在线baseActivity.startActivityForResult片段。

  • 在线baseactivity onactivityresult)接口和覆盖。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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);
    }
  • 在线OnBaseActivityResult片段器具

    1
    2
    3
    4
    5
    6
    7
    8
    @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();
      }
    }
  • 这将workaround的戏法。


    我有一个强烈的被怀疑在所有的答案是不多的黑客。我想很多人都和他们没有任何可靠的结论,但总有一些排序)的愚蠢的问题。我是一个不能依靠不一致的结果。如果你看看官方的Android API的谷歌文档你会清楚地看到美国片段以下:

    Call startActivityForResult(Intent, int) from the fragment's containing Activity.

    国有企业:Android API的片段。

    操作系统,它将似乎是最准确和可靠的方法,其实是从主机startactivityforresult(呼叫)的活性也导致onactivityresult(手柄),从那里。


    正如Ollie C所提到的,在使用嵌套片段时,支持库有一个活动的bug,它使用返回到onActivityResult的值。我刚刚打了一下。

    请参见fragment.onActivityResult,请求代码时未调用!= 0。


    你有嵌套的代码片段。呼叫super.onactivityforresult不是工作

    你不想你的每一个活性的修改,称为片段,可以从工作或使呼叫和在每个片段的片段链。

    这里是一个解决方案的许多工作。创建一个片段,它直接飞到电线与支持经理活性片段。然后从新创建的呼叫startactivityforresult片段。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    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
    <div class="suo-content">[collapse title=""]<ul><li>这确实有效,我只有一票支持。在飞行中创建一个片段。太简单了,但它真正的工作解决方案。甚至有人试图为我编辑它。</li></ul>[/collapse]</div><hr><P>我的问题是主机活动,我是用一套<wyn>android:launchMode="standard"</wyn>找到它的,我把它暂时删除了一个IT工作!</P><p><center>[wp_ad_camp_5]</center></p><hr><P>如果您使用的是嵌套片段,那么这也可以工作:</P>[cc]getParentFragment().startActivityForResult(intent, RequestCode);

    除此之外,还必须从父活动调用super.onActivityResult,并填充片段的onActivityResult方法。


    只要使用下面的代码片段。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    @Override
    public void onOtherButtonClick(ActionSheet actionSheet, int index) {

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

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

    它的母onactivityresult打电话没有电话。


    如果fragment类中的方法onActivityResult有问题,并且您希望更新fragment类中的某些内容,请使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

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

    如上面代码所示,只需添加this.variable。否则,将在父活动中调用该方法,并且不会更新当前实例的变量。

    我还通过将这个代码块放入MainActivity中、用HomeFragment类替换this并使变量保持静态来测试它。我得到了预期的结果。

    因此,如果您希望fragment类有自己的onActivityResult实现,那么上面的代码示例就是答案。


    最简单的方法之一是从片段开始一个活动。

    1
    startActivity(ActivityName);

    然后,从你的活动中添加你称之为startActivityForResult(intent,"1");,在你的活动中添加onActivityResult

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    startActivityForResult(intent,"1");

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

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

    One point no one has mention that make sure your Host Activity launch mode must not set to singleInstance or singleTask.

    如果启动模式设置为singleInstance或singleTask,则OnActivityResult将不起作用。或者使用这些intentfilters调用您的活动

    standardsingleTop发射模式可以正常工作。


    我通过编写一个扩展Fragment的基类来处理这个问题,在onactivityresult的活动中,我使用fragmenttag识别了当前运行的片段。然后在fragmentBase类中调用一个用户定义的方法。这将在当前运行的片段中激发一个事件。


    我只是做了一个变通方法:

    1
    2
    3
    4
    5
    6
    7
    public static Fragment _tempFragment = null;
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(_tempFragment != null)
            _tempFragment.onActivityResult(requestCode, resultCode, data);
    }

    在片段中,在StartActivityResult之前,设置

    1
    MainActivity._tempFragment = this;

    OnActivityResult之后<--in fragment

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);

         // Do your job
         {

         }
         MainActivity._tempFragment = null;
    }


    只需打电话:

    1
    startActivityForResult(intent,"1");