Android: как использовать grantUriPermission, чтобы иметь возможность создавать и отправлять электронную почту с помощью растрового вложения

Из моего приложения я пытаюсь создать письмо, содержащее изображение, содержащееся в растровом объекте.

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

Это отлично работает в Android 2.3.

Но используя более поздние версии, он вызывает следующую ошибку:

 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() 

Итак, принимая предложение об ошибке, я попытался предоставить UriPermission.

 grantUriPermission(String toPackage, Uri uri, int modeFlags) 

Но я не уверен, что поставить для Package или uri

Но опять же, используя сообщение об ошибке, я изменил код следующим образом:

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

И я получаю ту же ошибку.

Может ли любезная душа, пожалуйста, дать мне подсказку, как позаботиться о ури и предметах поставщика grantUriPermission? Это правильный подход?

Большое спасибо за ЛЮБУЮ помощь, подсказку, рекомендации или предложения, которые вы можете предоставить!

Попробуйте включить это в свой AndroidManifest.xml.

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

В Android 6.0+ разрешение должно быть предоставлено пользователем для приложения, иначе это вызовет исключение SecurityException.

Для этого перейдите в Настройки / Приложения / [AppName] / Разрешения и разрешите разрешение хранилища.

У меня была аналогичная проблема. Ниже я расскажу, как я решил проблему для своего проекта. Вы должны уметь адаптировать это решение. В этом решении также есть код Firebase, который вы можете игнорировать. Ключевыми моментами являются ActivityCompat.requestPermissions и 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; } 
Intereting Posts
Android: как захватить долгое нажатие на мягкий вход / клавиатуру? Андроидный хром для закрытия вкладок браузера Как сделать fadein изображения на экране активности Android? Android Studio build не работает, требуется полная перестройка для продолжения Проверка по крайней мере одного переключателя выбирается из каждой радиогруппы в android? Введение или Учебник по извлечению данных с собственного сайта? Не удалось загрузить карту. Ошибка при обращении к серверам Google с помощью android google maps api v2 Проблема при назначении одного экземпляра календаря другому System.MissingMethodException: метод «Android.Support.V4.Widget.DrawerLayout.AddDrawerListener» не найден Панель заголовков Android PreferenceScreen удаляет Неожиданный сбой в BaseDexClassLoader Google Планета Земля на Android SSLException, связанный с отправкой товара для услуги Amazon Данные и синхронизация – синхронизация вручную. Каландр и контакты SENSOR_DELAY_GAME: сколько это?