英文:
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
也许你的 path
是 null
?你进行过调试吗?
从方法 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
以下是翻译好的代码部分:
- 从
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
}
- 创建用于保存
Bitmap
的File
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)
}
- 使用
Stream
将Bitmap
写入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
}
}
- 在清单文件中创建
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>
- 创建
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>
- 使用
FileProvider
从File
获取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
-
Create
Bitmap
FromView
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 }
-
Create a
File
for saving theBitmap
fun getFileFromBitmap(bitmap: Bitmap): File? { val parentDirectory = File(externalCacheDir, "reminder_images") //image file is stored in external cache directory/reminder_images if (!parentDirectory.exists()) { parentDirectory.mkdirs() } val externalCacheFile = File(parentDirectory, "name_of_your_file.png") return writeBitmapToFile(externalCacheFile, bitmap)
}
-
Write the
Bitmap
toFile
usingStream
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 } }
-
Create the
FileProvider
in Manifest<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>
-
5.Create the
provider_paths.xml
resource file<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="external_files" path="."/> </paths>
-
Get
Uri
FromFile
usingFileProvider
val uri = FileProvider.getUriForFile(context,"com.your_package_name.FileProvider", 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!
专注分享java语言的经验与见解,让所有开发者获益!
评论