web-dev-qa-db-ja.com

カメラ:setDisplayOrientation関数がAndroid 2.3.6のSamsung Galaxy ACEで機能しない

研究用のシンプルなカメラアプリケーションを作成しようとしていました。私は Android Camera Official Document を読んでから、コーディングを開始しました。だから私はそれを機能させるためにいくつかのステップを行いました

1.アプリのカメラ機能に必要な権限を追加しました。

2.アクティビティをポートレートモードのみにロックしました。

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

3.カメラを機能させるために、いくつかのカメラコールバックを追加しました。

  • SurfaceHolder.Callback、
  • Camera.PreviewCallback
  • AutoFocusCallback
  • ShutterCallback
  • RAW画像データのPictureCallback
  • JPG画像データのPictureCallback

4。surfaceChangedメソッドで、カメラ設定をカスタマイズしています。これまでのところ、私はこれをほぼすべてのAndroidデバイスで動作しています

  • LG
  • スパイス
  • サムスン
  • HTC
  • マイクロマックス
  • ソニー
  • モトローラ
  • Google Nexusシリーズ。

しかしそれから私はSamsung Galaxy ACEでテストしたAndroidバージョン2.3.6で、カメラディスプレイプレビューが横向きモードに回転しました。

したがって、log-cat/breakポイントを配置した後、以下のメソッドはこの特定のモデルでは機能しないことがわかります

//This method is not working for Samsung Galaxy ACE
 camera.setDisplayOrientation(90); 
//or 
parameters.set("orientation", "portrait");
//or
parameters.setRotation(90);

注:I GoogleおよびSOでも、これまでのところこれで運が取れなかった

参考までに、私のサンプルコードは以下です

@Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
        Log.v(TAG, "surfaceChanged get called");

        if (previewing) {
            camera.stopPreview();
            previewing = false;
        }

        if (camera != null) {
            try {
                Camera.Parameters parameters = camera.getParameters();
                List<Size> sizes = parameters.getSupportedPictureSizes();

                Camera.Size result = null;
                for (int i = 0; i < sizes.size(); i++) {
                    result = (Size) sizes.get(i);
                    Log.i("PictureSize", "Supported Size. Width: "
                            + result.width + "height : " + result.height);

                    if (result.width == 640) {
                        parameters.setPreviewSize(result.width, result.height);// 640*480
                        parameters.setPictureSize(result.width, result.height);
                    } else {

                    }
                }


                //**************************************************************//

                /* 
                 * Here is the logic I have added to Manage Camera Display Orientation
                 *  It checks Current Orientation and SDK and then rotate display to make it Portrait view.
                 */
                int currentSDKVersion = Android.os.Build.VERSION.SDK_INT;
                Log.d(TAG, "currentVersion " + currentSDKVersion);

                if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                    if (currentSDKVersion != 7) {

                        camera.setDisplayOrientation(90);
                         parameters.setRotation(90);
                    } else {
                            parameters.setRotation(90);

                        /*
                         * params.set("orientation", "portrait");
                         * params.set("rotation",90);
                         */
                    }
                } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
                    if (currentSDKVersion != 7) {

                        camera.setDisplayOrientation(0);
                    } else {

                        parameters.set("orientation", "landscape");
                        parameters.set("rotation", 90);

                    }
                }


                //**************************************************************//

                camera.setParameters(parameters);
                camera.setPreviewDisplay(surfaceHolder);
                camera.startPreview();
                camera.autoFocus(myAutoFocusCallback);
                camera.setOneShotPreviewCallback(cameraPreviewCallback);
                previewing = true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

私のカメラアクティビティ(MainActivity.Java)完全なコードは次のとおりです。

public class MainActivity extends Activity implements SurfaceHolder.Callback,
        OnClickListener {

    public static final String TAG = "CameraActivity";
    private Context context = null;
    Camera camera = null;
    private SurfaceView surfaceView = null;
    private SurfaceHolder surfaceHolder = null;
    boolean previewing = false;
    private LayoutInflater controlInflater = null;
    private Button buttonTakePicture = null;
    //private TextView textViewResultInfo = null;

    @SuppressWarnings("deprecation")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Log.v(TAG, "onCreate get called");

        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        //textViewResultInfo = (TextView) findViewById(R.id.textViewResultInfo);
        context = this;

        getWindow().setFormat(PixelFormat.UNKNOWN);
        surfaceView = (SurfaceView) findViewById(R.id.surfaceview);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_Push_BUFFERS);

        controlInflater = LayoutInflater.from(getBaseContext());
        View viewControl = controlInflater.inflate(R.layout.control, null);
        LayoutParams layoutParamsControl = new LayoutParams(
                LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
        this.addContentView(viewControl, layoutParamsControl);

        buttonTakePicture = (Button) findViewById(R.id.takepicture);
        buttonTakePicture.setOnClickListener(this);

    }

    @Override
    public void surfaceCreated(SurfaceHolder arg0) {

        Log.v(TAG, "surfaceCreated get called");
        camera = Camera.open();

        if (camera != null) {
            try {
                camera.setPreviewDisplay(surfaceHolder);
                camera.startPreview();
                previewing = true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
        Log.v(TAG, "surfaceChanged get called");

        if (previewing) {
            camera.stopPreview();
            previewing = false;
        }

        if (camera != null) {
            try {

                 //new MainActivity().setCameraDisplayOrientation();

                Camera.Parameters parameters = camera.getParameters();
                // List<String> focusModes =
                // parameters.getSupportedFocusModes();
                // if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO))
                // {
                // parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
                // }

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

                Camera.Size result = null;
                for (int i = 0; i < sizes.size(); i++) {
                    result = (Size) sizes.get(i);
                    Log.i("PictureSize", "Supported Size. Width: "
                            + result.width + "height : " + result.height);

                    if (result.width == 640) {
                        parameters.setPreviewSize(result.width, result.height);// 640*480
                        parameters.setPictureSize(result.width, result.height);
                    } else {

                    }
                }


                //**************************************************************//

                Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
                int rotation = display.getRotation();
                Log.v(TAG, "Current Device Orientation is ="+rotation);

                /* 
                 * Here is the logic I have added to Manage Camera Display Orientation
                 *  It checks Current Orientation and SDK and then rotate display to make it Portrait view.
                 */
                int currentSDKVersion = Android.os.Build.VERSION.SDK_INT;
                Log.d(TAG, "currentVersion " + currentSDKVersion);

                if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                    if (currentSDKVersion != 7) {
                        Log.i(TAG, "ORIENTATION_PORTRAIT +SDK is: " + currentSDKVersion
                                + "rotate 90");
                        camera.setDisplayOrientation(90);
                         parameters.setRotation(90);
                    } else {
                        Log.i(TAG, "ORIENTATION_PORTRAIT +SDK is: " + currentSDKVersion
                                + "rotate 90");
                        parameters.setRotation(90);

                        /*
                         * params.set("orientation", "portrait");
                         * params.set("rotation",90);
                         */
                    }
                } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
                    if (currentSDKVersion != 7) {
                        Log.i(TAG, "ORIENTATION_LANDSCAPE +SDK is: " + currentSDKVersion
                                + "rotate 90");

                        camera.setDisplayOrientation(0);
                    } else {

                        Log.i(TAG, "ORIENTATION_LANDSCAPE +SDK is: " + currentSDKVersion
                                + "rotate 90");

                        parameters.set("orientation", "landscape");
                        parameters.set("rotation", 90);

                    }
                }


                //**************************************************************//


                camera.setParameters(parameters);
                camera.setPreviewDisplay(surfaceHolder);
                camera.startPreview();
                camera.autoFocus(myAutoFocusCallback);
                camera.setOneShotPreviewCallback(cameraPreviewCallback);
                previewing = true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder arg0) {
        Log.v(TAG, "surfaceDestroyed get called");
        camera.stopPreview();
        camera.release();
        camera = null;
        previewing = false;

    }


    public void setCameraDisplayOrientation() 
    {        
        Log.v(TAG, "setCameraDisplayOrientation get called");

         if (camera == null)
         {
             Log.d(TAG,"setCameraDisplayOrientation - camera null");
             return;             
         }

         Camera.CameraInfo info = new Camera.CameraInfo();
         Camera.getCameraInfo(1, info);

         WindowManager winManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
         int rotation = winManager.getDefaultDisplay().getRotation();

         int degrees = 0;

         switch (rotation) 
         {
             case Surface.ROTATION_0: degrees = 0; break;
             case Surface.ROTATION_90: degrees = 90; break;
             case Surface.ROTATION_180: degrees = 180; break;
             case Surface.ROTATION_270: degrees = 270; break;
         }

         int result;
         if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) 
         {
             result = (info.orientation + degrees) % 360;
             result = (360 - result) % 360;  // compensate the mirror
         } else {  // back-facing
             result = (info.orientation - degrees + 360) % 360;
         }
         camera.setDisplayOrientation(result);
    }


    @Override
    public void onClick(View v) {
        Log.v(TAG, "onClick get called");

        if (v == buttonTakePicture) {
            camera.takePicture(myShutterCallback, myPictureCallback_RAW,
                    myPictureCallback_JPG);
        }

    }

    private Camera.PreviewCallback cameraPreviewCallback = new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            Log.i(TAG, "onPreviewFrame size=" + data.length);
        }
    };

    AutoFocusCallback myAutoFocusCallback = new AutoFocusCallback() {

        @Override
        public void onAutoFocus(boolean arg0, Camera arg1) {
            Log.v(TAG, "onAutoFocus get called");
            buttonTakePicture.setEnabled(true);
        }
    };

    ShutterCallback myShutterCallback = new ShutterCallback() {

        @Override
        public void onShutter() {
            Log.v(TAG, "onShutter get called");
        }
    };

    PictureCallback myPictureCallback_RAW = new PictureCallback() {

        @Override
        public void onPictureTaken(byte[] arg0, Camera arg1) {
            Log.v(TAG, "onPictureTaken-RAW get called");

        }
    };

    public static Bitmap RotateBitmap(Bitmap source, float angle) {
        Matrix matrix = new Matrix();
        matrix.postRotate(angle);
        return Bitmap.createBitmap(source, 0, 0, source.getWidth(),
                source.getHeight(), matrix, true);
    }

    PictureCallback myPictureCallback_JPG = new PictureCallback() {

        @Override
        public void onPictureTaken(byte[] arg0, Camera arg1) {
            Bitmap rawImage = BitmapFactory.decodeByteArray(arg0, 0,
                    arg0.length);

            if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                Log.v(TAG, "#####  ORIENTATION_PORTRAIT   ####");

                rawImage = MainActivity.RotateBitmap(rawImage, 90);

                ByteArrayOutputStream stream = new ByteArrayOutputStream();
                rawImage.compress(Bitmap.CompressFormat.JPEG, 100, stream);
                arg0 = stream.toByteArray();

            } else if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
                Log.v(TAG, "#####   ORIENTATION_LANDSCAPE  #####");

            }

            Intent intent = new Intent(MainActivity.this, ResultActivity.class);
            intent.putExtra("picture", arg0);
            startActivity(intent);

            Log.v(TAG, "onPictureTaken-JPG get called");

        }
    };

    /**
     * Get the size in bitmap.
     * 
     * @param bitmap
     * @return size in bytes
     */
    @TargetApi(12)
    public static int getBitmapSize(Bitmap bitmap) {
        if (MainActivity.hasHoneycombMR1()) {
            return bitmap.getByteCount();
        }
        // Pre HC-MR1
        return bitmap.getRowBytes() * bitmap.getHeight();
    }

    public static boolean hasHoneycombMR1() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1;
    }

}

編集開発者フォーラム にコメントを投稿しましたが、応答がありません。

お願いします!!誰かがこの問題について何か考えを持っています。

どんな提案もありがたいです。

20
swiftBoy

2.2.1を実行している元のGalaxy Tabで同様の問題が発生した場合、次のようにして解決できました。

Camera.Parameters parameters = camera.getParameters();
parameters.set("orientation", "portrait");
parameters.setRotation(90);
camera.setParameters(parameters);

ただし、上記の同一の(ただしコメント化された)コードがある場合、あなたはmayでその正確な組み合わせをすでに試しているようです。ただし、現在コードを使用している方法では、APIレベル(10)であるため、Aceはコメントされたコードがある場所をバイパスします。このブロックの中で具体的に試してください:

if (currentSDKVersion != 7) { }

うまくいくかどうか教えてください。ありがとう!

10
Mike P.

ZXingプロジェクトから大幅に変更されたいくつかのコードを記述してカメラを処理しました: http://code.google.com/p/zxing/

それらを使用してみてください。これを使用しようとしている場合は、この解決策を検討することをお勧めします stackoverflow質問

これはあなたの質問に対する完璧な解決策ではないかもしれませんが、私はこの問題を経験し、Zxingを使用することにしました。

0
droidx

私も何時間も解決策を探していました。本当にクレイジーです。私の解決策は、(私の縦向きアプリで)横長モードでカメラプレビューを使用し、不要なプレビューの部分をマスクすることでした。これを行うには、フルスクリーンプレビューの上下の部分をいくつかのビューでオーバーレイします。そのため、カメラから取得している写真をトリミングする必要があるため、解像度が低下します。私のアプリでは、これは問題ありませんでした。

私は今私のソリューションに完全に満足しています。ユーザーは何の違いも見ません。

0
stoefln