onActivityResult不在Fragment中调用

托pipe此片段的活动在相机活动返回时调用onActivityResult

我的片段开始一个活动的结果与意图发送给相机拍照。 图片应用程序加载正常,拍照,并返回。 然而, onActivityResult从来没有被击中。 我设置了断点,但没有任何触发。 片段是否有onActivityResult ? 我会这么想,因为这是一个提供的function。 为什么这不被触发?

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

托pipe活动覆盖onActivityResult() ,但未针对未处理的结果代码调用super.onActivityResult() 。 显然,即使片段是做startActivityForResult()调用的片段,活动也会在处理结果时获得第一个镜头。 当你考虑碎片的模块性时,这是有道理的。 一旦我为所有未处理的结果实现了super.onActivityResult() ,这个片段在处理结果时得到了一个镜头。

还来自@siqing答案:

为了得到你的片段的结果,请确保你调用startActivityForResult(intent,111); 而不是getActivity().startActivityForResult(intent,111); 在你的片段里面。

我想你叫getActivity().startActivityForResult(intent,111); 。 你应该调用startActivityForResult(intent,111);

选项1:

如果从fragment中调用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 } 

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

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

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

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

原帖。

FragmentActivity用一个修改的代码replacerequestCode 。 之后,当onActivityResult()被调用时, FragmentActivityparsing更高的16位,并恢复原始片段的索引。 看这个scheme:

在这里输入图像说明

如果您在根级别有几个片段,则没有问题。 但是如果你有嵌套的片段 ,例如在ViewPager带有几个标签的ViewPager ,你可以保证会面临一个问题 (或者已经面对过)。

因为只有一个索引存储在requestCode内部。 这是Fragment内的FragmentManager索引。 当我们使用嵌套片段时,有子FragmentManager ,它们有自己的片段列表。 所以,需要保存从FragmentManager开始的整个索引链。

在这里输入图像说明

我们如何解决这个问题? 在这篇文章中有常见的解决方法。

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

这是最受欢迎的问题之一。 我们可以在这个问题上find很多线索。 但是没有一个对我有用。

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

我们先来了解为什么会这样。

我们可以直接从Fragment调用startActivityForResult ,但实际上后面的机制都是由Activity处理的。

一旦从Fragment调用startActivityForResult ,requestCode将被更改为将Fragment的标识附加到代码中。 这将使活动能够追踪收到结果后谁发送此请求。

一旦Activity导航回来,结果将被发送到Activity的onActivityResult与修改的requestCode将被解码为原始的requestCode + Fragment的身份。 之后,Activity将通过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) { } } 

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

对于很多嵌套片段(例如,在片段中使用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 – 将其replace为嵌套片段中唯一的int,以防止其他片段处理答案。

接收回应

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

注意

需要在uniqueInstanceInt中使用0到65536之间的数字以避免错误“只能使用低16位的requestCode”。

如果有人仍然无法做到,我可以添加两个build议。 在Manifest.xml文件中,确保在callback时主机活动没有完成,并且要启动的活动具有标准的启动模式。 详情如下:

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

 android:noHistory="false" 

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

 android:launchMode="standard" 

我也在一个片段中遇到了这个问题。 我在DialogFragment调用了startActivityForResult

但是现在这个问题已经解决了:
FragmentClassname.this.startActivityForResult

解决scheme1:

调用startActivityForResult(intent, REQUEST_CODE); 而不是getActivity().startActivityForResult(intent, REQUEST_CODE);

解决scheme2:

startActivityForResult(intent, REQUEST_CODE); 被称为activity的onActivityResult(requestCode,resultcode,intent)被调用,然后你可以从这里调用fragments onActivityResult() ,传递requestCode, resultCode and intent

在你的片段里面,打电话

 this.startActivityForResult(intent, REQUEST_CODE); 

this是指这个片段。 否则就像@Clevester说的那样:

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

我也不得不打电话

 super.onActivityResult(requestCode, resultCode, data); 

在父活动的onActivityResult中使其工作。

(我从@ Clevester的回答中修改了这个答案。)

简而言之,

在片段中,声明Fragment fragment = this ;

之后使用fragment.startActivityForResult

结果将返回到activityResult。

在我的情况下,这是一个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); } } } 
 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); } } 
  1. 您可以简单地覆盖片段baseActivity.startActivityForResult上的BaseActivity onActivityResult

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

这个解决方法将会诀窍。

如果上面的问题是面对Facebooklogin,那么你可以在你的片段的父级活动中使用下面的代码,如:

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

对于嵌套片段(例如,使用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 } 

大多数这些答案一直说,你必须在你的主机Activity为你的Fragment调用super.onActivityResult(...) 。 但是,这似乎并没有为我工作。

所以,在你的主机Activity你应该调用你的Fragments onActivityResult(...) 。 这是一个例子。

 public class HostActivity extends Activity { private MyFragment myFragment; protected void onActivityResult(...) { super.onActivityResult(...); this.myFragment.onActivityResult(...); } } 

HostActivity某个时候,你将需要为你正在使用的Fragment分配this.myFragment 。 或者,使用FragmentManager获取Fragment而不是在HostActivity中保留对它的引用。 另外,在尝试调用this.myFragment.onActivityResult(...);之前检查null this.myFragment.onActivityResult(...);

正如Ollie C提到的那样,在使用嵌套片段时,支持库使用返回值给onActivityResult存在一个活动错误。 我只是打了它:-(。

请参阅requestCode!= 0时未调用的Fragment.onActivityResult

我有强烈的怀疑,这里的所有答案只不过是黑客。 我已经尝试了所有的和其他的,但没有任何可靠的结论,因为总会有一些愚蠢的问题。 我不能依靠不一致的结果。 如果您查看Fragments的官方Android API文档,您将看到Google明确指出以下内容:

从片段的Activity中调用startActivityForResult(Intent,int)。

请参阅: Android Fragment API

所以,看起来最正确和可靠的方法是从宿主活动中实际调用startActivityForResult() ,并从那里处理结果onActivityResult()

你的代码有一个嵌套的片段。 调用super.onActivityForResult不起作用

你不想修改你的片段可以被调用的每一个活动,或者做一个工作,调用片段链中的每个片段。

这是许多工作解决scheme之一。 dynamic创build一个片段,并使用支持片段pipe理器将其直接连接到活动。 然后从新创build的片段中调用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(); } 

我的问题是与主机活动我发现它与一组android:launchMode="standard"我删除它临时工作!

我已经通过编写扩展Fragment的基类来处理这个问题,并且在onactivity结果中,我使用fragmenttag标识了当前正在运行的片段,并在fragmentbase类中调用了用户定义的方法。 这将在当前正在运行的片段中激发一个事件。

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

 startActivity(ActivityName); 

然后,添加你调用startActivityForResult(intent,"1"); 从您的活动中添加onActivityResult

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

我只是做一个解决方法:

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

在你的Fragment中,在startActivityResult之前设置

 MainActivity._tempFragment = this; 

onActivityResult < – 在片段之后

 @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // Do your job { } MainActivity._tempFragment = null; } 

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

 @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会调用它的父类。

有一点没有人mention确保您的主机活动启动模式不能设置为singleInstancesingleTask

如果您的启动模式设置为SingleInstance或SingleTask,则onActivityResult将不起作用。 或者使用这些IntentFilter调用您的活动

standardsingleTop启动模式将正常工作。

如果fragment类中的onActivityResult方法有问题,并且想要更新也在fragment类中的东西,请使用:

 @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 。 否则该方法将在父活动中被调用,并且该variables不会更新当前实例。

我也通过将这段代码放到MainActivity ,用HomeFragment类replace了thisvariables,并使variables静态化。 我得到了预期的结果。

所以如果你想让片段类有自己的onActivityResult实现,上面的代码示例就是答案。

如果你正在使用嵌套片段,这也是工作:

 getParentFragment().startActivityForResult(intent, RequestCode); 

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