Android onActivityResult не вызывается / срабатывает - PullRequest
27 голосов
/ 16 февраля 2011

Я много читал о проблемах с onActivityResult, но, похоже, ни одна из описанных проблем не подходит мне, например, установка отрицательного кода запроса в startActivityForResult или что-то еще.

Я играю с камерой в своей Деятельности, которая передает предварительный просмотр в SurfaceView. Сделав снимок, я закрываю камеру, освобождая ее ресурсы, звоню setResult(RESULT_OK, DataIntent) и надеюсь, что onActivityResult запущен в моем родителе.

Но это не так. Если я устанавливаю результат в onCreate дочернего Activity и заканчиваю дочерний в onCreate, результат не передается onActivityResult.

Какова возможная причина того, что onActivityResult не срабатывает? Я напишу некоторые из моих источников для понимания того, что я делаю ...

public class MainActivity extends Activity {
    Button mButtonScan;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        mButtonScan = (Button)findViewById(R.id.main_btn_scan);
    }

    /**
    * OnClick Event called from main.xml
    * @param v View that called that onClickEvent
    */
    public void btnCaptureClick(View v) {
        Intent intent = new Intent(this, CaptureActivity.class);
        startActivityForResult(intent, Constants.REQUEST_CODE_CAPTURE);
    }

    /**
    * callback for this Activity. Called when an Activity which was started by
    * this.startActivityForResult(intent, requestCode) sets its result and calls finish()
    */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        String foo = "foo";
        switch (requestCode) {
            case Constants.REQUEST_CODE_CAPTURE:
                switch (resultCode) {
                    case RESULT_FIRST_USER:
                        Toast.makeText(this, data.getStringExtra(Config.SCAN_RESULT_TEXT), Toast.LENGTH_LONG).show();
                        break;
                    case RESULT_CANCELED:
                        break;
                    default:
                        break;
                }
                break;

            default:
                super.onActivityResult(requestCode, resultCode, data);
                break;
        }
    }
}


public class CaptureActivity extends Activity implements ActivityCallback, SurfaceHolder.Callback, PreviewCallback {

    private Preview mPreview;
    private Camera mCam;
    private SurfaceHolder mHolder;
    private Size size;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.capture);

        mPreview = (Preview)findViewById(R.id.capture_preview); 
    }

    @Override
    public void onValidDecodeResult(Result rawResult, Bitmap barcode) {
        Intent intent = new Intent();
        if (rawResult != null && barcode != null) {
            intent.putExtra(Config.SCAN_RESULT_TEXT, rawResult.getText());
            intent.putExtra(Config.SCAN_RESULT_FORMAT, rawResult.getBarcodeFormat().getName());
            intent.putExtra(Config.SCAN_RESULT_BMP, barcode);
        } else {
            intent.putExtra(Config.SCAN_RESULT_TEXT, "foo");
            intent.putExtra(Config.SCAN_RESULT_FORMAT, "bar");
            intent.putExtra(Config.SCAN_RESULT_BMP, "barcode");
        }
        mPreview = null;
        setResult(Activity.RESULT_FIRST_USER, intent);
        finish();   
    }

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {
        MultiFormatReader reader = new MultiFormatReader();     
        PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data, size.width, size.height, 160, 60, 480, 360);
        GlobalHistogramBinarizer binarizer = new GlobalHistogramBinarizer(source);
        BinaryBitmap bb = new BinaryBitmap(binarizer);
        Result result = null;
        try {
            result = reader.decode(bb);
        } catch (NotFoundException e) {
            //do NOTHING cause e == null
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            reader.reset();
        }
        if (result != null) {
            mCam.stopPreview();
            releaseCameraResources();
            onValidDecodeResult(result, source.renderCroppedGreyscaleBitmap());
        } else {
            camera.setOneShotPreviewCallback(this);
        }       
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        try {
            mCam = Camera.open();
            mCam.setPreviewDisplay(mPreview.getHolder());
        } catch (IOException e) {
            releaseCameraResources();
            e.printStackTrace();
        }           
    }

    private void releaseCameraResources() {
        mCam.release();
        mCam = null;
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
        //begin Preview
        Camera.Parameters parameters = mCam.getParameters();

        List<Size> sizes = parameters.getSupportedPreviewSizes();

        size = getOptimalPreviewSize(sizes, width, height);
        parameters.setPreviewSize(size.width, size.height);

        mCam.setParameters(parameters);
        mCam.startPreview();
        mCam.setOneShotPreviewCallback(this);
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if (mCam != null) {
            mCam.stopPreview();
            releaseCameraResources();
        }   
    }

    private Size getOptimalPreviewSize(List<Size> sizes, int width, int height) {
        final double ASPECT_TOLERANCE = 0.05;
        double targetRatio = (double) width / height;

        if (sizes == null) return null; 
            Size optimalSize = null;
            double minDiff = Double.MAX_VALUE;

            int targetHeight = height;

            for (Size size: sizes) {
                double ratio = (double) size.width / size.height;
                if(Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) {
                    continue;
                }

                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }               
            }

            if (optimalSize == null) {
                //cannot find matching aspect-ratio
                minDiff = Double.MAX_VALUE;
                for (Size size : sizes) {
                    if (Math.abs(size.height - targetHeight) < minDiff) {
                        optimalSize = size;
                        minDiff = Math.abs(size.height - targetHeight);
                }
            }
        }
        return optimalSize;
    }
}

Ответы [ 8 ]

49 голосов
/ 02 октября 2014

Убедитесь, что числовой параметр (requestCode), переданный startActivityForResult(...), равен> = 0

36 голосов
/ 14 мая 2011

Была такая же проблема.проверьте свой манифест и убедитесь, что вы НЕ используете один экземпляр:

android:launchMode="singleInstance"
23 голосов
/ 28 июля 2014

Удаление android:noHistory="true" из действия, с которым у меня возникла проблема, решило проблему для меня.

18 голосов
/ 18 февраля 2011

Я решил проблему сам сейчас.

После отказа от запуска onActivityResult я решил «взломать» инкапсуляцию Android, передав статическую ссылку из MainActivity в CaptureActivity, даже если я знаю, что это не очень хорошая идея.

После вызова finish() MAGICALLY onActivityResult запускается с Context.RESULT_CANCELLED ... как и ожидалось, потому что я больше не звоню setResult.

Получение onActivityResult срабатывания Я выяснил, почему он работает сейчас.Я узнал, что это как-то связано с растровым изображением, переданным Intent.Если я добавлю Parcellable растровое изображение в мой resultIntent onActivityResult никогда не будет запущен.

Так что удаление следующей строки в коде выше будет работать:

intent.putExtra(Config.SCAN_RESULT_BMP, barcode);

Это нормально для меня, потому чтоМне действительно не нужно BitMap в этом другом действии.Это была скорее «особенность», чем необходимость.

Если некоторые из вас, ребята, хотят передать большие данные в Intent, например Bitmap, подумайте о том, чтобы сохранить их где-нибудь на SD, передать путь в Intent, читая этот Bitmap с SDв ParentActivity ( Как сделать фотографию с помощью Intent ).

Как указано здесь , предел Parcelable составляет 1 МБ, таким образом, все большее передается вIntent вызовет внутренний TransactionTooLargeException и тихо завершится с ошибкой

3 голосов
/ 03 октября 2016

Еще один вариант на этот.Из DialogFragment вы можете startActivityForResult.Но если ваше намерение запускается из связанной деятельности, вы должны включить getActivity() до startActivityForResult.Смотрите ниже (последняя строка):

Activity activeOne=FileDialogWindow.this.getActivity();
Intent intent = new Intent(activeOne,FolderSelectionActivity.class);
String message = "foobar";
intent.putExtra(EXTRA_MESSAGE, message);
getActivity().startActivityForResult(intent,1);
3 голосов
/ 22 апреля 2016

В моем случае это не сработало, так как я добавил флаг Intent.FLAG_ACTIVITY_NEW_TASK при создании намерения для startActivityForResult.Удаление ее решило мою проблему.

1 голос
/ 16 февраля 2011

Это может быть просто случай, когда ваше предыдущее действие не заканчивается? Попробуйте отладку с помощью Log.d и просмотрите logcat, чтобы увидеть, действительно ли стек вызовов достигает оператора finish () в вашем классе CaptureActivity.

0 голосов
/ 24 сентября 2014

в моем случае код запроса сканирования должен быть IntentIntegrator.REQUEST_CODE ,

, то есть

startActivityForResult(intent, IntentIntegrator.REQUEST_CODE).

Надежда может помочь вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...