camera inside app force close data null when i try

2019-07-19 17:53发布

问题:

i have an apk app which can take photo and take video with a button.

This is my activity

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;
    }
}

I have first device running the app and I have 2 button, take photo and take video.

When I click take video in this app and it works well but when i click take picture from the button, the app always "force closes".

this is my error 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

EDIT : this is my different activity with single app button

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);
        }
    }
}

this app still error too, i have tried many app. searching in google.the error still same like my logcat error

When i try to run it on other device, this app works perfectly.

How to fix this, So that i can run and take photos in my first device?

BR.

Alex

回答1:

The crash is happening inside the device's Camera application, not your own. Unfortunately, because the Camera application on this device could be a heavily customized variation of what is actually in AOSP, it's not entirely clear what the failure is, but here is a link to the source file in the AOSP 2.3.7 source tree where your exception is occurring. The line numbers don't match up exactly to anything of interest, which is what tells me the application on your particular device has been customized at least some.

Any object in the initializeFirstTime() method, where the exception occurs, where a method is called could be the source of the issue, but none of this is related to the Intent parameters your request passes in, so it is doubtful there is much you can do to make this operate appropriately.

As a result, you may have better luck implementing the capture functionality yourself in your own application. It is likely that the Android APIs on this device are more stable than the system applications it's bundled with. Here is an example of how you can create your own camera preview and capture Activity.



回答2:

I'm curious about your phone. what the different of them

because of your onCaptureImage(View v) does describe about external storage. but onCaptureVideo(View v) doesn't

  1. the phone that didn't work. is it support external sd card? if it not, all your code is about ext.sd

  2. Is it your phone that didn't work it remove sd card occasionally? try connect it as camera or mtp



回答3:

Friend Do one thing.

Make Simple app which have only one button. onClick event photo should be capture no add other task.

Is it working Properly ?



回答4:

try to catch the exception and post the message here:

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


回答5:

Thanks @Devunwired, thanks @chintan and thanks all for helping me. i use camera api and it works.

this is my activity

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;
    }
}

i create home.xml to show button image like my question

<?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 this is a camera preview

<?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>

and create control.xml take picture button inside camera preview.

<?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> 

but i have 2 problem in this app.

  1. the camera resolution not full size . -+20kb
  2. when take camera preview is rotate 90 degrees