什么可能导致Android活动从相机返回时无限重新启动自己?

时间:2012-09-19 21:24:36

标签: android android-activity camera infinite-loop restart

我的应用程序中有一个奇怪的错误,当我从相机应用程序返回后,在拍照后,活动会在无限循环中重新启动它。

UI流程如下:

  1. 主要活动 - >
  2. 接受照片活动 - >在onCreate()中使用startActivityForResult()
  3. 打开相机
  4. 相机屏幕 - >拍照(或取消) - >返回接受照片
  5. 完全创建“接受照片”屏幕,并立即停止并以无限循环重新创建
  6. 奇怪的是,它只发生在一些相机上。在运行Jellybean的Nexus S上,相机的行为正常,而Camera Zoom FX则会导致此错误。在运行ICS的Archos G9平板电脑上,相机和Zoom FX都会导致错误。

    我已经逐步检查了代码,但找不到重新启动调用的来源。当我在第二个(和后续的)onCreate()调用中停止调试器时,在调用堆栈中有一个ActivityThread.handleRelaunchActivity()调用。它的Intent没有太多信息:动作为null,类是AcceptPhoto。 mFlags具有603979776值,我不知道如何将其转换为实际的意图标记。

    但是,这种古怪并不止于此。在我的平板电脑上,我第一次拍照时,应用程序很好。如果我尝试拍第二张照片,屏幕会变得疯狂。如果我没有拍摄秒图片,而是返回上一个屏幕,那么在我打开新活动之前一切正常。无论从哪里开始,如果我一直返回到根活动并开始一个新的活动,它就会开始闪烁。

    我会尝试发布一些代码,但我怀疑这个错误不是由我的代码引起的,而是我在底层的Android代码中触发了一些东西。我希望的是,也许有人可以指出我正确的方向来找到解决这个bug的方法。任何事都有帮助,所以我感谢你的任何想法!

    用于打开相机的代码(使用实用程序类在AcceptPhoto.onCreate()中调用):

    private void openCamera(Context context) {
        Intent pictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        File tempFile = getTempFile(context);
        try {
            if (tempFile != null) {
    
                pictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(tempFile));
    
                ((Activity) context).startActivityForResult(pictureIntent, GET_ITEM_PHOTO);
            } else {
                Toast.makeText(context, "Could not create temp file", Toast.LENGTH_SHORT).show();
            }
        } catch (Exception e) {
            Toast.makeText(context, "Error opening camera " + e.getMessage(), Toast.LENGTH_LONG).show();
            e.printStackTrace();
        }
    }
    

    用于显示图片的代码,在AcceptPhoto.onActivityResult()中调用:

    private void displayPhoto() {
        if (cameraUtils == null) {
            cameraUtils = new CameraUtil();
        }
        previewImageView.setImageDrawable(null);
        File tempFile = cameraUtils.getTempFile(this);
    
        int rotation = 0;
        try {
            ExifInterface exif = new ExifInterface(tempFile.getPath());
            String orientation = exif.getAttribute(ExifInterface.TAG_ORIENTATION);
            Log.i("SPRING", "Photo orientation " + orientation);
            rotation = getBitmapRotation(Integer.valueOf(orientation));
            Log.i("SPRING", "The image needs to be rotated by " + (rotation) + " degrees");
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        try {
            previewBitmap = BitmapEncoderUtil.loadPrescaledBitmap(tempFile);
            if (rotation != 0) {
    
                Matrix rotationMatrix = new Matrix();
                rotationMatrix.postRotate(rotation);
    
                int w = previewBitmap.getWidth();
                int h = previewBitmap.getHeight();
    
                Bitmap rotatedBitmap = Bitmap.createBitmap(previewBitmap, 0, 0, w, h, rotationMatrix, false);
    
                previewBitmap = rotatedBitmap;
            }
            previewImageView.setImageBitmap(previewBitmap);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    

    实用程序类中用于创建/检索相机保存照片的文件的方法:

    public File getTempFile(Context context) {
    
        String externalStorageStateString = Environment.getExternalStorageState();
        File cacheDirectory;
        // try to save in external storage
        if (externalStorageStateString.equals(Environment.MEDIA_MOUNTED)) {
            cacheDirectory = context.getExternalCacheDir();
        } else {
            // save in internal storage
            cacheDirectory = context.getCacheDir();
        }
        File tempSnapshotFile = new File(cacheDirectory, MissionOtherActivity.ITEM_SNAPSHOT_PATH);
    
        // make sure the file exists, possible fix for the camera bug
        try {
            if (tempSnapshotFile.exists() == false) {
                tempSnapshotFile.getParentFile().mkdirs();
                tempSnapshotFile.createNewFile();
            }
    
        } catch (IOException e) {
            Log.e("SPRING", "Could not create file.", e);
        }
        return tempSnapshotFile;
    }
    

1 个答案:

答案 0 :(得分:18)

经过大量调查后,似乎重新启动的呼叫来自onConfigurationChanged。我还是没弄明白为什么,但至少我知道该避免什么。

它解释了为什么有些相机触发了这个错误而其他相机没有:一些相机使用与我的应用程序相同的配置,其他相机没有。

编辑:我在其他调查后发现我在扩展的Application类中有一个错误。在onConfigurationChanged方法中,我通过强制某个语言环境来更改配置。这触发了一个新的onConfigurationChanged()调用,它导致了一个无限循环和随后的屏幕创建/销毁序列。我不知道为什么我把这些代码放在onConfigurationChanged()方法中,但我想你必须忍受才能学习:)