在我的应用程序中,我正在尝试创建一个包含位图对象中包含的图像的电子邮件。
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()
因此,根据错误消息的建议,我尝试grantUriPermission。
grantUriPermission(String toPackage, Uri uri, int modeFlags)
但我不确定要给toPackage或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的uri和提供者项目?这是正确的方法吗?
非常感谢您提供的任何帮助,提示,指南或建议!
答案 0 :(得分:9)
尝试在AndroidManifest.xml中包含此内容。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
在Android 6.0+上,用户必须将权限授予应用程序,否则会抛出SecurityException。
要执行此操作,请转到“设置/应用/ [AppName] /权限”并允许存储权限。
答案 1 :(得分:3)
我有类似的问题。以下是我解决项目问题的方法。您应该能够根据您的解决方案进行调整。此解决方案还有一些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;
}
答案 2 :(得分:2)
我通过向intent添加权限标志解决了我的问题,如下所示:
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
更多细节可以在文档中找到: https://developer.android.com/reference/android/support/v4/content/FileProvider.html#Permissions