工作中有一个需求是分享一些图片到其他应用,但是由于是Android11的系统,看了网上很多内容,有点混乱,所以在此记录一下实现方法。
1.从网络上下载图片到本地,如果是存储在内部存储和外部存储的app下的私有目录里(也就是沙盒目录),是不需要申请读写权限的,可以直接写入和读取SD卡中的文件。
2.对于外部存储沙盒里的文件,可以通过file provider来分享给其他应用。 首先在清单文件里声明以下代码
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_paths" />
</provider>
然后在res文件夹下的xml文件夹创建file_provider_paths.xml文件
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-cache-path name="external_cache_path" path="."/>
<!--配置root-path。这样子可以读取到sd卡和一些应用分身的目录,否则微信分身保存的图片,就会导致 java.lang.IllegalArgumentException: Failed to find configured root that contains /storage/emulated/999/tencent/MicroMsg/WeiXin/export1544062754693.jpg,在小米6的手机上微信分身有这个crash,华为没有
-->
<root-path name="root-path" path="" />
</paths>
我的应用存储的图片路径/storage/emulated/10/Android/data/packgname,所以必须加上root-path。
下载图片之后,path路径转换为uri分享出去
val contentUri = FileProvider.getUriForFile(
context,
context.getPackageName() + ".fileprovider", // 要与`AndroidManifest.xml`里配置的`authorities`一致,假设你的应用包名为com.example.app
file
)
3.其他应用只要添加,并且拿到uri,解析显示。
<queries>
<package android:name="com.xx.xx.fileprovider" />
</queries>
private Bitmap getInputStrem(String icon) {
if(icon == null){
return null;
}
Uri fileUri = Uri.parse(icon);
Bitmap bm = null;
try {//获得uri图片并显示
InputStream is = getContentResolver().openInputStream(fileUri);
bm= BitmapFactory.decodeStream(is);
Log.e(TAG,"bm is null?:"+( bm== null));
return bm;
} catch(FileNotFoundException e) {
e.printStackTrace();
System.out.println("fatal e.getMessage() = " + e.getMessage());
}
return null;
}
//拿到uri的图片,显示在textview上
if(iconUri != null){
Bitmap bm = getInputStrem(iconUri);
if(bm != null){
Log.e(TAG,"updateButton--填充图片====");
//根据Bitmap对象创建ImageSpan对象
ImageSpan imageSpan=new ImageSpan(this,bm);
//创建一个SpannableString对象,以便插入用ImageSpan对象封装的图像
SpannableString spannableString=new SpannableString("icon");
//用ImageSpan对象替换icon
spannableString.setSpan(imageSpan, 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//将图像显示在TextView组件上
textview.setText(spannableString);
}
}