Android:如何使用grantUriPermission创建和发送带位图附件的电子邮件

时间:2014-07-14 06:24:24

标签: java android bitmap

在我的应用程序中,我正在尝试创建一个包含位图对象中包含的图像的电子邮件。

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和提供者项目?这是正确的方法吗?

非常感谢您提供的任何帮助,提示,指南或建议!

3 个答案:

答案 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