1

我在理解崩溃的应用程序的 logcat 时遇到问题。(我是一个初学者,我的应用程序只是拍了一张照片,然后将其保存在一个特定的文件夹中,但是当我点击应该允许我拍照的按钮时,它崩溃了,我收到了著名的消息( MY_APP_Name 没有响应)

这是 MySurfaceView.java 中的代码

package android.cam_bouton_save;



private SurfaceHolder holder;
private Camera camera;

public MySurfaceView(Context context, Camera camera)
{
    super(context);
    this.camera = camera;
    holder = getHolder();
    holder.addCallback(this);
    holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

public void surfaceChanged(SurfaceHolder holder, 
        int format, int weight, int height)
{
    if (holder.getSurface() == null)
        return;
    try
    {
        camera.stopPreview();
        camera.setPreviewDisplay(holder);
        camera.startPreview();
    }
    catch (Exception e){}
}

public void surfaceCreated(SurfaceHolder holder)
{
    try
    {
        camera.setPreviewDisplay(holder);
        camera.startPreview();
    }
    catch (IOException e){}
}

public void surfaceDestroyed(SurfaceHolder holder){}

}

这是日志猫:

05-14 17:15:04.216: E/AndroidRuntime(1123): FATAL EXCEPTION: main
05-14 17:15:04.216: E/AndroidRuntime(1123): java.lang.NullPointerException
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.cam_bouton_save.MySurfaceView.surfaceCreated(MySurfaceView.java:42)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.view.SurfaceView.updateWindow(SurfaceView.java:532)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.view.SurfaceView.dispatchDraw(SurfaceView.java:339)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.view.ViewGroup.drawChild(ViewGroup.java:1638)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.view.ViewGroup.drawChild(ViewGroup.java:1638)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.view.ViewGroup.drawChild(ViewGroup.java:1638)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.view.View.draw(View.java:6743)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.widget.FrameLayout.draw(FrameLayout.java:352)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.view.ViewGroup.drawChild(ViewGroup.java:1640)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.view.ViewGroup.drawChild(ViewGroup.java:1638)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1367)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.view.View.draw(View.java:6743)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.widget.FrameLayout.draw(FrameLayout.java:352)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1842)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.view.ViewRoot.draw(ViewRoot.java:1407)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.view.ViewRoot.performTraversals(ViewRoot.java:1163)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1727)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.os.Handler.dispatchMessage(Handler.java:99)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.os.Looper.loop(Looper.java:123)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at android.app.ActivityThread.main(ActivityThread.java:4627)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at java.lang.reflect.Method.invokeNative(Native Method)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at java.lang.reflect.Method.invoke(Method.java:521)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
05-14 17:15:04.216: E/AndroidRuntime(1123):     at dalvik.system.NativeStart.main(Native Method)

你能帮我吗?

    package android.cam_bouton_save;
      public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);

        Button bouton = (Button) findViewById(R.id.btn_photo);
    //  camera = Camera.open();
        mySurfaceView = new MySurfaceView(this, camera);
        final FrameLayout myPreview = (FrameLayout) findViewById(R.id.preview);
        myPreview.addView(mySurfaceView);

        bouton.setOnClickListener(new View.OnClickListener()  {
      //  @Override
         public void onClick(View actuelView)   {
            /* //camera.open();
            // camera.getParameters();*/

            camera = Camera.open();

        /*   camera = Camera.open();
             Parameters parameters = camera.getParameters();
             parameters.setPictureFormat(PixelFormat.JPEG);
             camera.setParameters(parameters);
            // camera.setPreviewDisplay(surfaceHolder);
             camera.startPreview();*/
            camera.takePicture(shutterCallback, rawCallback, myPictureCallback_JPG);
         } 
      });

    }


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

        PictureCallback rawCallback = new PictureCallback() {
            public void onPictureTaken(byte[] data, Camera camera) {
      } 
    };

        PictureCallback myPictureCallback_JPG = new PictureCallback(){
            public void onPictureTaken(byte[] arg0, Camera arg1) {

                int imageNum = 0;
                Intent imageIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);

                //Gets the Android external storage directory
                File imagesFolder = new File(Environment.getExternalStorageDirectory(), "Punch");
                imagesFolder.mkdirs(); // <----
                String fileName = "image_" + String.valueOf(imageNum) + ".jpg";
                File output = new File(imagesFolder, fileName);
                while (output.exists()){
                    imageNum++;
                    fileName = "image_" + String.valueOf(imageNum) + ".jpg";
                    output = new File(imagesFolder, fileName);
                }
                Uri uriSavedImage = Uri.fromFile(output);
                imageIntent.putExtra(MediaStore.EXTRA_OUTPUT, uriSavedImage);


                OutputStream imageFileOS;
                try {
                    imageFileOS = getContentResolver().openOutputStream(uriSavedImage);
                    imageFileOS.write(arg0);
                    imageFileOS.flush();
                    imageFileOS.close();

                    Toast.makeText(Cam_bouton_save_picActivity.this, 
                            "Image saved: ", 
                            Toast.LENGTH_LONG).show();
                    camera.release() ;
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

         //       camera.startPreview();
            }};
}           
4

1 回答 1

1

Your LogCat says you are getting a NullPointerException in line 36 of your activity class, inside the onClick method: m Cam_bouton_save_picActivity.java:36.

Just a guess, but perhaps your Camera instance is null. This occurs most often because of a missing permission in the androidManifest.xml, so please make sure you've included it:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Also note, that if you want to save the photos taken to the SD card, you'll need an other permission as well:

<uses-permission android:name="android.permission.CAMERA" />

Edit 1: Thans for the code!

Now it is obvious, that you need to initialize your camera member! Without initializing it that's the weak point that ends up in a NullPointerException.

In your onCreate method you should have this line:

camera = Camera.open();

If performed correctly, you won't get the NPE anymore.

Edit 2: For a camera preview: -removed-

Edit 3: Please -in future- ask new questions if you are facing a new problem and need help, instead of modifying your existing question. This answer already has nothing to do with your original question.

Keep in mind, that StackOverflow is about answers to specific problems, not about solving all the problems of particular people.

Here is a small and very focused sample application that shows how you can take consecutive camera shots and save them on the sd card:

public class AndroidCamera extends Activity implements 
    SurfaceHolder.Callback, View.OnClickListener
{
    private static final String TAG = "CS";
    private Camera camera;
    private SurfaceView surface;
    private SurfaceHolder holder;
    private boolean isPreview = false;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        surface = (SurfaceView) findViewById(R.id.preview);
        holder = surface.getHolder();
        holder.addCallback(this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        final Button shotButton = (Button) findViewById(R.id.btn_shot);
        shotButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View v)
    {
        camera.takePicture(shutterCallback, rawCallback, jpgCallback);
    }

    ShutterCallback shutterCallback = new ShutterCallback()
    {
        @Override
        public void onShutter()
        {}
    };

    PictureCallback rawCallback = new PictureCallback()
    {
        @Override
        public void onPictureTaken(byte[] arg0, Camera arg1)
        {}
    };

    PictureCallback jpgCallback = new PictureCallback()
    {
        @Override
        public void onPictureTaken(byte[] arg0, Camera arg1)
        {
            if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
            {
                final String imageDir =
                        Environment.getExternalStorageDirectory() + 
                        File.separator + "Punch" + File.separator;
                int counter = 0;
                String imageName = "image_" + counter + ".jpg";
                File outputFile = new File(imageDir, imageName);
                if (!outputFile.getParentFile().exists())
                    outputFile.getParentFile().mkdirs();
                while (outputFile.exists())
                {
                    counter++;
                    imageName = "image_" + counter + ".jpg";
                    outputFile = new File(imageDir, imageName);
                }
                Uri uriSavedImage = Uri.fromFile(outputFile);
                OutputStream imageFileOS;
                try
                {
                    imageFileOS = getContentResolver().openOutputStream(uriSavedImage);
                    imageFileOS.write(arg0);
                    imageFileOS.flush();
                    imageFileOS.close();

                    Log.w(TAG, "Image saved: " + uriSavedImage.toString());
                    camera.startPreview();
                }
                catch (FileNotFoundException e)
                {
                    Log.e(TAG, "onPictureTaken", e);
                }
                catch (IOException e)
                {
                    Log.e(TAG, "onPictureTaken", e);
                }
            }
        }
    };

    @Override
    public void surfaceChanged(SurfaceHolder sHolder, int format, int width, int height)
    {
        if (isPreview)
        {
            try
            {
                camera.stopPreview();
                isPreview = false;
            }
            catch (Exception e)
            {
                Log.e(TAG, "surfaceChanged", e);
            }
        }

        if (camera != null)
        {
            try
            {
                camera.setPreviewDisplay(holder);
                camera.startPreview();
                isPreview = true;
            }
            catch (IOException e)
            {
                Log.e(TAG, "surfaceChanged", e);
                releaseCamera();
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder)
    {
        try
        {
            camera = Camera.open();
        }
        catch (Exception e)
        {
            Log.e(TAG, "surfaceCreated Camera.open()", e);
            releaseCamera();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder)
    {
        releaseCamera();
    }

    private void releaseCamera()
    {
        try
        {
            camera.stopPreview();
            camera.release();
            camera = null;
            isPreview = false;
        }
        catch (Exception e)
        {
            Log.e(TAG, "releaseCamera", e);
        }
    }
}

For this you only need a very simple layout (main.xml):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <SurfaceView android:id="@+id/preview"
        android:layout_width="fill_parent" android:layout_height="wrap_content"/>
    <Button android:id="@+id/btn_shot" android:text="Shot!"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true" />
</RelativeLayout>

I hope it's clear enough :)

于 2012-05-14T14:44:56.177 回答