You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android开发:如何让类A等待类B的拍照执行结果?

Fixing the Async Camera Result Issue in Android

Hey there, let's work through your problem! The main issue here is that startActivityForResult runs asynchronously—it doesn't pause your code to wait for the camera to finish taking a photo. Your attempt to use wait() is actually harmful here: it'll freeze your UI thread (leading to an ANR error) and there's no corresponding notify() to wake it up, so you'll just get stuck. Also, when you call camera.getImage() right after takePicture(), the photo hasn't been captured yet, so image will be null and you'll hit a NullPointerException when trying to compress it.

Let's fix this with two common, reliable approaches:


Option 1: Use a Callback Interface (Standard Android Practice)

Callbacks are the go-to way to handle async results in Android. We'll define an interface to let your camera class notify the caller when the photo is ready.

Step 1: Update Your Camera Class (Class B)

First, add a callback interface to your camera helper class, and remove that broken wait() call:

public class CameraHelper { // Assuming your class B is named CameraHelper
    static final int REQUEST_IMAGE_CAPTURE = 1;
    private Bitmap image = null;
    private OnPictureTakenListener resultListener;

    // Define the callback interface
    public interface OnPictureTakenListener {
        void onPictureSuccess(Bitmap capturedBitmap);
        void onPictureFailed(); // Handle cancellations or errors
    }

    // Set the listener from the calling class
    public void setOnPictureTakenListener(OnPictureTakenListener listener) {
        this.resultListener = listener;
    }

    public void takePicture(Context context, Activity activity) {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePictureIntent.resolveActivity(context.getPackageManager()) != null) {
            activity.startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        } else {
            // No camera app available? Notify failure
            if (resultListener != null) {
                resultListener.onPictureFailed();
            }
        }
        // Remove the wait() call here—it's causing problems!
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data); // Don't forget super!
        if (requestCode == REQUEST_IMAGE_CAPTURE) {
            if (resultCode == Activity.RESULT_OK && data != null) {
                Bundle extras = data.getExtras();
                image = (Bitmap) extras.get("data");
                // Send the result back to the caller via callback
                if (resultListener != null) {
                    resultListener.onPictureSuccess(image);
                }
            } else {
                // Photo was cancelled or failed
                if (resultListener != null) {
                    resultListener.onPictureFailed();
                }
            }
        }
    }

    public Bitmap getImage(){
        return image;
    }
}

Step 2: Update the Calling Class (Class A)

Now, instead of trying to get the image immediately, we'll wait for the callback to fire:

public void openCamera() {
    CameraHelper camera = new CameraHelper();
    
    // Set up the callback to handle the result
    camera.setOnPictureTakenListener(new CameraHelper.OnPictureTakenListener() {
        @Override
        public void onPictureSuccess(Bitmap capturedBitmap) {
            // Now we have the image—process it here
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            capturedBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
            byte[] picture = outStream.toByteArray();
            _addView.SetCameraPicture(picture);
        }

        @Override
        public void onPictureFailed() {
            // Let the user know something went wrong
            Toast.makeText(_addView, "拍照失败或已取消", Toast.LENGTH_SHORT).show();
        }
    });

    camera.takePicture((Context) _addView, (Activity) _addView);
}

Option 2: Use LiveData (Modern Jetpack Approach)

If you're using Jetpack components, LiveData is a great choice—it handles lifecycle automatically so you don't have to worry about memory leaks.

Step 1: Update Camera Class with LiveData

public class CameraHelper {
    static final int REQUEST_IMAGE_CAPTURE = 1;
    private final MutableLiveData<Bitmap> imageLiveData = new MutableLiveData<>();

    // Expose immutable LiveData to the caller
    public LiveData<Bitmap> getImageLiveData() {
        return imageLiveData;
    }

    public void takePicture(Context context, Activity activity) {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        if (takePictureIntent.resolveActivity(context.getPackageManager()) != null) {
            activity.startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        } else {
            imageLiveData.postValue(null); // Signal failure
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK && data != null) {
            Bundle extras = data.getExtras();
            Bitmap image = (Bitmap) extras.get("data");
            imageLiveData.postValue(image); // Send result to observers
        } else {
            imageLiveData.postValue(null); // Signal failure/cancellation
        }
    }
}

Step 2: Observe LiveData in the Calling Class

public void openCamera() {
    CameraHelper camera = new CameraHelper();
    
    // Observe the LiveData for results
    camera.getImageLiveData().observe((AppCompatActivity) _addView, bitmap -> {
        if (bitmap != null) {
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outStream);
            byte[] picture = outStream.toByteArray();
            _addView.SetCameraPicture(picture);
        } else {
            Toast.makeText(_addView, "拍照失败或已取消", Toast.LENGTH_SHORT).show();
        }
    });

    camera.takePicture((Context) _addView, (Activity) _addView);
}

Quick Notes to Remember

  • Never call wait() on the UI thread—it'll make your app freeze and crash with an ANR.
  • Make sure your camera class correctly receives the onActivityResult callback. If your class B isn't an Activity/Fragment, you'll need to forward the callback from your host Activity to it.
  • If you're using AndroidX, consider using registerForActivityResult instead of the old startActivityForResult—it's more lifecycle-safe and avoids some edge cases.

内容的提问来源于stack exchange,提问作者Belved

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:11:19