0

这是我的第一个 Android 应用程序,我使用相机预览和 FileOutputStream 将图片保存在我的 SD 卡上。在应用程序中,我想通过按一次按钮来制作单张图片或连续图片行。当我调用方法“手动跟踪”时,预览会冻结,我只能返回上一个屏幕。当我调用方法“串行跟踪”时,应用程序以 NPE 结尾。(碰巧我在崩溃一次后也无法在其他应用程序中使用我的相机;必须重新启动我的设备)

我在哪里失败?

package com.example.autoimageapp;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.annotation.SuppressLint;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.os.Environment;
import android.util.Log;

public class PictureTaker {

private static final int MEDIA_TYPE_IMAGE = 1;
private static final int MEDIA_TYPE_VIDEO = 2;
private static final String TAG = "PictureTaker";

private int milliseconds;
private CameraPreview preview;
public Thread t;

// Called when shutter is opened
private ShutterCallback shutterCallback = new ShutterCallback() {
    public void onShutter() {
        Log.d(TAG, "onShutter'd");
    }
};

// Handles data for raw picture
private PictureCallback rawCallback = new PictureCallback() {
    public void onPictureTaken(byte[] data, Camera camera) {
        Log.d(TAG, "onPictureTaken - raw");
    }
};

// Handles picture data after picture was taken.
// Saves picture.
private PictureCallback jpegCallback = new PictureCallback() {

    @Override
    public void onPictureTaken(byte[] data, Camera camera) {
        Log.d(TAG, "onPictureTaken - jpeg");
        File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
        if (pictureFile == null) {
            Log.d(TAG,
                    "Error creating media file, check storage permissions.");
            return;
        }

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

public PictureTaker(CameraPreview preview, int milliseconds) {
    this.milliseconds = milliseconds;
    this.preview = preview;
}

/** Create a File for saving an image or video */
@SuppressLint({ "NewApi", "SimpleDateFormat" })
private static File getOutputMediaFile(int type) {

    if (Environment.getExternalStorageState().equals(
            Environment.MEDIA_UNMOUNTED)) {
        Log.d(TAG, "SD Card is not mounted");
        return null;
    }

    // Create folder with name "AutoImageApp" in "Pictures"
    File mediaStorageDir = new File(
            Environment
                    .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
            "AutoImageApp");

    // Create the storage directory if it does not exist
    if (!mediaStorageDir.exists()) {
        if (!mediaStorageDir.mkdirs()) {
            Log.d("AutoImageApp", "failed to create directory");
            return null;
        }
    }

    // Create a media file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmssSSS")
            .format(new Date());
    File mediaFile;
    if (type == MEDIA_TYPE_IMAGE) {
        mediaFile = new File(mediaStorageDir.getPath() + File.separator
                + "IMG_" + timeStamp + ".jpg");
    } else if (type == MEDIA_TYPE_VIDEO) {
        mediaFile = new File(mediaStorageDir.getPath() + File.separator
                + "VID_" + timeStamp + ".mp4");
    } else {
        return null;
    }

    return mediaFile;
}

/**
 * Calls
 * {@link Camera#takePicture(ShutterCallback, PictureCallback, PictureCallback)}
 * <br>
 * with a frequency of milliseconds, which are given from the user in a
 * Spinner.<br>
 * Runs a new thread so the preview can be shown and pictures can be taken
 * at the same time.
 */
public void takeSerialPics() {
    t = new Thread() {
        @Override
        public void run() {
            while (!isInterrupted()) {
                Log.d(TAG, "vor takePicture Methode");
                try {
                    preview.camera.takePicture(shutterCallback,
                            rawCallback, jpegCallback);
                } catch (RuntimeException e) {
                    Log.d(TAG, "Smartphone zu lahm!");
                    return;
                }
                Log.d(TAG, "nach takePicture Methode");
                try {
                    Thread.sleep(milliseconds);
                } catch (InterruptedException e) {
                    interrupt();
                }
            }
        }
    };
    t.start();
}

/**
 * Calls
 * {@link Camera#takePicture(ShutterCallback, PictureCallback, PictureCallback)}
 * .
 */
public void takeSinglePics() {
    preview.camera.takePicture(shutterCallback, rawCallback, jpegCallback);
}

}

我设置了权限:

<uses-feature android:name="android.hardware.camera" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

我认为 NPE 发生在第 57 行 -> fos.write(data)

这是堆栈跟踪:

02-20 14:53:26.689: D/PictureTaker(995): vor takePicture Methode
02-20 14:53:26.729: D/PictureTaker(995): nach takePicture Methode
02-20 14:53:26.769: D/PictureTaker(995): onShutter'd
02-20 14:53:27.229: D/PictureTaker(995): vor takePicture Methode
02-20 14:53:41.109: E/SensorManager(995): unregisterListener:: all sensors,  listener = com.example.autoimageapp.Accelerometer@40569578
02-20 14:53:41.109: E/SensorManager(995): unregisterListener:: all sensors,  listener = com.example.autoimageapp.MagneticField@4056bda8
02-20 14:53:41.109: E/SensorManager(995): unregisterListener:: all sensors,  listener = com.example.autoimageapp.Gyroscope@4056cff0
02-20 14:54:26.789: D/SensorManager(1037): ====>>>>>Num Sensor: 1
02-20 14:54:26.789: D/SensorManager(1037): ====>>>>>Num Sensor: 2
02-20 14:54:26.789: D/SensorManager(1037): ====>>>>>Num Sensor: 3
02-20 14:54:26.789: D/SensorManager(1037): ====>>>>>Num Sensor: 4
02-20 14:54:26.799: D/SensorManager(1037): ====>>>>>Num Sensor: 5
02-20 14:54:26.799: D/SensorManager(1037): ====>>>>>Num Sensor: 6
02-20 14:54:26.799: D/SensorManager(1037): ====>>>>>Num Sensor: 0
02-20 14:54:26.799: E/SensorManager(1037): registerListener :: handle = 0  name= BMA220 delay= 200000 Listener= com.example.autoimageapp.Accelerometer@40568ed0
02-20 14:54:26.799: E/SensorManager(1037): =======>>>Sensor Thread RUNNING <<<========
02-20 14:54:26.799: E/SensorManager(1037): reg :: handle = 0
02-20 14:54:26.799: E/SensorManager(1037): registerListener :: handle = 1  name= MMC314X delay= 200000 Listener= com.example.autoimageapp.MagneticField@4056b700
02-20 14:54:26.799: E/SensorManager(1037): reg :: handle = 1
02-20 14:54:26.799: E/SensorManager(1037): registerListener :: handle = 0  name= BMA220 delay= 200000 Listener= com.example.autoimageapp.Accelerometer@40568ed0
02-20 14:54:26.809: E/SensorManager(1037): reg :: handle = 0
02-20 14:54:26.809: E/SensorManager(1037): registerListener :: handle = 1  name= MMC314X delay= 200000 Listener= com.example.autoimageapp.MagneticField@4056b700
02-20 14:54:26.809: E/SensorManager(1037): reg :: handle = 1
02-20 14:54:26.809: E/SensorManager(1037): registerListener :: handle = 0  name= BMA220 delay= 200000 Listener= com.example.autoimageapp.Accelerometer@40568ed0
02-20 14:54:26.819: E/SensorManager(1037): reg :: handle = 0
02-20 14:54:26.819: E/SensorManager(1037): registerListener :: handle = 1  name= MMC314X delay= 200000 Listener= com.example.autoimageapp.MagneticField@4056b700
02-20 14:54:26.819: E/SensorManager(1037): reg :: handle = 1
02-20 14:54:26.939: D/CameraPreview(1037): cannot open Camera
02-20 14:54:26.939: W/dalvikvm(1037): threadid=1: thread exiting with uncaught exception (group=0x40018578)
02-20 14:54:26.959: E/AndroidRuntime(1037): FATAL EXCEPTION: main
02-20 14:54:26.959: E/AndroidRuntime(1037): java.lang.NullPointerException
02-20 14:54:26.959: E/AndroidRuntime(1037):     at com.example.autoimageapp.CameraPreview.surfaceCreated(CameraPreview.java:48)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.view.SurfaceView.updateWindow(SurfaceView.java:552)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.view.SurfaceView.dispatchDraw(SurfaceView.java:350)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.view.View.draw(View.java:6883)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.widget.FrameLayout.draw(FrameLayout.java:357)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.view.View.draw(View.java:6883)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.widget.FrameLayout.draw(FrameLayout.java:357)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1921)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.view.ViewRoot.draw(ViewRoot.java:1528)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.view.ViewRoot.performTraversals(ViewRoot.java:1264)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1866)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.os.Handler.dispatchMessage(Handler.java:99)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.os.Looper.loop(Looper.java:130)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at android.app.ActivityThread.main(ActivityThread.java:3687)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at java.lang.reflect.Method.invokeNative(Native Method)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at java.lang.reflect.Method.invoke(Method.java:507)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
02-20 14:54:26.959: E/AndroidRuntime(1037):     at dalvik.system.NativeStart.main(Native Method)

这是我的班级“跟踪屏幕”的一部分,其中创建了“预览”:

preview = new CameraPreview(this);
((FrameLayout) findViewById(R.id.preview)).addView(preview);
preview.setKeepScreenOn(true);
4

0 回答 0