Android.hardware.Camera $EventHandler.handleMessage

Я пишу программу, в которой я фотографирую, а затем хочу сохранить изображение на SD-карте и, наконец, попытаться изменить размер существующего изображения (а затем поверх того же самого со старым).

Мой код отлично работает практически на всех устройствах, но сталкивается с этой проблемой только на устройствах Samsung.

Когда я снимаю изображение, я не могу сохранить изображение в SDCard

Logcat:

12-05 18:23:15.407: E/AndroidRuntime(2378): FATAL EXCEPTION: main
12-05 18:23:15.407: E/AndroidRuntime(2378): java.lang.NullPointerException
12-05 18:23:15.407: E/AndroidRuntime(2378):     at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:461)
12-05 18:23:15.407: E/AndroidRuntime(2378):     at com.example.kdh.TakePhotoActivity$1.onPictureTaken(TakePhotoActivity.java:325)
12-05 18:23:15.407: E/AndroidRuntime(2378):     at android.hardware.Camera$EventHandler.handleMessage(Camera.java:789)
12-05 18:23:15.407: E/AndroidRuntime(2378):     at android.os.Handler.dispatchMessage(Handler.java:99)
12-05 18:23:15.407: E/AndroidRuntime(2378):     at android.os.Looper.loop(Looper.java:137)
12-05 18:23:15.407: E/AndroidRuntime(2378):     at android.app.ActivityThread.main(ActivityThread.java:4921)
12-05 18:23:15.407: E/AndroidRuntime(2378):     at java.lang.reflect.Method.invokeNative(Native Method)
12-05 18:23:15.407: E/AndroidRuntime(2378):     at java.lang.reflect.Method.invoke(Method.java:511)
12-05 18:23:15.407: E/AndroidRuntime(2378):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1036)
12-05 18:23:15.407: E/AndroidRuntime(2378):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:803)
12-05 18:23:15.407: E/AndroidRuntime(2378):     at dalvik.system.NativeStart.main(Native Method)

Код:

private void createCamera() {
                // Create an instance of Camera
                mCamera = getCameraInstance();

                // Setting the right parameters in the camera
                Camera.Parameters params = mCamera.getParameters();

                List<Size> allSizes = params.getSupportedPictureSizes();
                Camera.Size size = allSizes.get(0); // get top size
                for (int i = 0; i < allSizes.size(); i++) {
                     if (allSizes.get(i).width > size.width)
                       size = allSizes.get(i);
                 }
                //set max Picture Size
                params.setPictureSize(size.width, size.height);
                params.setPictureFormat(PixelFormat.JPEG);
                params.setJpegQuality(85);
                mCamera.setParameters(params);

                // Create our Preview view and set it as the content of our activity.
                mPreview = new CameraPreview(TakePhotoActivity.this, mCamera);
                FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);

                // Calculating the width of the preview so it is proportional.
                float widthFloat = (float) (deviceHeight) * 4 / 3;
                int width = Math.round(widthFloat);

                // Resizing the LinearLayout so we can make a proportional preview. This
                // approach is not 100% perfect because on devices with a really small
                // screen the the image will still be distorted - there is place for
                // improvment.
                RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(width, deviceHeight);
                preview.setLayoutParams(layoutParams);

                // Adding the camera preview after the FrameLayout and before the button
                // as a separated element.
                preview.addView(mPreview, 0);
            }

            @Override
            protected void onResume() {
                super.onResume();

                // Test if there is a camera on the device and if the SD card is
                // mounted.
                if (!checkCameraHardware(this)) {
                    finish();
                } else if (!checkSDCard()) {                    
                    finish();
                }

                // Creating the camera
                createCamera();

                // Register this class as a listener for the accelerometer sensor
                sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
            }

            @Override
            protected void onPause() {
                super.onPause();
                // release the camera immediately on pause event
                releaseCamera();

                // removing the inserted view - so when we come back to the app we
                // won't have the views on top of each other.

                preview.removeViewAt(0);
            }

            private void releaseCamera() {
                if (mCamera != null) {
                    mCamera.stopPreview();
                    mCamera.setPreviewCallback(null);
                    mCamera.release(); // release the camera for other applications
                    mCamera = null;
                }
            }

            /** Check if this device has a camera */
            private boolean checkCameraHardware(Context context) {
                if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
                    // this device has a camera
                    return true;
                } else {
                    // no camera on this device
                    return false;
                }
            }

            private boolean checkSDCard() {
                boolean state = false;

                String sd = Environment.getExternalStorageState();
                if (Environment.MEDIA_MOUNTED.equals(sd)) {
                    state = true;
                }

                return state;
            }

            /**
             * A safe way to get an instance of the Camera object.
             */
            public static Camera getCameraInstance() {
                Camera c = null;
                try {
                    // attempt to get a Camera instance
                    c = Camera.open();
                } catch (Exception e) {
                    // Camera is not available (in use or does not exist)
                }

                // returns null if camera is unavailable
                return c;
            }

            private PictureCallback mPicture = new PictureCallback() {

                public void onPictureTaken(byte[] data, Camera camera) {

                    // Replacing the button after a photho was taken.
                    linearLayout1.setVisibility(View.GONE);
                    linearLayout2.setVisibility(View.VISIBLE);

                    File directory = new File(Environment.getExternalStoragePublicDirectory
                            (Environment.DIRECTORY_PICTURES) 
                                +"/Data/" + stringFolderName);                  

                    fileName = String.format("%d.jpg", System.currentTimeMillis());
                    File outFile = new File(directory, fileName);

                    try {
                        FileOutputStream purge = new FileOutputStream(outFile);
                        purge.write(data);
                        purge.close();                      
                    } catch (FileNotFoundException e) {
                        Log.d("DG_DEBUG", "File not found: " + e.getMessage());
                    } catch (IOException e) {
                        Log.d("DG_DEBUG", "Error accessing file: " + e.getMessage());
                    }

                    String cPath = Environment.getExternalStoragePublicDirectory
                            (Environment.DIRECTORY_PICTURES) 
                            +"/Data/" + stringFolderName + "/"+ fileName;

                    Bitmap bMap= BitmapFactory.decodeFile(cPath);
                    Bitmap out = Bitmap.createScaledBitmap(bMap, 1024, 768, true);
                    //Bitmap adjustedBitmap = Bitmap.createBitmap(out, 0, 0, 1024, 768, matrix, true);
                    Log.d("image-name:-", fileName);
                    File resizedFile = new File(directory, fileName);

                    OutputStream fOut=null;
                    try {
                        fOut = new BufferedOutputStream(new FileOutputStream(resizedFile));
                        out.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
                        fOut.flush();
                        fOut.close();
                        bMap.recycle();
                        out.recycle();

                    } catch (Exception e) { // TODO

                    }


                    // Adding Exif data for the orientation. For some strange reason the
                    // ExifInterface class takes a string instead of a file.
                    try {
                        exif = new ExifInterface(directory + "/"+fileName);
                        exif.setAttribute(ExifInterface.TAG_ORIENTATION, "" + orientation);
                        exif.saveAttributes();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }

                }
            };

Ответ 1

Попробуйте этот код и попытайтесь сохранить изображение или видео в фоновом потоке вместо UI

private PictureCallback mPicture = new PictureCallback() {
            @Override
            public void onPictureTaken(final byte[] data, Camera camera) {
                final File pictureFile = getOutputMediaFile();
                if (pictureFile == null) {
                    return;
                }

                Thread thread = new Thread() {
                    @Override
                    public void run() {
                        try {
                            FileOutputStream fos = new FileOutputStream(pictureFile);
                            fos.write(data);
                            fos.close();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                };

                thread.start();


            }
        };


        private File getOutputMediaFile() {
            File mediaStorageDir = new File(
                    Environment.getExternalStorageDirectory(),
                    "/Images");
            if (!mediaStorageDir.exists()) {
                if (!mediaStorageDir.mkdirs()) {
                    Log.d("Camera", "failed to create directory");
                    return null;
                }
            }
            // Create a media file name
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
                    .format(new Date());
            File mediaFile;
            String image_path = mediaStorageDir.getPath() + File.separator
                    + "IMG_" + timeStamp + ".jpg";
            mediaFile = new File(image_path);
            return mediaFile;
        }

Ответ 2

Если доза данных не создана. Вы не можете использовать растровое изображение.

Это означает, что нужно немного времени, чтобы создать image.so bitmapcreate вернуть null.

Я думаю, что PictureCallback работает как поток

Чтобы решить эту проблему. изменить этот код

   Bitmap bMap= BitmapFactory.decodeFile(cPath);
   Bitmap out = Bitmap.createScaledBitmap(bMap, 1024, 768, true);

To

    Bitmap bMap = BitmapFactory.decodeByteArray(data, 0,.length);
    Bitmap out = Bitmap.createScaledBitmap(bMap, 1024, 768, true);

Этот код преобразует байт [] в растровое изображение (см. данные в picturecallback);

Ссылка на API-интерфейс камеры: Руководство по API-интерфейсу камеры