为什么在外部存储中保存位图失败,即使位图已正确创建并且可以在 imageView 中显示?

Why saving a bitmap in external storage failed, even though bitmap is created properly and can be displayed in imageView?

我可以从文件位置 "file:///sdcard/temporary_file.jpg" 成功 运行 意图共享屏幕截图(位图)。但现在我坚持将位图保存到那个位置。

我在清单中包含以下内容

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

还有这个函数来检查权限:

@Override
public void onRequestPermissionsResult(int requestCode,
                                       String[] permissions, int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE:
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // do your stuff
            } else {
                Toast.makeText(iv_ScoreBoard.this, "GET_ACCOUNTS Denied",
                        Toast.LENGTH_SHORT).show();
            }
            break;
        default:
            super.onRequestPermissionsResult(requestCode, permissions,
                    grantResults);
    }
}

点击分享按钮:

    View rootView = getWindow().getDecorView().findViewById(android.R.id.content);
    Bitmap bitmaptest = getScreenShot(rootView);

    Intent share = new Intent(Intent.ACTION_SEND);
    share.putExtra(Intent.EXTRA_TEXT, "@Share from App \"XXYY\"");
    share.setType("image/jpeg");
    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    bitmaptest.compress(Bitmap.CompressFormat.JPEG, 100, bytes);

    File f = new File(Environment.getExternalStorageDirectory() + File.separator + "temporary_file.jpg");
            try {
                f.createNewFile();
                FileOutputStream fo = new FileOutputStream(f);
                fo.write(bytes.toByteArray());
            } catch (IOException e) {
                e.printStackTrace();
            }
            share.putExtra(Intent.EXTRA_STREAM, Uri.parse("file:///sdcard/temporary_file.jpg"));
            startActivity(Intent.createChooser(share, "Share Image"));

            return true;

getScreenShot(查看视图)

public static Bitmap getScreenShot(View view) {
    View screenView = view.getRootView();
    screenView.setDrawingCacheEnabled(true);
    Bitmap bitmap = Bitmap.createBitmap(screenView.getDrawingCache());
    screenView.setDrawingCacheEnabled(false);
    return bitmap;
}

点击分享按钮时,它会产生一个黑色的屏幕帽作为图片... 没有创建文件,没有发现错误。

您至少在问题中提供的代码中没有 requesting/checking 权限。

您的代码仅实现了 onRequestPermissionResult,一旦您请求了权限,就会调用它来通知您结果。

您必须请求许可。

在您的 activity 中实施以下操作。

 final int requestCode1 = 100;//this is the constant which you pass while requesting permission.
 // this code helps you to identify which permission was requested in onPermissionResultReceived, in case you are dealing with more than one permission groups. 
 ....
 onCreate(){
 ... // your code goes here
 ...
 @Override
 public void onClick(View view){
 if (ContextCompat.checkSelfPermission(thisActivity, 
     Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
    // Permission is not granted
    // request permission    
     ActivityCompat.requestPermissions(iv_ScoreBoard.this, new String[] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, requestCode1);
 } else{
    //permission granted
    takeScreenShot();
 }

你的 onRequestPermissionsResult

public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
    case requestCode1:
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            // do your stuff
             takeScreenShot();
        } else {
            Toast.makeText(iv_ScoreBoard.this, "Permission Denied",
                    Toast.LENGTH_SHORT).show();
        }
        break;
    default:
        super.onRequestPermissionsResult(requestCode, permissions,
                grantResults);
   }
}

在 onCreate 中或在执行需要这些权限的操作之前添加以上代码。

参考 - https://developer.android.com/training/permissions/requesting#java

将文件共享到另一个应用程序时,您需要提供 Uri 权限。

为此,您首先必须在 Manifest 中创建一个提供程序,如下所示:

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="${applicationId}.provider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths" />
</provider>

@xml/provider_paths 将如下所示:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="SavedImages" path="Android/data/com.yourpackagename.yourappname/files/SavedImages/"/>
</paths>

您必须在您的 res->xml 文件夹中创建以上内容,我将其命名为 provider_paths.xml

如果您没有 xml 文件夹,请创建一个。


然后当您共享文件时,您应该提供权限:

Uri imageUri;
Intent share = new Intent(Intent.ACTION_SEND);
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
    imageUri = Uri.parse("file:///sdcard/temporary_file.jpg");
}else {
    File newFile = new File(Environment.getExternalStorageDirectory() + File.separator + "temporary_file.jpg");
    imageUri = FileProvider.getUriForFile(getContext(), getContext().getPackageName() + ".provider", newFile);
    share.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
share.setType("image/jpeg");
share.putExtra(Intent.EXTRA_STREAM, imageUri);
share(Intent.createChooser(share, "Share image using"));

老实说,我不认为您的问题与运行时权限有关。 如果是,您会遇到崩溃并且不会创建文件。正如您在问题中所述 It produces a black screen cap as a picture when share button is clicked... No file is created, no error is found..

另一方面,当不提供 Uri 权限时,很可能会产生 Uri 暴露异常。

该文件仍将被创建,但它将是空的。就像你正在经历的那样。