takepicture зависает на Android 2.3.3 - PullRequest
10 голосов
/ 30 июня 2011

У меня есть несколько кодов фотографирования, которые работают в Android 2.1 и 2.2.Но эти коды сломались на Android 2.3.Потратив время на исправление этой проблемы, которая оказалась напрасной, я хотел бы попросить о помощи здесь.

Мой код для создания снимка выглядит так:

создайте класс Camlayerextends SurfaceView

public class CamLayer extends SurfaceView implements SurfaceHolder.Callback {
    private void init(Context context){
        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        mCamera = Camera.open();
    }

    public CamLayer(Context context) {
        super(context);
        init(context);
    }

    public CamLayer(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        Log.i(TAG+".surfaceChanged", "being called!");
        Log.i(TAG+".surfaceChanged", "w="+w); 
        Log.i(TAG+".surfaceChanged", "h="+h);
        if (isPreviewRunning) {
            mCamera.stopPreview();
        }

        try {
            mCamera.setPreviewDisplay(holder);
            mCamera.setPreviewCallback(mPreviewCallback);
        } catch (IOException e) {
            Log.e(TAG+".surfaceCreated", "mCamera.setPreviewDisplay(holder);");
        }

        Camera.Parameters p = mCamera.getParameters();  
        setOptimalSize(p, w, h, SIZEOFPREVIEW);
        setOptimalSize(p, w, h, SIZEOFPICTURE);
        mCamera.setParameters(p);

        mCamera.startPreview();
        isPreviewRunning = true;
    }

    public void takePicture(){
        Log.i(TAG+".takePicture", "being called!");
        mCamera.takePicture(null, null, mPictureCallback);
        Log.i(TAG+".takePicture", "call ended!");
    }
}

CamLayer.takePicture() будет вызываться внешними классами для запуска.

Проблема в том, что в Android 2.3.3 takePicture зависает, поэтомупроблема ANR найдена.В /data/anr/traces.txt, ниже находятся.Как видите, native_takePicture никогда не возвращается.

РЕЗЬБЫ DALVIK:

(mutexes: tll=0 tsl=0 tscl=0 ghl=0 hwl=0 hwll=0)
"main" prio=5 tid=1 NATIVE

  | group="main" sCount=1 dsCount=0 obj=0x40022170 self=0xce68

  | sysTid=2411 nice=0 sched=0/0 cgrp=default handle=-1345006464

  at android.hardware.Camera.native_takePicture(Native Method)

  at android.hardware.Camera.takePicture(Camera.java:746)

  at android.hardware.Camera.takePicture(Camera.java:710)

  at oms.cj.tube.camera.CamLayer.takePicture(CamLayer.java:256)

  at oms.cj.tube.camera.DefineColor.takePicture(DefineColor.java:61)

  at oms.cj.tube.camera.DefineColor.onKeyUp(DefineColor.java:71)

  at android.view.KeyEvent.dispatch(KeyEvent.java:1280)

  at android.app.Activity.dispatchKeyEvent(Activity.java:2078)

  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:16
66)
  at android.view.ViewRoot.deliverKeyEventToViewHierarchy(ViewRoot.java:2571)

  at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2546)

  at android.view.ViewRoot.handleMessage(ViewRoot.java:1878)

  at android.os.Handler.dispatchMessage(Handler.java:99)

  at android.os.Looper.loop(Looper.java:123)

  at android.app.ActivityThread.main(ActivityThread.java:3691)

  at java.lang.reflect.Method.invokeNative(Native Method)

  at java.lang.reflect.Method.invoke(Method.java:507)

  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)

  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)

  at dalvik.system.NativeStart.main(Native Method)

Есть ли у кого-нибудь такая же проблема?И знаете, как это исправить?

Ответы [ 5 ]

7 голосов
/ 04 мая 2012

Я также заметил, что mCamera.takePicture (null, null, handler) зависает.Я попытался очистить обработчик предварительного просмотра: mCamera.setPreviewCallback (null) перед вызовом takePicture (), и теперь он работает.

5 голосов
/ 31 июля 2011

У меня была точно такая же проблема сегодня, когда мы тестировали наше приложение на Samsung Exhibit 4G с Android 2.3.3 и решили ее, используя обходной путь.

Я больше не вызываю takepicture , но использую последний обратный вызов предварительного просмотра в качестве изображения.

Проблема заключается в том, что обратный вызов предварительного просмотра отправляет буфер данных в формате NV21,

Таким образом, вы должны преобразовать изображение, используя этот процесс: NV21 -> RGB -> Загрузить растровое изображение -> Сжать в JPEG

Наш код сейчас выглядит так:

    camera.setPreviewCallback(new PreviewCallback() {

        @Override
        public synchronized void onPreviewFrame(byte[] data, Camera arg1) {
            if (!mTakePicture) {
                CameraPreview.this.invalidate();
            } else {

                if (mTakePictureCallback != null && !mPictureTaken) {
                    int rgb[] = new int[previewSize.width*previewSize.height];
                    decodeYUV420SP(rgb, data, previewSize.width, previewSize.height);
                    Bitmap memoryImage = Bitmap.createBitmap(rgb, previewSize.width, previewSize.height, Bitmap.Config.ARGB_8888);
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    memoryImage.compress(CompressFormat.JPEG, 100, baos);
                    shutterSound();
                    setBackgroundDrawable(new BitmapDrawable(getContext().getResources(), memoryImage));
                    mTakePictureCallback.onPictureTaken(baos.toByteArray(), arg1);
                }
                mPictureTaken = true;
                camera.stopPreview();
            }
        }
    });

Код decodeYUV420SP здесь http://www.41post.com/3470/programming/android-retrieving-the-camera-preview-as-a-pixel-array, который нашел его на Кетаи http://code.google.com/p/ketai/

Когда вы делаете снимок, просто установите mTakePicture переменная на true

Я работаю над улучшенной версией, но это должно помочь вам.

1 голос
/ 18 апреля 2013

Я не уверен, какой метод setOptimalSize используется в вашем коде, но убедитесь, что вы установили параметр камеры

mCamera.setPictureSize(captureSize.width, captureSize.height);
mCamera.setPictureFormat(ImageFormat.JPEG);
0 голосов
/ 05 августа 2014

Я столкнулся с этой проблемой с телефонами GB, и для меня это произошло потому, что я вызывал camera.startPreview () сразу после вызова camera.takePicture (), и это вызывало некоторую блокировку потоков в Android.Исправление состояло в том, чтобы переместить camera.startPreview () в обратный вызов, переданный в camera.takePicture (), так, чтобы он вызывался только после того, как были получены данные изображения (пример кода ниже).Это, конечно, уместно, только если вы заинтересованы в перезапуске предварительного просмотра после того, как снимок сделан.

// BAD BAD DON'T DO THIS!
public void myTakePicture(Camera.PictureCallback callback) {
  mCamera.takePicture(null, null, null, callback);
  mCamera.startPreview();
}

// ...
// The way that worked for me
public void myTakePicture(final Camera.PictureCallback callback) {
  mCamera.takePicture(null, null, null, new Camera.PictureCallback() {
    @Override
    public void onPictureTaken(byte[] pictureData, Camera camera) {
      callback.onPictureTaken(pictureData, camera);
      mCamera.takePicture();
    }
  });
}

Это не только убрало ANR при вызове takePicture, но также исправило нативный сбой при startPreviewэто происходило на некоторых более дорогих телефонах (особенно a> = 4.3 Nexus 5).Надеюсь, это поможет!

0 голосов
/ 01 июля 2011

Проблема заключается в том, что записаны приведенные ниже коды.

  1. Определен PreviewCallback,

    PreviewCallback mPreviewCallback = new PreviewCallback() {
    
        @Override
            public void onPreviewFrame(byte[] data, Camera camera) {
                //Log.i(TAG+".mPreviewCallback.onPreviewFrame", "being called!");
            }
    };
    
  2. mCamera.setPreviewCallback (mPreviewCallback);

  3. mCamera.takePicture ()

Это работает в 2.1 / 2.2, но не в 2.3.

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

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