onActivityResult không được gọi trong Fragment


877

Hoạt động lưu trữ đoạn này onActivityResultđược gọi khi hoạt động camera quay lại.

Đoạn của tôi bắt đầu một hoạt động cho một kết quả với ý định được gửi cho máy ảnh để chụp ảnh. Ứng dụng hình ảnh tải tốt, chụp ảnh và trả về. Các onActivityResulttuy nhiên không bao giờ đạt. Tôi đã đặt điểm dừng, nhưng không có gì được kích hoạt. Một mảnh có thể có onActivityResult? Tôi nghĩ vậy vì nó là một chức năng được cung cấp. Tại sao điều này không được kích hoạt?

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
kiểm tra bài đăng này, có mô tả vấn đề và giải pháp khắc phục chung: stackoverflow.com/questions/6147884/
Kẻ

5
Bất kỳ ai khác đọc điều này chắc chắn rằng bạn vượt qua requestCode >= 0!
Muhammad Babar

3
Ngoài ra, hãy đảm bảo LauchMode hoạt động của bạn không được đơn lẻ hoặc SingleTask. mặt khác, onActivityResult sẽ không được gọi
Jawad Zeb


Chúng ta cần chuyển hướng onActivityResult trong Activity sang Fragment. Tham khảo liên kết này: codexpedia.com/android/ đá
Reejesh PK

Câu trả lời:


1239

Hoạt động lưu trữ ghi đè onActivityResult(), nhưng nó không thực hiện cuộc gọi super.onActivityResult()cho các mã kết quả chưa được xử lý. Rõ ràng, mặc dù đoạn đó là người thực hiện startActivityForResult()cuộc gọi, hoạt động này được bắn đầu tiên để xử lý kết quả. Điều này có ý nghĩa khi bạn xem xét tính mô-đun của các mảnh. Khi tôi thực hiện super.onActivityResult()cho tất cả các kết quả chưa được xử lý, đoạn đã xử lý kết quả.

Và cũng từ câu trả lời @si Khánh:

Để có kết quả trong đoạn của bạn, hãy chắc chắn rằng bạn gọi startActivityForResult(intent,111);thay vì getActivity().startActivityForResult(intent,111);bên trong đoạn của bạn.


34
Trong hoạt động của bạn là onActivityResult, hãy gọi super.onActivityResult ()
Spidy

167
@StErMi Hãy chắc chắn rằng bạn gọi startActivityForResult () chứ không phải getActivity (). StartActivityForResult () từ đoạn của bạn. Xem câu trả lời si Khánh dưới đây.
OferR

8
Dường như có một lỗi liên quan, trong đó thư viện hỗ trợ đang được sử dụng code.google.com/p/android/issues/detail?id=15394
Ollie C

82
Cũng lưu ý rằng nếu bạn đang sử dụng các đoạn lồng nhau, đoạn con nên gọi getParentFragment().startActivityForResultđể đoạn cha mẹ sẽ có phương thức onActivityResult được gọi.
Eric Brynsvold

7
@EricBrynsvold đã đúng, startActivityForResult không hoạt động trong các đoạn lồng nhau. Đối với điều này, bạn nên gọi getParentFragment (). StartActivityForResult () và trong đoạn cha mẹ đó, sau đó, bạn có thể triển khai onActivityResult () và trong phương thức đó cung cấp kết quả cho các phần tử con, ví dụ: childFragment.getParent. onActivityResult (requestCode, resultCode, data)
edrian 7/1/2015

328

Tôi nghĩ bạn đã gọi getActivity().startActivityForResult(intent,111);. Bạn nên gọi startActivityForResult(intent,111);.


3
Tôi cũng có vấn đề tương tự với RingtonePreferencenằm ở PreferenceFragment. Thật không may, RingtonePreferencecác cuộc gọi getActivity().startActivityForResult()và tôi đã không nhận được kết quả mặc dù tôi gọi super.onActivityResulttrong hoạt động onActivityResult. Tôi đã buộc phải tạo ra một dẫn xuất từ RingtonePreferencelớp, nó liên kết chính nó với PreferenceFragmentvà các cuộc gọi fragment.startActivityForResult().
Stan

@si Khánh Tôi không thể gọi startActivitForResult từ phương thức tĩnh của mình. Bất kỳ giải pháp cho điều đó? Tôi phải sử dụng Activity.startActivityForResult. Xin hãy giúp tôi trong việc này
Shreyash Mahajan

270

Lựa chọn 1:

Nếu bạn đang gọi điện thoại startActivityForResult()từ các mảnh vỡ thì bạn nên gọi startActivityForResult(), không phải getActivity().startActivityForResult(), vì nó sẽ dẫn đến đoạn onActivityResult ().

Nếu bạn không chắc chắn nơi bạn đang gọi startActivityForResult()và cách bạn sẽ gọi phương thức.

Lựa chọn 2:

Vì Hoạt động nhận được kết quả của onActivityResult(), bạn sẽ cần ghi đè lên hoạt động onActivityResult()và gọi super.onActivityResult()để tuyên truyền đến đoạn tương ứng cho các mã kết quả chưa được xử lý hoặc cho tất cả.

Nếu hai tùy chọn trên không hoạt động, thì hãy tham khảo tùy chọn 3 vì nó chắc chắn sẽ hoạt động.

Tùy chọn 3:

Một cuộc gọi rõ ràng từ đoạn đến hàm onActivityResult như sau.

Trong lớp Activity gốc, ghi đè phương thức onActivityResult () và thậm chí ghi đè tương tự trong lớp Fragment và gọi dưới dạng mã sau.

Trong lớp cha mẹ:

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

Trong lớp con:

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

4
Điều này làm việc cho tôi. Đó là một cách giải quyết khó chịu, nhưng tôi không có ý tưởng nào tốt hơn để giải quyết lỗi ngu ngốc này ...
Bogdan Zurac

@Vivky, câu trả lời của bạn đã làm việc cho tôi. Nhưng có một vấn đề nữa mà tôi đang phải đối mặt, thay vì setResult(); finish();khi tôi nhấn lại từ hoạt động thứ hai thì cũng onActivityResultđược gọi với điều kiện được cung cấp RESULT_CODE.
snehal_penurkar

câu trả lời tuyệt vời. Tôi thực hiện giải pháp thứ ba để hoàn thành nó.
Sash_KP

Tôi nghĩ rằng giải pháp 3 sẽ có hiệu quả với tôi nhưng onActivityResult()hoạt động trả lại một điều kỳ lạ requestCodeđược truyền cho đoạn của tôi và sau đó bị bỏ qua = /
E-Kami

1
@notGeek Bạn đúng rồi. Kết quả luôn được nhận trong Hoạt động mặc dù bạn đã gọi từ phân đoạn hoặc hoạt động.
Vinayak

83

Trong trường hợp bạn không biết các đoạn trong hoạt động của mình, hãy liệt kê tất cả chúng và gửi các đối số kết quả hoạt động:

// 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
Chết tiệt, tôi nghĩ rằng tôi chỉ tìm thấy giải pháp đơn giản nhất, nhưng không có phương pháp nào như getFragments ().
WindRider

2
@WindRider Có. Nếu bạn sử dụng thư viện hỗ trợ Android (AppCompat).
dasar

2
Ngoài ra, tôi đã học được một cách khó khăn mà bạn phải kiểm tra xem đoạn trong mảng không phải là một tham chiếu đến chính nó! `if (Fragment! = this) {Fragment.onActivityResult (requestCode, resultCode, data); `
reubenjohn

Điều này không hoạt động nếu các đoạn được lồng vào nhau, vì chỉ có đoạn trên cùng sẽ nằm trong danh sách. Tôi tin rằng super.onActivityResult () đã gọi onActivityResult () trên tất cả các đoạn trong danh sách, vì vậy ý ​​tưởng này là dư thừa.
BeccaP


83

Tôi đang gặp vấn đề tương tự với ChildFragmentManager. Người quản lý sẽ không chuyển kết quả cho đoạn được lồng, bạn phải làm điều đó bằng tay trong đoạn cơ sở của bạn.

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
Nếu bạn có con Fragment là thành viên riêng, thì hãy sử dụng Fragment fragment = myChildFragment;để thay thế findFragmentByTagdòng mã trên. Phần còn lại có thể được giữ nguyên.
lcn

7
Tôi đoán tôi sẽ khuyên bạn không nên giữ một mảnh vỡ như một thành viên tư nhân. Họ có vòng đời riêng để bạn không bao giờ biết nếu họ ở trạng thái tốt để tương tác, người quản lý sẽ làm. Ngoài ra chúng khá nặng và tôi sẽ lo lắng về việc rò rỉ bộ nhớ. Người quản lý sẽ không được tạo nếu bạn không cần sử dụng nó.
MinceMan

67

Bài gốc.

FragmentActivitythay thế requestCodebởi một sửa đổi. Sau đó, khi onActivityResult()được gọi, FragmentActivityphân tích 16 bit cao hơn và khôi phục chỉ mục của Fragment gốc. Nhìn vào sơ đồ này:

Nhập mô tả hình ảnh ở đây

Nếu bạn có một vài mảnh ở cấp độ gốc thì không có vấn đề gì. Nhưng nếu bạn có các đoạn lồng nhau , ví dụ Fragmentvới một vài tab bên trong ViewPager, bạn được đảm bảo sẽ gặp phải một vấn đề (hoặc đã đối mặt với nó).

Bởi vì chỉ có một chỉ mục được lưu trữ bên trong requestCode. Đó là chỉ số Fragmentbên trong của nó FragmentManager. Khi chúng ta đang sử dụng các đoạn được lồng vào nhau, có các phần tử con FragmentManager, có danh sách các Đoạn riêng. Vì vậy, cần phải lưu toàn bộ chuỗi chỉ số, bắt đầu từ root FragmentManager.

Nhập mô tả hình ảnh ở đây

Làm thế nào để chúng tôi giải quyết vấn đề này? Có giải pháp khắc phục phổ biến trong bài này .

GitHub: https://github.com/shamanland/nested-fragment- phát hành


Tôi có vấn đề tương tự như tôi đã sử dụng ViewPager trong đoạn cha mẹ chứa các đoạn khác dưới dạng tab. Đã thử sử dụng vấn đề lồng nhau-kết thúc nhưng kết thúc với erros biên dịch. Bạn có thể gợi ý cho tôi giải pháp?
Đưa ra

Tôi đã trả lời trên github, vì vậy hãy chuyển cuộc trò chuyện này ra khỏi đây github.com/shamanland/nested-fragment-issue/issues/...
Oleksii K.

Cảm ơn! Nếu nó không phải là một giải pháp được đề xuất, tôi khuyên bạn nên chỉnh sửa câu trả lời cho phù hợp để người ta không cần phải dành thời gian thử nó để biết nó có bản dịch tổng hợp.
cgr

44

Đây là một trong những vấn đề phổ biến nhất. Chúng tôi có thể tìm thấy rất nhiều chủ đề liên quan đến vấn đề này. Nhưng không ai trong số chúng hữu ích cho tôi.

Vì vậy, tôi đã giải quyết vấn đề này bằng cách sử dụng giải pháp này.

Trước tiên hãy hiểu tại sao điều này xảy ra.

Chúng ta có thể gọi startActivityForResulttrực tiếp từ Fragment nhưng thực sự cơ học phía sau đều do Activity xử lý.

Một khi bạn gọi startActivityForResult từ Fragment, requestCode sẽ được thay đổi để đính kèm danh tính của Fragment vào mã. Điều đó sẽ cho phép Activity có thể theo dõi lại rằng ai đã gửi yêu cầu này sau khi nhận được kết quả.

Khi Activity được điều hướng trở lại, kết quả sẽ được gửi đến onActivityResult của Activity với mã yêu cầu được sửa đổi sẽ được giải mã thành nhận dạng ban đầu của requestCode + Fragment. Sau đó, Activity sẽ gửi Kết quả hoạt động tới Fragment đó thông qua onActivityResult. Và thế là xong.

Vấn đề là:

Hoạt động chỉ có thể gửi kết quả đến Đoạn được gắn trực tiếp vào Hoạt động chứ không gửi kết quả. Đó là lý do tại sao onActivityResult của các đoạn lồng nhau sẽ không bao giờ được gọi bất kể điều gì.

Giải pháp:

1) Bắt đầu ý định trong đoạn của bạn bằng mã dưới đây:

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

2) Bây giờ trong phần ghi đè Hoạt động cha mẹ của bạn **onActivityResult() : **

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

Bạn phải gọi điều này trong hoạt động của cha mẹ để làm cho nó hoạt động.

3) Trong cuộc gọi phân đoạn của bạn:

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

       }
}

Đó là nó. Với giải pháp này, nó có thể được áp dụng cho bất kỳ phân đoạn nào cho dù nó có được lồng hay không. Và vâng, nó cũng bao gồm tất cả các trường hợp! Hơn nữa, các mã cũng tốt đẹp và sạch sẽ.


Tôi đã yêu cầu ý định hệ thống với 'hoạt động' tôi chỉ phải sử dụng bối cảnh phân đoạn.
Uzair

18

ĐỐI VỚI NHIỀU FRAGITT NESTED (ví dụ: khi sử dụng ViewPager trong một đoạn)

Trong hoạt động chính của bạn :

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

Trong đoạn của bạn:

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

Trong đoạn lồng nhau của bạn

Hoạt động gọi

getParentFragment().startActivityForResult(intent, uniqueInstanceInt);

uniqueInstanceInt - thay thế nó bằng một int duy nhất trong số các đoạn lồng nhau để ngăn một đoạn khác xử lý câu trả lời.

Nhận phản hồi

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

Chú ý

Một số trong khoảng từ 0 đến 65536 cần được sử dụng trong uniqueInstanceInt để tránh lỗi "Chỉ có thể sử dụng 16 bit thấp hơn cho requestCode".


Hoạt động tuyệt vời trong Hoạt động> Mảnh vỡ (ViewPager)> Mảnh vỡ
Oleksandr Firsov

14

Tôi có thể thêm hai lời khuyên nếu ai đó vẫn không thể thực hiện được. Trong tệp Manifest.xml, đảm bảo hoạt động lưu trữ không kết thúc khi gọi lại và hoạt động được bắt đầu có chế độ khởi chạy là tiêu chuẩn. Xem chi tiết như dưới đây:

Đối với hoạt động Hosting, đặt thuộc tính không có lịch sử là sai nếu có

android:noHistory="false"

Để Hoạt động được bắt đầu, hãy đặt chế độ khởi chạy làm chuẩn nếu có

android:launchMode="standard"

13

Tôi cũng gặp phải vấn đề tương tự khi tôi chuyển khối mã này bên ngoài Mảnh vỡ sang Lớp tiện ích , với parentActivitythông qua là đối số ,

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

Sau đó, tôi đã không nhận được bất kỳ giá trị nào trong onActivityResultphương thức của Đoạn đó, Sau đó, tôi đã thay đổi đối số thành Mảnh vỡ , vì vậy định nghĩa sửa đổi của phương thức trông như thế nào,

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

Sau đó, tôi đã có thể nhận được giá trị onActivityResulttrên Mảnh vỡ


10

Tôi cũng đã gặp vấn đề này trong một mảnh. Và tôi gọi startActivityForResulttrong a DialogFragment.

Nhưng bây giờ vấn đề này đã được giải quyết :
FragmentClassname.this.startActivityForResult .


Tuyệt vời, làm việc cho tôi, bởi vì tôi đã gọi startActivityForResult(...)từ một lớp trừu tượng bên trong mã của đoạn.
Vince

9

ĐỐI VỚI FRAGITT NESTED (ví dụ: khi sử dụng ViewPager)

Trong hoạt động chính của bạn:

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

Trong đoạn chính cấp cao nhất của bạn (đoạn 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);
}

Trong YourFragment (đoạn lồng nhau):

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

8

Trong trường hợp của tôi, đó là một lỗi Android ( http://technet.weblineindia.com/mobile/onactivityresult-not-getting-called-in-nested-fragments-android/ ), nếu bạn sử dụng được hỗ trợ, FragmentActivitybạn phải sử dụng getSupportFragmentManagerthay vì getChildFragmentManager:

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

6

Nói ngắn gọn,

Trong đoạn, khai báo Fragment fragment = this;

sau khi sử dụng mà fragment.startActivityForResult.

Kết quả sẽ trở lại trong hoạt độngResult.


6

Giải pháp 1:

Gọi startActivityForResult(intent, REQUEST_CODE);thay vìgetActivity().startActivityForResult(intent, REQUEST_CODE); .

Giải pháp 2:

Khi startActivityForResult(intent, REQUEST_CODE);được gọi là hoạt động onActivityResult(requestCode,resultcode,intent)được gọi, và sau đó bạn có thể gọi fragments onActivityResult()từ đây, chuyển qua requestCode, resultCode and intent.


5

Bên trong mảnh vỡ của bạn, gọi

this.startActivityForResult(intent, REQUEST_CODE);

nơi thisđang đề cập đến các mảnh. Nếu không, hãy làm như @Clevester đã nói:

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

Tôi cũng phải gọi

super.onActivityResult(requestCode, resultCode, data);

trong hoạt động của cha mẹ onActivityResultđể làm cho nó hoạt động.

(Tôi đã điều chỉnh câu trả lời này từ câu trả lời của @ Clevester.)


5

Đối với những người sử dụng Android Navigation Component nên sử dụng trong Hoạt động của onActivityResult(...)các primaryNavigationFragmentđể có được nó là tài liệu tham khảo đoạn và gọi đoạn của fragment.onActivityResult(...).

Đây là hoạt động 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

Hầu hết các câu trả lời này cứ nói rằng bạn phải gọi super.onActivityResult(...)máy chủ Activitycủa bạn cho bạn Fragment. Nhưng điều đó dường như không làm việc cho tôi.

Vì vậy, trong máy chủ của Activitybạn, bạn nên gọi Fragments onActivityResult(...)thay thế. Đây là một ví dụ.

public class HostActivity extends Activity {

    private MyFragment myFragment;

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

Tại một số điểm trong của bạn HostActivity, bạn sẽ cần phải gán this.myFragmentcác Fragmentbạn đang sử dụng. Hoặc, sử dụng FragmentManagerđể có được Fragmentthay vì giữ một tham chiếu đến nó trong của bạn HostActivity. Ngoài ra, kiểm tra nulltrước khi bạn cố gắng gọi 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. Bạn chỉ có thể ghi đè BaseActivity onActivityResulttrên đoạn baseActivity.startActivityForResult.

  2. Trên BaseActivity thêm giao diện và ghi đè 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. Trên mảnh vỡ thực hiện 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();
      }
    }

Cách giải quyết này sẽ thực hiện các mẹo.


3

Nếu vấn đề trên gặp phải khi đăng nhập Facebook thì bạn có thể sử dụng mã dưới đây trong hoạt động chính của đoạn của bạn như:

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

Hoặc là:

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

Và thêm cuộc gọi dưới đây vào đoạn của bạn ...

callbackManager.onActivityResult(requestCode, resultCode, data);

2

Một trường hợp sử dụng khác chưa được mô tả trong các câu trả lời khác:

onActivityResult()khai báo trong đoạn không được gọi khi sử dụng exception.startResolutionForResult():

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

Trong trường hợp này thay thế exception.startResolutionForResult()bằng đoạn startIntentSenderForResult():

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

2

Phiên bản Kotlin (Trong hoạt động của bạn trênActivityResult ())

 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

Tôi có một sự nghi ngờ mạnh mẽ rằng tất cả các câu trả lời ở đây không gì khác hơn là hack. Tôi đã thử tất cả chúng và nhiều thứ khác, nhưng không có kết luận đáng tin cậy nào vì luôn có một số vấn đề ngu ngốc. Tôi cho một người không thể dựa vào kết quả không nhất quán. Nếu bạn xem tài liệu API Android chính thức cho Fragment, bạn sẽ thấy Google nêu rõ các điều sau:

Gọi startActivityForResult (Intent, int) từ Activity chứa đoạn.

Xem: API phân mảnh Android

Vì vậy, có vẻ như cách tiếp cận chính xác và đáng tin cậy nhất sẽ thực sự gọi startActivityForResult () từ hoạt động lưu trữ và cũng xử lý kết quả onActivityResult () từ đó.


2
Tôi không nghĩ "gọi startActivityForResult từ Activity" là một đề xuất. Nếu bạn nhìn vào việc triển khai bên trong lớp cơ sở Fragment, thì tất cả những gì nó làm là mActivity.startActivityFromFragment(this, intent, requestCode)- vì vậy nó không gì khác ngoài một trình bao bọc tiện lợi
Anti Veeranna

1

Mã của bạn có một đoạn lồng nhau. Gọi super.onActivityForResult không hoạt động

Bạn không muốn sửa đổi mọi hoạt động mà đoạn của bạn có thể được gọi từ và hoặc thực hiện một công việc xoay quanh việc gọi mọi đoạn trong chuỗi phân đoạn.

Đây là một trong nhiều giải pháp làm việc. tạo một đoạn khi đang bay và nối trực tiếp vào hoạt động với trình quản lý đoạn hỗ trợ. Sau đó gọi startActivityForResult từ đoạn vừa tạo.

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

Điều này thực sự hoạt động và tôi chỉ có một phiếu bầu cho nó. Tạo một mảnh trên bay. Quá dễ dàng nhưng giải pháp làm việc thực sự của nó. Thậm chí có người đã cố gắng chỉnh sửa nó cho tôi.
danny117

1

Vấn đề của tôi là với hoạt động Host tôi đã tìm thấy nó với một bộ android:launchMode="standard"tôi đã gỡ bỏ nó tạm thời nó hoạt động!


1

Một điểm không ai mentionđảm bảo rằng chế độ khởi chạy Hoạt động máy chủ của bạn không được đặt thành singleInstancehoặc singleTask.

onActivityResult sẽ không hoạt động nếu chế độ khởi chạy của bạn được đặt thành SingleInstance hoặc SingleTask. hoặc bạn gọi hoạt động của mình bằng các IntentFilters này

standardhoặc singleTopchế độ khởi chạy sẽ hoạt động tốt.


1

Nếu bạn đang sử dụng các đoạn lồng nhau, điều này cũng hoạt động:

getParentFragment().startActivityForResult(intent, RequestCode);

Ngoài ra, bạn phải gọi super.onActivityResulttừ hoạt động cha mẹ và điền vào onActivityResultphương thức của đoạn.


1

Tôi đã xử lý vấn đề bằng cách viết một lớp cơ sở mở rộng Fragmentvà trong onactivityresulthoạt động tôi đã xác định được đoạn đang chạy bằng cách sử dụng fragmenttag. Sau đó, tôi gọi một phương thức do người dùng định nghĩa trong lớp Fragmentbase. Điều này sẽ bắn một sự kiện trong đoạn hiện đang chạy.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.