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/…
Oleksii K.

5
คนอื่นที่อ่านข้อความนี้ให้แน่ใจว่าคุณผ่านrequestCode >= 0!
มูฮัมหมัดบาบาร์

3
ตรวจสอบให้แน่ใจด้วยว่ากิจกรรม LauchMode ของคุณต้องไม่ใช่ singleInstance หรือ singleTask มิฉะนั้นแล้วแอคติวิตี Result จะไม่ถูกเรียก
Jawad Zeb

ดูลิงค์นี้อาจช่วยคุณได้: androidtutorialonline.com/onactivityresult-in-fragment
บทช่วยสอนของ Android

เราจำเป็นต้องเปลี่ยนเส้นทาง theActivityResult ในกิจกรรมเป็นชิ้นส่วน อ้างอิงลิงค์นี้: 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 () จากแฟรกเมนต์ของคุณ ดูคำตอบ siqing ด้านล่าง
OferR

8
ดูเหมือนว่าจะมีข้อผิดพลาดที่เกี่ยวข้องซึ่งมีการใช้งานไลบรารีการสนับสนุนcode.google.com/p/android/issues/detail?id=15394
Ollie C

82
โปรดทราบด้วยว่าหากคุณใช้แฟรกเมนต์ที่ซ้อนกันแฟรกเมนต์ชายด์ควรเรียกใช้getParentFragment().startActivityForResultเพื่อให้แฟรกเมนต์ parent มีเมธอด onActivityResult
Eric Brynsvold

7
@EricBrynsvold ถูกต้อง startActivityForResult ไม่ทำงานในชิ้นส่วนซ้อนกัน สำหรับสิ่งนี้คุณควรเรียกใช้ 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()
Stan

@siqing ฉันไม่สามารถเรียก startActivitForResult จากวิธีการคงที่ของฉัน มีทางออกอะไรบ้าง? ฉันต้องใช้ activity.startActivityForResult โปรดช่วยฉันในเรื่องนี้
Shreyash Mahajan

269

ตัวเลือกที่ 1:

หากคุณโทรstartActivityForResult()จากแฟรกเมนต์คุณควรโทรหาstartActivityForResult()ไม่ใช่getActivity().startActivityForResult()เพราะจะทำให้แฟรกเมนต์ onActivityResult ()

หากคุณไม่แน่ใจว่าคุณกำลังโทรหาที่ไหนstartActivityForResult()และจะโทรไปยังวิธีการอย่างไร

ตัวเลือก 2:

เนื่องจากกิจกรรมได้รับผลลัพธ์onActivityResult()คุณจะต้องแทนที่กิจกรรมonActivityResult()และการโทรsuper.onActivityResult()เพื่อเผยแพร่ไปยังส่วนที่เกี่ยวข้องสำหรับรหัสผลลัพธ์ที่ไม่สามารถจัดการได้หรือทั้งหมด

หากตัวเลือกสองตัวด้านบนไม่ทำงานให้อ้างอิงตัวเลือก 3 เนื่องจากจะใช้งานได้อย่างแน่นอน

ตัวเลือก 3:

การเรียกที่ชัดเจนจากแฟรกเมนต์ไปยังฟังก์ชัน onActivityResult มีดังนี้

ในคลาสกิจกรรมหลักให้แทนที่เมธอด onActivityResult () และแม้กระทั่งแทนที่ในคลาสแฟรกเมนต์และเรียกใช้เป็นรหัสต่อไปนี้

ในระดับผู้ปกครอง:

@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
สิ่งนี้ใช้ได้สำหรับฉัน เป็นวิธีแก้ปัญหาที่น่ารังเกียจ แต่ฉันไม่มีความคิดที่ดีกว่าในการแก้บั๊กที่งี่เง่านี้ ...
Bogdan Zurac

@Vivky คำตอบของคุณใช้ได้กับฉัน แต่มีปัญหาอีกหนึ่งฉันกำลังหันหน้าไปแทนsetResult(); finish();เมื่อกดกลับมาจากกิจกรรมที่สองแล้วยังได้รับการเรียกว่ามีให้ไว้onActivityResult RESULT_CODE
snehal_penurkar

คำตอบที่ยอดเยี่ยม ฉันใช้โซลูชันที่สามเพื่อทำให้เสร็จ
Sash_KP

ฉันคิดว่าวิธีที่ 3 จะใช้งานได้สำหรับฉัน แต่onActivityResult()กิจกรรมคืนค่าแปลก ๆrequestCodeซึ่งถูกส่งไปยังส่วนของฉันแล้วละเว้น = /
E-Kami

1
@notGeek คุณถูกต้อง ผลลัพธ์จะได้รับเสมอในกิจกรรมแม้ว่าคุณจะเรียกจากส่วนหรือกิจกรรม
Vinayak

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! = this) {fragment.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รหัสบรรทัดด้านบน ส่วนที่เหลือสามารถเก็บไว้ไม่เปลี่ยนแปลง
lcn

7
ฉันคิดว่าฉันขอแนะนำอย่างยิ่งให้ไม่ให้มีการแยกส่วนในฐานะสมาชิกส่วนตัว พวกเขามีวงจรชีวิตของตัวเองดังนั้นคุณจึงไม่มีทางรู้ว่าพวกเขาอยู่ในสภาพที่ดีที่จะมีปฏิสัมพันธ์กับผู้จัดการหรือไม่ พวกมันค่อนข้างหนักและฉันก็กังวลเรื่องความจำรั่ว ผู้จัดการจะไม่ถูกสร้างขึ้นหากคุณไม่จำเป็นต้องใช้มัน
MinceMan

67

โพสต์ต้นฉบับ

FragmentActivityแทนที่requestCodeด้วยการแก้ไข หลังจากนั้นเมื่อonActivityResult()จะถูกเรียกใช้FragmentActivityจะแยกวิเคราะห์ 16 บิตที่สูงขึ้นและเรียกคืนดัชนีของแฟรกเมนต์ดั้งเดิม ดูรูปแบบนี้:

ป้อนคำอธิบายภาพที่นี่

หากคุณมีบางส่วนที่ระดับรูทจะไม่มีปัญหา แต่ถ้าคุณมีชิ้นส่วนซ้อนกันเช่นFragmentมีแท็บอยู่สองสามViewPagerอันคุณรับประกันว่าจะประสบปัญหา (หรือประสบปัญหาแล้ว)

เพราะเพียงหนึ่งดัชนีrequestCodeจะถูกเก็บไว้ภายใน นั่นคือดัชนีของภายในของมันFragment FragmentManagerเมื่อเราใช้แฟรกเมนต์ที่ซ้อนกันมีเด็กอยู่FragmentManagerซึ่งมีรายการของตัวเอง ดังนั้นจึงจำเป็นที่จะต้องบันทึกดัชนีโซ่ทั้งหมดเริ่มจากรูFragmentManager

ป้อนคำอธิบายภาพที่นี่

เราจะแก้ไขปัญหานี้ได้อย่างไร มีวิธีแก้ไขปัญหาทั่วไปในโพสต์นี้นี้

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


ฉันมีปัญหาแบบเดียวกันกับที่ฉันใช้ ViewPager ในแฟรกเมนต์หลักซึ่งมีแฟรกเมนต์อื่นเป็นแท็บ พยายามใช้ปัญหาที่ซ้อนกัน - ชิ้นส่วน แต่จบลงด้วยการรวบรวมข้อผิดพลาด คุณช่วยแนะนำวิธีแก้ปัญหาให้ฉันได้ไหม เพิ่มปัญหาด้วยที่นี่github.com/shamanland/nested-fragment-issue/issues/2
cgr

ฉันตอบ github ดังนั้นให้ย้ายบทสนทนานี้ออกไปจากที่นี่github.com/shamanland/nested-fragment-issue/issues/…
Oleksii K.

ขอบคุณ! หากไม่ใช่วิธีการแก้ปัญหาที่แนะนำฉันขอแนะนำให้แก้ไขคำตอบตามนั้นเพื่อให้ไม่จำเป็นต้องใช้เวลาลองทำเช่นนี้เพื่อทราบว่ามีข้อผิดพลาดในการรวบรวม
cgr

44

นี่เป็นหนึ่งในปัญหาที่ได้รับความนิยมมากที่สุด เราสามารถพบหัวข้อมากมายเกี่ยวกับปัญหานี้ แต่ไม่มีประโยชน์สำหรับฉันเลย

ดังนั้นฉันได้แก้ไขปัญหานี้โดยใช้วิธีนี้

ก่อนอื่นเรามาทำความเข้าใจว่าทำไมสิ่งนี้จึงเกิดขึ้น

เราสามารถโทรติดต่อstartActivityForResultได้โดยตรงจาก Fragment แต่จริงๆแล้วช่างเบื้องหลังถูกจัดการโดย Activity

เมื่อคุณโทรมา startActivityForResultจาก Fragment แล้ว RequestCode จะถูกเปลี่ยนเพื่อแนบข้อมูลประจำตัวของ Fragment เข้ากับรหัส นั่นจะทำให้กิจกรรมสามารถติดตามว่าใครส่งคำขอนี้เมื่อได้รับผลลัพธ์

เมื่อกิจกรรมถูกสำรวจกลับผลลัพธ์จะถูกส่งไปยังกิจกรรมของ onActivityResult พร้อมกับ requestCode ที่แก้ไขแล้วซึ่งจะถูกถอดรหัสเป็นรหัสประจำตัวเดิมของ RequestCode + Fragment หลังจากนั้นกิจกรรมจะส่งผลลัพธ์ของกิจกรรมไปที่แฟรกเมนต์นั้นผ่าน 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" เท่านั้น


ใช้งานได้ดีในกิจกรรม> Fragment (ViewPager)> Fragment
Oleksandr Firsov

14

ฉันสามารถเพิ่มคำแนะนำสองคำได้ถ้ามีคนยังทำไม่ได้ ในไฟล์ Manifest.xml ตรวจสอบให้แน่ใจว่ากิจกรรมการโฮสต์ไม่เสร็จสิ้นเมื่อโทรกลับและกิจกรรมที่จะเริ่มมีโหมดเรียกใช้เป็นมาตรฐาน ดูรายละเอียดดังนี้:

สำหรับกิจกรรมการโฮสต์ให้ตั้งค่าคุณสมบัติประวัติไม่เป็นเท็จหากมี

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

ฉันยังพบปัญหานี้ในแฟรกเมนต์ และฉันเรียกว่าในstartActivityForResultDialogFragment

แต่ตอนนี้ปัญหานี้ได้รับการแก้ไขแล้ว:
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.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

รุ่น Kotlin (ในกิจกรรมของคุณใน ActivityResult ())

 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

ดังที่ Ollie C กล่าวถึงมีบั๊กที่ใช้งานอยู่สำหรับไลบรารีสนับสนุนโดยใช้ค่าที่ส่งคืนไปยัง onActivityResult เมื่อคุณใช้แฟรกเมนต์ที่ซ้อนกัน ฉันแค่กดมัน :-(

ดูFragment.onActivityResult ไม่ได้เรียกว่าเมื่อ requestCode! = 0


1

ฉันสงสัยอย่างมากว่าคำตอบทั้งหมดที่นี่ไม่มีอะไรมากไปกว่าแฮ็ก ฉันได้ลองพวกเขาทั้งหมดและอื่น ๆ อีกมากมาย แต่ไม่มีข้อสรุปที่น่าเชื่อถือเนื่องจากมีปัญหาโง่ ๆ อยู่เสมอ ฉันหนึ่งไม่สามารถพึ่งพาผลลัพธ์ที่ไม่สอดคล้องกัน หากคุณดูที่เอกสารทางการของ Android API สำหรับ Fragments คุณจะเห็น Google ระบุสิ่งต่อไปนี้อย่างชัดเจน:

เรียก startActivityForResult (Intent, int) จากกิจกรรมที่มีแฟรกเมนต์ของ

โปรดดู: Android Fragment API

ดังนั้นดูเหมือนว่าวิธีที่ถูกต้องและเชื่อถือได้มากที่สุดคือการเรียกstartActivityForResult ()จากกิจกรรมการโฮสต์และจัดการกับผลลัพธ์ที่ได้จากActActivity ()จากที่นั่น


2
ฉันไม่คิดว่า "การเรียก startActivityForResult จากกิจกรรม" เป็นคำแนะนำ หากคุณดูการใช้งานในคลาสฐานของ Fragment แล้วทั้งหมดก็คือmActivity.startActivityFromFragment(this, intent, requestCode)- ดังนั้นจึงไม่มีอะไรอื่นนอกจาก wrapper ที่ให้ความสะดวกสบาย
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ที่ให้แน่ใจว่าโฮสต์กิจกรรมของคุณโหมดการเปิดตัวไม่ต้องตั้งค่าให้หรือsingleInstancesingleTask

onActivityResult จะไม่ทำงานหากโหมดการเปิดใช้ของคุณถูกตั้งค่าเป็น SingleInstance หรือ SingleTask หรือคุณเรียกกิจกรรมของคุณโดยใช้ IntentFilters เหล่านี้

standardหรือsingleTopโหมดเปิดใช้งานจะทำงานได้ดี


1

หากคุณใช้ชิ้นส่วนซ้อนกันสิ่งนี้จะทำงานเช่นกัน:

getParentFragment().startActivityForResult(intent, RequestCode);

นอกจากนี้คุณต้องโทรsuper.onActivityResultจากกิจกรรมหลักและกรอกonActivityResultวิธีการแยกส่วน


1

ฉันได้รับการจัดการปัญหาโดยการเขียนชั้นฐานที่ขยายFragmentและในของกิจกรรมที่ฉันได้ระบุส่วนที่ทำงานอยู่ในปัจจุบันโดยใช้onactivityresult fragmenttagจากนั้นฉันเรียกใช้เมธอดที่ผู้ใช้กำหนดในคลาส Fragmentbase สิ่งนี้จะดำเนินการเหตุการณ์ในส่วนที่รันอยู่ในปัจจุบัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.