【问题标题】:Android onActivityResult not called / triggeredAndroid onActivityResult 未调用/触发
【发布时间】:2011-02-16 17:15:56
【问题描述】:

我阅读了很多关于 onActivityResult 问题的信息,但似乎没有一个所描述的问题适合我,比如在 startActivityForResult 中放置一个否定的 requestCode 或其他内容。

我在我的 Activity 中使用相机,它将其预览流式传输到 SurfaceView。 拍照后,我关闭了释放资源的摄像头,调用setResult(RESULT_OK, DataIntent) 并希望在我的父母中触发onActivityResult

但事实并非如此。如果我在子活动的onCreate 中设置结果并在 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;
    }
}

【问题讨论】:

  • 勾勒代码并点击工具栏上的代码按钮。
  • 您是否尝试在 onValidDecodeResult 函数中放置断点?也许它从未被输入,因此在父活动中没有结果?
  • 是的,我在 onValidDecodeResult 中设置了一个断点。一旦 onPreviewFrame 中的结果不为空,就会触发它。它得到的数据是我怀疑的。

标签: android


【解决方案1】:

确保传递给startActivityForResult(...) 的数字参数(requestCode)>=0

【讨论】:

  • 天哪!我什至不考虑它!但最好说:“确保传递的 requestCode 是 ...”。更清楚了。
【解决方案2】:

遇到了同样的问题。检查您的清单并确保您没有使用单实例:

android:launchMode="singleInstance"

【讨论】:

  • 对我来说,我删除的是android:noHistory="true"
  • +1 但是,如果您使用的是 SearchView 并且您必须将启动模式设置为 SingleInstante;有什么方法可以停止为 searchView 打开新活动??
  • 奇怪的行为。谢谢你的提示。为我工作,因为在活动中添加 onactivityResult 后停止调用。
  • ...或单任务。关于调用者活动。
【解决方案3】:

从我遇到问题的活动中删除 android:noHistory="true" 为我解决了问题。

【讨论】:

  • 你这个摇滚狂人!很棒的发现。谢谢
  • @ralphgabb 你打赌!
  • 这拯救了我的一天
【解决方案4】:

我现在自己解决了这个问题。

在放弃触发onActivityResult 之后,我决定通过将静态引用从 MainActivity 传递给 CaptureActivity 来“破解”Android 封装,即使我知道这不是一个好主意。

finish() 调用之后,神奇地onActivityResultContext.RESULT_CANCELLED... 触发,正如预期的那样,因为我不再调用setResult

触发onActivityResult 我调查了为什么它现在可以工作。我发现它与传递给 Intent 的位图有关。如果我将 Parcellable 位图放入我的 resultIntent,onActivityResult 永远不会被解雇。

因此删除上面代码中的以下行将起作用:

intent.putExtra(Config.SCAN_RESULT_BMP, barcode);

这对我来说没问题,因为我在其他活动中并不需要位图。与其说是需要,不如说是一个“功能”。

如果你们中的一些人想将大数据传递到 Intent 中,例如 Bitmap,请考虑将其存储在 SD 中的某个位置,在 Intent 中传递路径,同时在 ParentActivity 中从 SD 中读取此 BitmapHow to take a photo by Intent)。

here 所述,Parcelable 的限制为 1MB,因此传递给Intent 的所有内容都将导致内部 TransactionTooLargeException 并且会静默失败

【讨论】:

  • 另一种可能难以发现原因的情况:当有这样的嵌入方案时 TabActivity -> ActivityGroup ->Activity 和最后一个嵌入实体(Activity)通过使用 Window.getDecorView( ) 方法 - 不要从最后一个嵌入实体中调用 startActivityForResult(),而是从更高的一步调用,因此从 ActivityGroup 调用。还要在同一个 ActivityGroup 实例中等待结果。
  • 它解决了我的问题。但是,您能否解释一下为什么当您执行 putExtra() 时它不起作用?
  • @AndrewDashin 不,我真的不能。我只能假设,我的位图太大而无法打包。
  • 遇到了同样的问题...谁知道尝试返回可打包位图会使 onActivityResult() 永远不会被调用??? -__- 顺便说一句,非常感谢这篇文章.. 为我节省大量时间!
【解决方案5】:

就我而言,它没有被触发,因为我在为startActivityForResult 创建意图时添加了标志Intent.FLAG_ACTIVITY_NEW_TASK。删除它解决了我的问题。

【讨论】:

    【解决方案6】:

    这个的另一个变种。从 DialogFragment,您可以startActivityForResult。但如果你的 Intent 是从关联的 Activity 启动的,则必须在 startActivityForResult 之前包含 getActivity()。见下文(最后一行):

    Activity activeOne=FileDialogWindow.this.getActivity();
    Intent intent = new Intent(activeOne,FolderSelectionActivity.class);
    String message = "foobar";
    intent.putExtra(EXTRA_MESSAGE, message);
    getActivity().startActivityForResult(intent,1);
    

    【讨论】:

    • 请使用标记(反引号)格式化文本中的code-words
    • 非常感谢您的回答 - 拯救了我的白天/黑夜!
    • 我已经为另一个线程的结果启动了活动。所以我不得不实现runOnUIThread()
    【解决方案7】:

    可能只是您之前的活动没有完成?尝试使用 Log.d 进行调试并查看 logcat 以查看调用堆栈是否实际到达 CaptureActivity 类中的 finish() 语句。

    【讨论】:

    • 如果我在 CaptureActivity 中调用 this.finish(),CaptureActivity 怎么可能没有完成。如果我在 finish() 调用中设置断点,它会在 Android 的 Activity.class 中触发。我在 onDestroy 上放了一个日志,看看它是否被调用并被调用。还有其他想法吗?
    【解决方案8】:

    在我的情况下,扫描请求代码必须是IntentIntegrator.REQUEST_CODE

    那是

    startActivityForResult(intent, IntentIntegrator.REQUEST_CODE).

    希望能帮到你。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-10
      • 2014-10-24
      • 2017-06-15
      • 1970-01-01
      相关资源
      最近更新 更多