0

I'm trying to take picture when Image clicked, and then save Image Uri in FileProvide.

In my app, when I take picture and save it. I can't save my pic in my database.

I got null point error Error message

Process: com.example.android.inventoryapp, PID: 7732
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { act=inline-data (has extras) }} to activity {com.example.android.inventoryapp/com.example.android.inventoryapp.EditorActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.toString()' on a null object reference
    at android.app.ActivityThread.deliverResults(ActivityThread.java:4360)
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:4402)
    at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:49)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:193)
    at android.app.ActivityThread.main(ActivityThread.java:6669)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
 Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.toString()' on a null object reference
    at com.example.android.inventoryapp.EditorActivity.onActivityResult(EditorActivity.java:483)
    at android.app.Activity.dispatchActivityResult(Activity.java:7454)
    at android.app.ActivityThread.deliverResults(ActivityThread.java:4353)
    at android.app.ActivityThread.handleSendResult(ActivityThread.java:4402) 
    at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:49) 
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108) 
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loop(Looper.java:193) 
    at android.app.ActivityThread.main(ActivityThread.java:6669) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 

How to solve this problem? Here is my code,

My EditorActivity

TakePicture method

  private void takePicture() {
    Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    try {
        File photoFile = createImageFile();

        Log.d(LOG_TAG, "File: " + photoFile.getAbsolutePath());

        if (cameraIntent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(cameraIntent, REQUEST_IMAGE_CAPTURE);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

CreateImageFile method

 private File createImageFile() throws IOException {// Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    File image = File.createTempFile(
            imageFileName,  /* prefix */
            ".jpg",         /* suffix */
            storageDir      /* directory */
    );

    // Save a file: path for use with ACTION_VIEW intents
    mCurrentPhotoPath = image.getAbsolutePath();
    return image;
}

saveItem method

 ContentValues values = new ContentValues();
    if (mHasImage) {
        values.put(ItemContract.ItemEntry.COLUMN_PICTURE, mImgUri.toString());
    } else {
        Toast.makeText(this, "Take photo", Toast.LENGTH_SHORT).show();
        return;
    }

onActivity method

 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
        Log.i(LOG_TAG, "Uri: " + mImgUri.toString());
        mImgTxt.setText(mImgUri.toString());
        mImgBitmap = getBitmapFromUri(mImgUri);
        mImageClick.setImageBitmap(mImgBitmap);
    }
}

getBitmapFromUri method

private Bitmap getBitmapFromUri(Uri uri) {
    ParcelFileDescriptor parcelFileDescriptor = null;
    try {
        parcelFileDescriptor =
                getContentResolver().openFileDescriptor(uri, "r");
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
        parcelFileDescriptor.close();
        return image;
    } catch (Exception e) {
        Log.e(LOG_TAG, "Failed to load image.", e);
        return null;
    } finally {
        try {
            if (parcelFileDescriptor != null) {
                parcelFileDescriptor.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
            Log.e(LOG_TAG, "Error closing ParcelFile Descriptor");
        }
    }
}
young ban
  • 169
  • 1
  • 12
  • can you post the error stacktrace? – Raghunandan Sep 20 '18 at 09:06
  • what is exact issue? does it refrsh? check https://stackoverflow.com/questions/18624235/android-refreshing-the-gallery-after-saving-new-images if same kind of issue – Developer Sep 20 '18 at 09:06
  • did you add permission in manifest and ask runtime permissions ? – Quick learner Sep 20 '18 at 09:11
  • i ran your code on emulator 28. seems to be working fine. On what device did the crash occur? taking picture is working fine – Raghunandan Sep 20 '18 at 09:44
  • @AndroidUser Nope, If i take pic and save and then app is crashed. – young ban Sep 20 '18 at 10:28
  • @Raghunandan take picture is fine, but when i clicked save it. app is crashed. – young ban Sep 20 '18 at 10:29
  • @youngban saving also worked fine on emulator 28. and i get a uri as Uri: **content://co.carlosandresjimenez.android.myfileprovider/share/dcim/MyFileProviderExample/IMG_20180920_160106_5483292216731325801.jpg** – Raghunandan Sep 20 '18 at 10:30
  • @Raghunandan I reference 'MyFileProviderExample' this code and I made app my self. But when I save the picture app is crashed in my app. Not that code. – young ban Sep 20 '18 at 10:40
  • @youngban look the code you linked works. so what is that your doing differently you just edited recently. Your stacktrace pointed to EditorActivity. so you should look at it and also post editoractivity code. how else can anyone help? – Raghunandan Sep 20 '18 at 10:47
  • @Raghunandan Sorry guys, I'm not fluent with English. So My post was bit confused. Now I'm posted my EditorActivity code. – young ban Sep 20 '18 at 10:57

2 Answers2

3

Create a folder xml in res then create a file "my_paths" in this folder and paste below code

<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
    name="my_images"
    path="Android/data/YOUR_APP_PACKAGE_NAME/files" />//Don't forget to add package name here i.e. com.android.example
</paths>

Add this to you AndroidManifest.xml in application tag.

<provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="YOUR_APP_PACKAGE_NAME"////Don't forget to add package name here i.e. com.android.example
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/my_paths" />
    </provider>

Now you need permission to write file in storage,

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

After getting permission call this method to open camera

private void displayCamera() {
    File imagesFolder = new File(Environment
            .getExternalStorageDirectory(), getContext().getResources()
            .getString(R.string.app_name));
    try {
        if (!imagesFolder.exists()) {
            boolean isCreated = imagesFolder.mkdirs();
            if (!isCreated) {
                Toast.makeText(getContext(), R.string.str_storage_error, Toast.LENGTH_LONG).show();
                return;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
    String imageFileName = "IMG_" + timeStamp + "_";
    File storageDir = getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    try {
        File image = File.createTempFile(
                imageFileName,  /* prefix */
                ".jpg",  /* suffix */
                storageDir     /* directory */
        );
        Uri uri = FileProvider.getUriForFile(getContext(), getContext().getPackageName(), image);

            String imagePath=image.getAbsolutePath();//Store this path as globe variable

            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
            startActivityForResult(intent, Constants.CAMERA);

    } catch (ActivityNotFoundException | IOException e) {
        e.printStackTrace();
    }
}


@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
     if (resultCode == Activity.RESULT_OK) {
         //Here you need to show image 
         //if you want to show using glid then use

         Glide.with(this)
              .load("file://" + imagePath)//here you need image path which is stored in globel variable
              .apply(RequestOptions.circleCropTransform())
              .into(mBinder.ivDp);
     }
}
Solulab Inc.
  • 107
  • 9
0

If you are know kotlin language please copy paste code in application. If you want to write in java just see logic.

On Camera Button Click:-

     /**
     * Handle camera button click
     */
    private fun onCameraButtonClick() {
        try {
            mPhotoFile = CommonUtils.createImageFile(this)
            // Continue only if the File was successfully created
            if (mPhotoFile != null) {
                dispatchTakePictureIntent(mPhotoFile!!)
            }
        } catch (ex: IOException) {
            // Error occurred while creating the File
            onError(R.string.some_error)
        }
    }

Create Image file : -

 /**
 * Create image file to save capture image
 * @return Image File
 */
@Throws(IOException::class)
fun createImageFile(context: Context): File {
    // Create an image file name
    val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
    val imageFileName = "JPEG_" + timeStamp + "_"
    val storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
    return File.createTempFile(
            imageFileName, /* prefix */
            ".jpg", /* suffix */
            storageDir      /* directory */
    )
}

After creating image file check weather is permission is grant or not:-

  /**
 * Launch camera application to take picture
 */
private fun dispatchTakePictureIntent(photoFile: File) {
    if (hasPermission(Manifest.permission.CAMERA) && hasPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
        val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        // Ensure that there's a camera activity to handle the intent
        if (takePictureIntent.resolveActivity(this.packageManager) != null) {

            val photoURI = FileProvider.getUriForFile(this,
                    "your packege name.fileprovider",
                    photoFile)
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
            startActivityForResult(takePictureIntent, AppConstants.REQUEST_IMAGE_CAPTURE)

        }
    } else {
        requestPermissionsSafely(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA), AppConstants.REQUEST_CAMERA_PERMISSION_CODE)
    }
}

Handle Camera Result:-

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if (resultCode == Activity.RESULT_OK) {
        when (requestCode) {
            AppConstants.REQUEST_IMAGE_CAPTURE -> {
                // Get the camera result
                mActivityEditProfileBinding.imgProfilePic.setImageBitmap(CommonUtils.getBitmapImageFromFilePath(mPhotoFile!!))

            }
            else -> super.onActivityResult(requestCode, resultCode, data)
        }
    }
}

Get bitmap from file:-

  /**
 * @return Bitmap from saved image file path
 */
fun getBitmapImageFromFilePath(file: File): Bitmap? {
    if (file.exists()) {
        val myBitmap = BitmapFactory.decodeFile(file.absolutePath)
        val ei = ExifInterface(file.absolutePath)
        val orientation = ei.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                ExifInterface.ORIENTATION_UNDEFINED)

        val rotatedBitmap: Bitmap?
        rotatedBitmap = when (orientation) {

            ExifInterface.ORIENTATION_ROTATE_90 -> rotateImage(myBitmap, 90.0f, file)

            ExifInterface.ORIENTATION_ROTATE_180 -> rotateImage(myBitmap, 180.0f, file)

            ExifInterface.ORIENTATION_ROTATE_270 -> rotateImage(myBitmap, 270.0f, file)

            ExifInterface.ORIENTATION_NORMAL -> myBitmap
            else -> myBitmap
        }
        return rotatedBitmap
    }
    return null
}

Paste into your manifest :-

   <provider
        android:name="android.support.v4.content.FileProvider"
        android:authorities="your package.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>

Create a xml name folder in your res folder paste below code:-

    <?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path
        name="external_files"
        path="." />
</paths>
Anand Jain
  • 2,365
  • 7
  • 40
  • 66