Search code examples
androidnullpointerexceptionruntimeexceptionandroid-camera-intentonactivityresult

Null Pointer Exception in onActivityResult after taking photo in Camera app of the mobile in android


This is the code of my UnityBridge which I'm using it to bridge between Unity and Native Android.

The bridge between Unity and android is successfull. When I call the openCamera method from Unity, the camera app opens and I can take photo. After taking photo image is saved to the Demo folder in the internal memory. Till this step there is no problem, but after saving the photo the app force closes. I have got the log from cmd like this: I think the Intent data that is obtained in the onActivityResult is null. Can someone please help me to solve this error. I need to save the image to the Demo folder in storage card, and get the full file path including the file name of the taken photo into a string variable so that I can that full file path back to unity for next process. Is it possible?

Logcat

E/AndroidRuntime( 1873): Caused by: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=100, result=-1, data=null} to activity {com.tony.example/com.tony.example.UnityBridge}: java.lang.NullPointerException E/AndroidRuntime( 1873): at android.app.ActivityThread.deliverResults(ActivityThread.java:3205) E/AndroidRuntime( 1873): at android.app.ActivityThread.handleSendResult(ActivityThread.java:3248) E/AndroidRuntime( 1873): at android.app.ActivityThread.access$1200(ActivityThread.java:140) E/AndroidRuntime( 1873): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1285) E/AndroidRuntime( 1873): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime( 1873): at android.os.Looper.loop(Looper.java:137) E/AndroidRuntime( 1873): at android.app.ActivityThread.main(ActivityThread.java:4921) E/AndroidRuntime( 1873): at java.lang.reflect.Method.invokeNative(NativeMethod) E/AndroidRuntime( 1873): at java.lang.reflect.Method.invoke(Method.java:511) E/AndroidRuntime( 1873): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027) E/AndroidRuntime( 1873): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:794) E/AndroidRuntime( 1873): at dalvik.system.NativeStart.main(Native Method) E/AndroidRuntime( 1873): Caused by: java.lang.NullPointerException E/AndroidRuntime( 1873): at com.tony.example.UnityBridge.onActivityResult(UnityBridge.java:154) E/AndroidRuntime( 1873): at android.app.Activity.dispatchActivityResult(Activity.java:5390) E/AndroidRuntime( 1873): at android.app.ActivityThread.deliverResults(ActivityThread.java:3201) E/AndroidRuntime( 1873): ... 11 more

Code

package com.tony.example;

import java.io.ByteArrayOutputStream;
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.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import android.widget.Toast;

import com.unity3d.player.UnityPlayerActivity;
import com.unity3d.player.UnityPlayer;

public class UnityBridge extends UnityPlayerActivity
{    
static private int _myInt;
private static int RESULT_LOAD_IMAGE = 1;
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;
public static final int MEDIA_TYPE_IMAGE = 1;
private Uri fileUri;
private Context context;
private static UnityBridge instance;
public Bitmap imgbitmap;
public String picturepath;

public UnityBridge() {
    this.instance = this;
}

public static UnityBridge instance() {
    if(instance == null) {
        instance = new UnityBridge();
    }
    return instance;
}

public void setContext(Context context) {
    this.context = context;
}

public void openCamera()
{
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image
    intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name

    // start the image capture Intent
    startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
}
/** Create a file Uri for saving an image or video */
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
    // using Environment.getExternalStorageState() before doing this.

    File mediaStorageDir = new File(android.os.Environment.getExternalStorageDirectory(), "Demo");
    // 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("Demo", "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 {
        return null;
    }

    return mediaFile;
}


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

    Log.d("Request Code: "+requestCode,"Result Code: "+resultCode);

    if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            // Image captured and saved to fileUri specified in the Intent
            Toast.makeText(this.context, "Image saved to:\n" +
                     data.getData(), Toast.LENGTH_LONG).show();
        } else if (resultCode == RESULT_CANCELED) {
            Toast.makeText(this.context, "Image Capture cancelled by the user", Toast.LENGTH_LONG).show();
            // User cancelled the image capture
        } else {
            // Image capture failed, advise user
            Toast.makeText(this.context,"Something unexpected happened, Please check your Camera",Toast.LENGTH_LONG).show();
        }
    }

}

public void showMessage(String message) {
    Toast.makeText(this.context, message, Toast.LENGTH_SHORT).show();
}
}

Solution

  • the NPE is here: Toast.makeText(this.context, "Image saved to:\n" + data.getData(), Toast.LENGTH_LONG).show();

    because when you start the activity (camera) the file will be saved containg the photo, and Intent data parameter will be null.

    data is returned in the Intent param in case no EXTRA_OUTPUT is set. and it will contain the photo itself, not it's path.

    to avoid the NPE use this toast (without data param) Toast.makeText(this.context, "Image saved", Toast.LENGTH_LONG).show();

    EDIT:

    use this to get storage directory, this way it will be saved to images folder which will be discoverable by gallery

    File storageDir = Environment.getExternalStoragePublicDirectory(
                Environment.DIRECTORY_PICTURES);
    

    and to display save path, use a global String variable to store the file path when you create it's file, then show it in the toast.

    in opencamera() method:

    fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);
    globalStringFilePath = fileUri .getAbsolutePath();
    

    then your toast will be

    Toast.makeText(this.context, "Image saved to:\n" + globalStringFilePath , Toast.LENGTH_LONG).show()