当我尝试在不同的设备时,相机内部应用程序强制关闭数据null

时间:2012-11-22 03:56:21

标签: android android-intent nullpointerexception android-camera android-sdcard

我有一个apk应用程序可以拍照并用按钮拍摄视频。

这是我的活动

package com.example.testcamera;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.view.View;

public class AndroidCameraTestsActivity extends Activity 
{
    private static final String TAG = AndroidCameraTestsActivity.class.getSimpleName(); 

    private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
    private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;
    public static final int MEDIA_TYPE_IMAGE = 1;
    public static final int MEDIA_TYPE_VIDEO = 2;

    private Uri fileUri;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    /** 
     * https://developer.android.com/guide/topics/media/camera.html 
     * **/
    public void onCaptureImage(View v) 
    {
        // give the image a name so we can store it in the phone's default location
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());

        ContentValues values = new ContentValues();
        values.put(MediaStore.Images.Media.TITLE, "IMG_" + timeStamp + ".jpg");

        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

        //fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image (this doesn't work at all for images)
        fileUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); // store content values
        intent.putExtra( MediaStore.EXTRA_OUTPUT,  fileUri);

        // start the image capture Intent
        startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
    }

    /** 
     * https://developer.android.com/guide/topics/media/camera.html 
     * **/
    public void onCaptureVideo(View v) 
    {
         //create new Intent
        Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);

        //fileUri = getOutputMediaFileUri(MEDIA_TYPE_VIDEO);  // create a file to save the video in specific folder (this works for video only)
        //intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);  // set the image file name

        intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // set the video image quality to high

        // start the Video Capture Intent
        startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {

                // Originally I was going to iterate through the list of images and grab last added to the MediaStore.
                // But this is not necessary if we store the Uri in the image
                /*
                String[] projection = {MediaStore.Images.ImageColumns._ID};
                String sort = MediaStore.Images.ImageColumns._ID + " DESC";

                Cursor cursor = this.managedQuery(MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, projection, null, null, sort);

                try{
                    cursor.moveToFirst();
                    Long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.ImageColumns._ID));
                    fileUri = Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, String.valueOf(id));
                } finally{
                    cursor.close();
                }
                */

                if(fileUri != null) {
                    Log.d(TAG, "Image saved to:\n" + fileUri);
                    Log.d(TAG, "Image path:\n" + fileUri.getPath());
                    Log.d(TAG, "Image name:\n" + getName(fileUri)); // use uri.getLastPathSegment() if store in folder
                }

            } else if (resultCode == RESULT_CANCELED) {
                // User cancelled the image capture
            } else {
                // Image capture failed, advise user
            }
        }

        if (requestCode == CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {

                // Video captured and saved to fileUri specified in the Intent
                fileUri = (Uri) data.getData();

                if(fileUri != null) {
                    Log.d(TAG, "Video saved to:\n" + fileUri);
                    Log.d(TAG, "Video path:\n" + fileUri.getPath());
                    Log.d(TAG, "Video name:\n" + getName(fileUri)); // use uri.getLastPathSegment() if store in folder
                }

            } else if (resultCode == RESULT_CANCELED) {
                // User cancelled the video capture
            } else {
                // Video capture failed, advise user
            }
        }
    }

    /** Create a file Uri for saving an image or video to specific folder
     * https://developer.android.com/guide/topics/media/camera.html#saving-media
     * */
    private static Uri getOutputMediaFileUri(int type)
    {
          return Uri.fromFile(getOutputMediaFile(type));
    }

    /** Create a File for saving an image or video */
    private static File getOutputMediaFile(int type)
    {
        // To be safe, you should check that the SDCard is mounted

        if(Environment.getExternalStorageState() != null) {
            // this works for Android 2.2 and above
            File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "AndroidCameraTestsFolder");

            // This location works best if you want the created images to be shared
            // between applications and persist after your app has been uninstalled.

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

            // Create a media file name
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").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;
        }

        return null;
    }

    // grab the name of the media from the Uri
    protected String getName(Uri uri) 
    {
        String filename = null;

        try {
            String[] projection = { MediaStore.Images.Media.DISPLAY_NAME };
            Cursor cursor = managedQuery(uri, projection, null, null, null);

            if(cursor != null && cursor.moveToFirst()){
                int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME);
                filename = cursor.getString(column_index);
            } else {
                filename = null;
            }
        } catch (Exception e) {
            Log.e(TAG, "Error getting file name: " + e.getMessage());
        }

        return filename;
    }
}

我有第一台运行该应用的设备,我有2个按钮,take phototake video

当我在此应用中点击take video并且效果很好但是当我从按钮点击take picture时,该应用始终“强行关闭”。

这是我的错误logcat

11-19 14:43:27.085: ERROR/AndroidRuntime(6903): FATAL EXCEPTION: main
11-19 14:43:27.085: ERROR/AndroidRuntime(6903): java.lang.NullPointerException
11-19 14:43:27.085: ERROR/AndroidRuntime(6903): at com.android.camera.Camera.initializeFirstTime(Came ra.java:328)
11-19 14:43:27.085: ERROR/AndroidRuntime(6903): at com.android.camera.Camera.access$1100(Camera.java: 95)
11-19 14:43:27.085: ERROR/AndroidRuntime(6903): at com.android.camera.Camera$MainHandler.handleMessag e(Camera.java:282)
11-19 14:43:27.085: ERROR/AndroidRuntime(6903): at android.os.Handler.dispatchMessage(Handler.java:99 )
11-19 14:43:27.085: ERROR/AndroidRuntime(6903): at android.os.Looper.loop(Looper.java:130)
11-19 14:43:27.085: ERROR/AndroidRuntime(6903): at android.app.ActivityThread.main(ActivityThread.jav a:3683)
11-19 14:43:27.085: ERROR/AndroidRuntime(6903): at java.lang.reflect.Method.invokeNative(Native Method)
11-19 14:43:27.085: ERROR/AndroidRuntime(6903): at java.lang.reflect.Method.invoke(Method.java:507)
11-19 14:43:27.085: ERROR/AndroidRuntime(6903): at com.android.internal.os.ZygoteInit$MethodAndArgsCa ller.run(ZygoteInit.java:839)
11-19 14:43:27.085: ERROR/AndroidRuntime(6903): at com.android.internal.os.ZygoteInit.main(ZygoteInit .java:597)
11-19 14:43:27.085: ERROR/AndroidRuntime(6903): at dalvik.system.NativeStart.main(Native Method)
11-19 14:43:27.093: WARN/ActivityManager(1308): Force finishing activity com.android.camera/.Camera
11-19 14:43:27.109: WARN/ActivityManager(1308): Force finishing activity makemachine.android.examples/.PhotoCaptureExample

logcat capture

编辑:这是我使用单个应用按钮的不同活动

package com.example.maincamera;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

public class OpenCameraDemo extends Activity {

    private static final int CAMERA_PIC_REQUEST = 2500;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Button b = (Button)findViewById(R.id.Button01);
        b.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                 Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                 startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);
            }
        });
    }

    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == CAMERA_PIC_REQUEST) {
              Bitmap image = (Bitmap) data.getExtras().get("data");
              ImageView imageview = (ImageView) findViewById(R.id.ImageView01);
              imageview.setImageBitmap(image);
        }
    }
}

这个应用程序仍然出错,我尝试了很多应用程序。在google中搜索。错误仍然与我的logcat错误相同

当我尝试在其他设备上运行时,此应用程序运行正常。

如何解决此问题,以便我可以在第一台设备上运行并拍照?

BR。

亚历

5 个答案:

答案 0 :(得分:3)

崩溃发生在设备的Camera应用程序内部,而不是您自己的。不幸的是,因为此设备上的Camera应用程序可能是AOSP中实际内容的大量自定义变体,所以失败是什么并不完全清楚,但AOSP 2.3.7源代码树中的here is a link to the source file发生了异常。行号与任何感兴趣的内容都不完全匹配,这就是告诉我您的特定设备上的应用程序至少已经定制了一些。

发生异常的initializeFirstTime()方法中的任何对象,其中调用方法可能是问题的根源,但这些对象都与请求传递的Intent参数无关因此,你可以采取哪些措施使其正常运作,这是值得怀疑的。

因此,您可能希望自己在自己的应用程序中实现捕获功能。该设备上的Android API可能比它捆绑的系统应用程序更稳定。 Here is an example如何创建自己的相机预览并捕捉活动。

答案 1 :(得分:0)

我对你的手机很好奇。它们的不同之处

因为 onCaptureImage(View v)确实描述了外部存储。 但 onCaptureVideo(查看v)

  
      
  1. 手机无效。它支持外部SD卡吗?如果不是,所有代码都是关于ext.sd

  2.   
  3. 您的手机是否有效,偶尔会移除SD卡?尝试将其连接为相机或mtp

  4.   

答案 2 :(得分:0)

朋友做一件事。

制作只有一个按钮的简单应用。 onClick事件照片应该是捕获而不添加其他任务。

它是否正常工作?

答案 3 :(得分:0)

尝试捕获异常并在此处发布消息:

try{
Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
startActivityForResult(cameraIntent, CAMERA_PIC_REQUEST);
}
catch(ActivityNotFoundException e){
e.printStackTrace();
}

答案 4 :(得分:0)

谢谢@Devunwired,谢谢@chintan并感谢大家的帮助。我使用相机api,它的工作原理。

这是我的活动

package com.exercise.AndroidCamera;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;

import android.app.Activity;
import android.content.ContentValues;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore.Images.Media;
import android.util.Log;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;

public class AndroidCamera extends Activity implements SurfaceHolder.Callback{

    Camera camera;
    SurfaceView surfaceView;
    SurfaceHolder surfaceHolder;
    boolean previewing = false;
    LayoutInflater controlInflater = null;

    final int RESULT_SAVEIMAGE = 0;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.home);

    }
        public void onCaptureImage(View v) 
        {

        setContentView(R.layout.main);

        Toast.makeText(AndroidCamera.this, 
                "Image dimulai : ", 
                Toast.LENGTH_LONG).show();
        getWindow().setFormat(PixelFormat.UNKNOWN);

        surfaceView = (SurfaceView)findViewById(R.id.camerapreview);
        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);

        Button buttonTakePicture = (Button)findViewById(R.id.takepicture);
        buttonTakePicture.setOnClickListener(new Button.OnClickListener(){

            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                camera.takePicture(myShutterCallback, 
                        myPictureCallback_RAW, myPictureCallback_JPG);

            }});
    }


    ShutterCallback myShutterCallback = new ShutterCallback(){

        @Override
        public void onShutter() {
            // TODO Auto-generated method stub

        }};

    PictureCallback myPictureCallback_RAW = new PictureCallback(){

        @Override
        public void onPictureTaken(byte[] arg0, Camera arg1) {
            // TODO Auto-generated method stub

        }};

    PictureCallback myPictureCallback_JPG = new PictureCallback(){

        @Override
        public void onPictureTaken(byte[] arg0, Camera arg1) {
            // TODO Auto-generated method stub
            /*Bitmap bitmapPicture 
                = BitmapFactory.decodeByteArray(arg0, 0, arg0.length);  */

            Uri uriTarget = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, new ContentValues());

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

                Toast.makeText(AndroidCamera.this, 
                        "Image Tersimpan: " + uriTarget.toString(), 
                        Toast.LENGTH_LONG).show();

            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }


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

        }};

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        // TODO Auto-generated method stub
        if(previewing){
            camera.stopPreview();
            previewing = false;
        }

        if (camera != null){
            try {

                camera.setPreviewDisplay(surfaceHolder);
                camera.startPreview();
                previewing = true;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }



    @Override
    public void surfaceCreated(SurfaceHolder holder) {

        camera = Camera.open();
        //m_camera = Camera.open();
        /*Camera.Parameters p = camera.getParameters();

        //camera.setDisplayOrientation(90);
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
        {   
            p.set("orientation", "portrait");
            p.set("rotation",90);
        }
        if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)
        {                               
            p.set("orientation", "landscape");          
            p.set("rotation", 90);
        }*/


    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        // TODO Auto-generated method stub
        camera.stopPreview();
        camera.release();
        camera = null;
        previewing = false;
    }
}

我创建home.xml以显示像我的问题

的按钮图像
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button android:text="Capture Image" android:onClick="onCaptureImage" 
        android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
</LinearLayout>

main.xml这是一个相机预览

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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/camerapreview"  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    />
</LinearLayout>

并在相机预览中创建control.xml拍照按钮。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="bottom"
    >
<Button
    android:id="@+id/takepicture"  
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:text=" * Ambil Foto " 
    android:layout_gravity="right"
    android:layout_margin="10px"
    />


</LinearLayout> 

但我在这个应用程序中有2个问题。

  1. 相机分辨率不是全尺寸。 - + 20KB
  2. 拍摄相机预览时旋转90度