How to get image from camera or gallery and upload to server in Android Q?

645 Views Asked by At

I am trying to get an image from the camera or gallery to upload on the server. My code is working perfectly in Android 9 or lower but I cannot able to access the image path in Android 10. I don't know much about Android 10’s Scoped Storage, Please review my code and help.

 private void selectImage(Context context, final int cameraRequestCode, final int galleryRequestCode) {

    if (!hasPermissions(context, PERMISSIONS)) {
        ActivityCompat.requestPermissions(requireActivity(), PERMISSIONS, PERMISSION_ALL);
    } else {
        final CharSequence[] options = {"Take Photo", "Choose from Gallery", "Cancel"};

        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle("Choose your profile picture");

        builder.setItems(options, new DialogInterface.OnClickListener() {

            @Override
            public void onClick(DialogInterface dialog, int item) {

                if (options[item].equals("Take Photo")) {
                   /* Intent takePicture = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                    startActivityForResult(takePicture, cameraRequestCode);*/
                    Uri outputFileUri = Uri.fromFile(sdImageMainDirectory);

                    Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
                    intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);

                    startActivityForResult(intent, cameraRequestCode);

                } else if (options[item].equals("Choose from Gallery")) {
                    Intent pickPhoto = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                    startActivityForResult(pickPhoto, galleryRequestCode);

                } else if (options[item].equals("Cancel")) {
                    dialog.dismiss();
                }
            }
        });
        builder.show();
    }
}

public File convertBitmaptoFile(Bitmap bitmap, String filename) throws IOException {
    File f = new File(requireContext().getCacheDir(), filename);
    f.createNewFile();


    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100 /*ignored for PNG*/, bos);
    byte[] bitmapdata = bos.toByteArray();


    FileOutputStream fos = new FileOutputStream(f);
    fos.write(bitmapdata);
    fos.flush();
    fos.close();
    return f;

}

'Here is my onActivity code'

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode != RESULT_CANCELED) {
        switch (requestCode) {
            case 0:

                try {
                    String millisecond = String.valueOf(Calendar.getInstance().getTimeInMillis());
                   // logo_file = new File(String.valueOf(convertBitmaptoFile(fileToBitmap(sdImageMainDirectory.getPath()), "IMAGE_" + millisecond + ".jpg")));

                   // img_logo.setImageURI(Uri.parse(logo_file.getAbsolutePath()));
                    img_logo.setImageURI(Uri.parse(getPath(Uri.fromFile(logo_file = new File(String.valueOf(convertBitmaptoFile(fileToBitmap(sdImageMainDirectory.getPath()), "IMAGE_" + millisecond + ".jpg")))))));
                    Log.e("logo file path","" +  logo_file.getPath());
                    Log.e("logo file absolute path","" +  logo_file.getAbsolutePath());
                } catch (IOException e) {
                    e.printStackTrace();
                }


                // fa_image.setImageURI(Uri.parse(fa_image_file.getPath()));

                break;
            case 1:
                if (resultCode == RESULT_OK && data != null) {
                    Uri selectedImage = Uri.parse(data.getData().getEncodedPath());
                    String[] filePathColumn = {MediaStore.Images.Media.DATA};
                    if (selectedImage != null) {
                        Cursor cursor = getActivity().getContentResolver().query(selectedImage,
                                filePathColumn, null, null, null);
                        if (cursor != null) {
                            cursor.moveToFirst();

                            int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
                            String picturePath = cursor.getString(columnIndex);
                            logo_file = new File(picturePath);
                            Log.e("IMAGE", "ja_image :" + logo_file);
                            img_logo.setImageBitmap(BitmapFactory.decodeFile(picturePath));
                            cursor.close();
                        }
                    }

                }
                break;

        }
    }
}
2

There are 2 best solutions below

1
On

Have you used android:requestLegacyExternalStorage="true" in AndroidManifest.xml

  <application
    android:name="com.xyz"
    android:allowBackup="true"
    android:exported="false"
    android:hardwareAccelerated="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:requestLegacyExternalStorage="true"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme"
    android:usesCleartextTraffic="true"
    tools:ignore="GoogleAppIndexingWarning"
    tools:targetApi="q">
0
On

In Android 10, you cannot access image using the uri provided in onActivityResult. Try this. I'm sure it will work for you. This is will work when you are selecting an image from gallery. For taking pictures from camera photo, the approach is a little different.

Kotlin Solution :

val imageType = contentResolver.getType(data.data!!)

data.data!!.let {
                application.contentResolver.openInputStream(it).use { inputStream ->
                    filePartImage = MultipartBody.Part.createFormData(
                        "image",     //should be same as the key of your parameter
                        "filename" + ".jpg",  // extension of file name is must
                        inputStream!!.readBytes().toRequestBody(imageType.toMediaTypeOrNull())
                    )
                }
            }

Later pass this filePartImage as your image parameter for uploading image to server.