Intereting Posts
Захват View.setOnClickListener (), определенный через XML Android Studio || GDK 'привет слово' || Import com.google.android.glass.app.Card || Невозможно разрешить символ «google» Безопасно ли использовать этот способ для передачи контекста в неконтекстные классы @ Проблема с отображением шрифта на теге абзаца, Chrome Android 4 Как подавать данные в PagerAdapter Android Google Play с измененным именем приложения Android Google отображает фрагмент в RecyclerView.ViewHolder Обновить разрешения на токен в Facebook Android SDK Установить положение / размер элемента пользовательского интерфейса в процентах от размера экрана Фиксированный и всегда видимый нижний колонтитул ниже ListFragment Сделать части текстового кликабельными (не URL-адрес) Преобразование представления в Bitmap без отображения его в Android? Инструменты namespace android listitem Связать объект с маркером (google map v2) Обнаружение, если ключи доступны на экранной клавиатуре мобильного устройства

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; }