Android: how to use grantUriPermission to be able to create and send emails using a raster attachment

From my application, I am trying to create an email containing an image contained in a raster object.

private void sendEmailWithBitmapAttached(){ final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND); emailIntent.setType("plain/text"); emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Email Subject"); emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Email Body"); emailIntent.setType("image/png"); ContentResolver cr = getContentResolver(); // insert the image and create a path String imageBitmapPath = MediaStore.Images.Media.insertImage(cr, bitmapForEmail,"title", "description"); // create a uri Uri imageUri = Uri.parse(imageBitmapPath); emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); emailIntent.putExtra(Intent.EXTRA_STREAM, imageUri); // send the email startActivity(Intent.createChooser(emailIntent, "Send mail...")); } 

This works fine in Android 2.3.

But using later versions, it causes the following error:

 07-13 23:01:01.252: E/MediaStore(5194): Failed to insert image 07-13 23:01:01.252: E/MediaStore(5194): java.lang.SecurityException: Permission Denial: writing com.android.providers.media.MediaProvider uri content://media/external/images/media from pid=5194, uid=10151 requires android.permission.WRITE_EXTERNAL_STORAGE, or grantUriPermission() 

So, accepting the error suggestion, I tried to provide a UriPermission.

 grantUriPermission(String toPackage, Uri uri, int modeFlags) 

But I'm not sure what to put for toPackage or uri

But then again, using the error message, I changed the code as follows:

 private void sendEmailWithBitmapAttached(){ final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND); emailIntent.setType("plain/text"); emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Email Subject"); emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, "Email Body"); emailIntent.setType("image/png"); ContentResolver cr = getContentResolver(); // create a Uri for the content provider suggested by the error message Uri uri = Uri.parse("content://media/external/images/media"); // create a package provider string suggested by the error messge. String provider = "com.android.providers.media.MediaProvider"; // grant all three uri permissions! grantUriPermission(provider, uri, Intent.FLAG_GRANT_READ_URI_PERMISSION); grantUriPermission(provider, uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION); grantUriPermission(provider, uri, Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); // insert the image and create a path String imageBitmapPath = MediaStore.Images.Media.insertImage(cr, bitmapForEmail,"title", "description"); // create a uri Uri imageUri = Uri.parse(imageBitmapPath); emailIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); emailIntent.putExtra(Intent.EXTRA_STREAM, imageUri); // send the email startActivity(Intent.createChooser(emailIntent, "Send mail...")); } 

And I get the same error.

Can a gracious soul please give me a hint how to take care of saving uri and provider resources? Is this the right approach?

Thank you very much for ANY help, hint, recommendations or suggestions you can provide!

+6
source share
3 answers

Try to include this in your AndroidManifest.xml.

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

In Android 6.0+, permission must be granted by the user for the application, otherwise this will raise a SecurityException.

To do this, go to Settings / Applications / [AppName] / Permissions and enable storage permission.

+7
source

I had a similar problem. Below I will tell you how I solved the problem for my project. You must be able to adapt this solution. This solution also has Firebase code that can be ignored. The key points are ActivityCompat.requestPermissions and ActivityCompat.checkSelfPermission:

 private void shareViaEmail() { int permissionCheck = ContextCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE); if (permissionCheck != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)) { AlertDialog.Builder alertBuilder = new AlertDialog.Builder(this); LayoutInflater inflater = this.getLayoutInflater(); final ViewGroup nullParent = null; final View dialogView = inflater.inflate(R.layout.alert_dialog, nullParent); alertBuilder.setView(dialogView); alertBuilder.setCancelable(true); alertBuilder.setTitle("Permission request"); String message = "\n\n" + getString(R.string.email_images); AppCompatTextView notice = (AppCompatTextView) dialogView.findViewById(R.id.notice); if (notice != null) { notice.setText(message); notice.setTextSize(getResources().getInteger(R.integer.dialog_text_size)); } else { alertBuilder.setMessage(message); } alertBuilder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() { @TargetApi(Build.VERSION_CODES.JELLY_BEAN) public void onClick(DialogInterface dialog, int which) { mShowingAlert = false; ActivityCompat.requestPermissions(baseActivity(), new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_TARGET_WRITE_PERMISSION_REQUEST); } }); mAlertDialog = alertBuilder.create(); mAlertDialog.show(); return; } } ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_TARGET_WRITE_PERMISSION_REQUEST); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) { if (requestCode == MY_TARGET_WRITE_PERMISSION_REQUEST) { doShareViaEmail(); } else { failWriteImage(); } } } protected void failWriteImage() { getHandler().post(new Runnable() { @Override public void run() { String email_failed = getResources().getString(R.string.fail_email_attach); @SuppressLint("ShowToast") Toast toast = Toast.makeText(getApplicationContext(), email_failed, Toast.LENGTH_SHORT); new CustomToast(toast).invoke(); } }); } protected void doShareViaEmail() { FireUtilities fireUtilities = FireUtilities.getInstance(); fireUtilities.logEvent(mFirebaseAnalytics, "option_item", "share", "share_string"); Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.string_share)); String appStoreLink = getString(R.string.app_store_link); String emailText = getString(R.string.share_string_body1) + " " + appStoreLink + " " + getString(R.string.share_string_body2); emailText = emailText + "<br><br>" + getTitleOfSegment(true, mCurrentSegment, mCurrentSegmentIndex); Bitmap targetImage = screenShot(mTargetImageView); if (targetImage != null) { ArrayList<Uri> files = new ArrayList<Uri>(); String path = MediaStore.Images.Media.insertImage(getContentResolver(), targetImage, "string", null); Uri targetUri = Uri.parse(path); files.add(targetUri); intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, files); } intent.setType("message/rfc822"); Spanned htmlText = fromHtml(getString(R.string.share_score_head1) + emailText + getString(R.string.share_score_head2)); intent.putExtra(Intent.EXTRA_TEXT, htmlText); try { startActivityForResult(Intent.createChooser(intent, "Email:"), 1234); } catch (final android.content.ActivityNotFoundException e) { String no_email_client = getResources().getString(R.string.no_email_client); @SuppressLint("ShowToast") Toast toast = Toast.makeText(getApplicationContext(), no_email_client, Toast.LENGTH_LONG); new CustomToast(toast).invoke(); } } public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == 1234) { LogHelper.v(TAG, "e-mail successfully sent"); } } public Bitmap screenShot(View view) { if (view != null) { Bitmap bitmap = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); view.draw(canvas); return bitmap; } return null; } 
0
source

I solved the problem by adding permission flags to the intent, for example:

 intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 

More information can be found in the documentation: https://developer.android.com/reference/android/support/v4/content/FileProvider.html#Permissions

0
source

Source: https://habr.com/ru/post/972156/


All Articles