为什么在发送位图时会崩溃

huangapple 未分类评论45阅读模式
英文:

Why does it crash while sending Bitmap

问题

我正尝试通过发送 Bitmap 图像来分享一张图片我找到的解决方案在 Android 10.0 的模拟器上运行正常但在 Android 7.0以及我运行 Android 9 的 LG V20 手机却崩溃

以下是我的当前代码有没有办法避免崩溃非常感谢您的帮助

picIV.buildDrawingCache();
Bitmap bitmap = picIV.getDrawingCache();

String path = MediaStore.Images.Media.insertImage(getContentResolver(),
bitmap, "Challengers", null);

Uri uri = Uri.parse(path);

Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/*");
share.putExtra(Intent.EXTRA_STREAM, uri);
//share.putExtra(Intent.EXTRA_TEXT, "I found something cool!");
startActivity(Intent.createChooser(share, "Share Your Design!"));

似乎崩溃发生在运行以下这行代码时

Uri uri = Uri.parse(path);
英文:

I am trying to share an image by sending a Bitmap. The solution i found works on the emulator for Android 10.0 but not on Android 7.0 (neither on my LG V20 running Android 9) where it crashes.

Here is my current code. Any idea how to avoid the crash? Thanks in advance for your help.

            picIV.buildDrawingCache();
            Bitmap bitmap = picIV.getDrawingCache();

            String path = MediaStore.Images.Media.insertImage(getContentResolver(),
            bitmap, "Challengers", null);

            Uri uri = Uri.parse(path);

            Intent share = new Intent(Intent.ACTION_SEND);
            share.setType("image/*");
            share.putExtra(Intent.EXTRA_STREAM, uri);
            //share.putExtra(Intent.EXTRA_TEXT, "I found something cool!");
            startActivity(Intent.createChooser(share, "Share Your Design!"));

The crash seems to be happenning when running this line

            Uri uri = Uri.parse(path);

答案1

得分: 0

也许你的 pathnull?你进行过调试吗?

从方法 Uri.parse(...) 的源代码中我注意到,如果它的参数是 null,它会返回一个错误;而且 MediaStore.Images.Media.insertImage(...) 会在“如果由于任何原因图像未能被存储”时返回 null

英文:

Maybe your path is null? Did you debug it?

From the source of the method Uri.parse(...) I noticed that it returns an error if it takes null as an argument and MediaStore.Images.Media.insertImage(...) returns null "if the image failed to be stored for any reason".

答案2

得分: 0

发现另一种在 Android 7 上有效但在 Android 10 上无效的方法所以找到了一种方法使它们能够在一起工作

Uri uri;
String path = MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, "Challengers", null);

if (path != null) {
    uri = Uri.parse(path);
} else {
    uri = null;
    String string = "";
    try {
        File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "to-share.png");
        FileOutputStream stream = new FileOutputStream(file);
        bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream);
        stream.close();
        uri = Uri.fromFile(file);
    } catch (IOException e) {
        Log.d(string, "IOException while trying to write file for sharing: " + e.getMessage());
    }
}

Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/*");
share.putExtra(Intent.EXTRA_STREAM, uri);
//share.putExtra(Intent.EXTRA_TEXT, "I found something cool!");
startActivity(Intent.createChooser(share, "Share Your Design!"));
英文:

Found another method that worked on Android 7 but not on Android 10. So found out a way to make them work together.

                Uri uri;
                String path = MediaStore.Images.Media.insertImage(getContentResolver(), bitmap, "Challengers", null);

                if (path!=null) {
                    uri = Uri.parse(path);
                }else{
                    uri = null;
                    String string="" ;
                    try {
                        File file = new File(getExternalFilesDir(Environment.DIRECTORY_PICTURES), "to-share.png");
                        FileOutputStream stream = new FileOutputStream(file);
                        bitmap.compress(Bitmap.CompressFormat.PNG, 90, stream);
                        stream.close();
                        uri = Uri.fromFile(file);
                    } catch (IOException e) {
                        Log.d(string, "IOException while trying to write file for sharing: " + e.getMessage());
                    }
                }

                Intent share = new Intent(Intent.ACTION_SEND);
                share.setType("image/*");
                share.putExtra(Intent.EXTRA_STREAM, uri);
                //share.putExtra(Intent.EXTRA_TEXT, "I found something cool!");
                startActivity(Intent.createChooser(share, "Share Your Design!"));

答案3

得分: 0

以下是翻译好的代码部分:

  1. View 创建 Bitmap
fun createBitmapFromView(view: View): Bitmap {
    val bitmap = Bitmap.createBitmap(view.measuredWidth, view.measuredHeight, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(bitmap)
    view.layout(view.left, view.top, view.right, view.bottom)
    view.draw(canvas)
    return bitmap
}
  1. 创建用于保存 BitmapFile
fun getFileFromBitmap(bitmap: Bitmap): File? {
    val parentDirectory = File(externalCacheDir, "reminder_images")  // 图像文件存储在外部缓存目录/reminder_images中
    if (!parentDirectory.exists()) {
        parentDirectory.mkdirs()
    }
    val externalCacheFile = File(parentDirectory, "name_of_your_file.png")
    return writeBitmapToFile(externalCacheFile, bitmap)
}
  1. 使用 StreamBitmap 写入 File
fun writeBitmapToFile(externalCacheFile: File, bitmap: Bitmap): File? {
    return try {
        val fOut = FileOutputStream(externalCacheFile)
        bitmap.compress(Bitmap.CompressFormat.PNG, 85, fOut)
        fOut.flush()
        fOut.close()
        externalCacheFile
    } catch (e: Exception) {
        null
    }
}
  1. 在清单文件中创建 FileProvider
<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="com.your_package_name.FileProvider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/provider_paths" />
</provider>
  1. 创建 provider_paths.xml 资源文件
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path name="external_files" path="."/>
</paths>
  1. 使用 FileProviderFile 获取 Uri
val uri = FileProvider.getUriForFile(context, "com.your_package_name.FileProvider", externalCacheFile)

一旦您获得了图像文件的 Uri,可以像以前一样使用 Intent 共享文件。

在我的解决方案中,图像文件存储在应用程序特定的外部目录中。如果卸载应用程序,此图像文件将被删除。如果您需要其他行为,请查看data-storage

英文:

This should work across each API -- Answer is in Koltin

  1. Create Bitmap From View

    fun createBitmapFromView(view: View): Bitmap {
            val bitmap = Bitmap.createBitmap(view.measuredWidth, 
            view.measuredHeight, Bitmap.Config.ARGB_8888)
            val canvas = Canvas(bitmap)
            view.layout(view.left, view.top, view.right, view.bottom)
            view.draw(canvas)
            return bitmap
        }
    
  2. Create a File for saving the Bitmap

    fun getFileFromBitmap(bitmap: Bitmap): File? {
    val parentDirectory = File(externalCacheDir, &quot;reminder_images&quot;)  //image file is stored in external cache directory/reminder_images
    if (!parentDirectory.exists()) {
        parentDirectory.mkdirs()
    }
    val externalCacheFile = File(parentDirectory, &quot;name_of_your_file.png&quot;)
    return writeBitmapToFile(externalCacheFile, bitmap)
    

    }

  3. Write the Bitmap to File using Stream

    fun writeBitmapToFile(externalCacheFile: File, bitmap: Bitmap): File? {
        return try {
            val fOut = FileOutputStream(externalCacheFile)
            bitmap.compress(Bitmap.CompressFormat.PNG, 85, fOut)
            fOut.flush()
            fOut.close()
            externalCacheFile
        } catch (e: Exception) {
            null
        }
    }
    
  4. Create the FileProvider in Manifest

             &lt;provider
                android:name=&quot;androidx.core.content.FileProvider&quot;
                android:authorities=&quot;com.your_package_name.FileProvider&quot;
                android:exported=&quot;false&quot;
                android:grantUriPermissions=&quot;true&quot;&gt;
                &lt;meta-data
                    android:name=&quot;android.support.FILE_PROVIDER_PATHS&quot;
                    android:resource=&quot;@xml/provider_paths&quot; /&gt;
            &lt;/provider&gt;
    
  5. 5.Create the provider_paths.xml resource file

     &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
      &lt;paths xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
        &lt;external-path name=&quot;external_files&quot; path=&quot;.&quot;/&gt;
      &lt;/paths&gt;
    
  6. Get Uri From File using FileProvider

    val uri = FileProvider.getUriForFile(context,&quot;com.your_package_name.FileProvider&quot;, externalCacheFile)
    

Once you have the Uri of the image file share the file as you were doing earlier using Intent.

In my solution, the image file is stored in app-specific external directories. This image file would be deleted if your app is uninstalled. If you want some other behaviour please check data-storage.

答案4

得分: 0

终于找到问题所在。是权限的问题。尽管我已经在Manifest.xml中添加了权限,但还需要在onCreate方法中添加几行代码。

    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, requestCode);
    onRequestPermissionsResult(requestCode, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, grantResults);

感谢大家的回答,真的很有帮助!

英文:

Finally found the problem. It was the permissions. Even though i had put the permissions in the Manifest.xml also need to add a couple lines in onCreate.

    ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},requestCode);
    onRequestPermissionsResult(requestCode,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},grantResults);

Thanks everyone for your answers, really helpful!

huangapple
  • 本文由 发表于 2020年4月5日 08:21:19
  • 转载请务必保留本文链接:https://java.coder-hub.com/61036518.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定