安卓uni.previewImage预览file://本地图片失败,一直转圈
背景自己开发的安卓原生插件,会返回安卓绝对路径形式的图片,如:file:///data/user/0/com.sample.test/cache/20220316.jpg这是在应用的cache目录下直接写入的图片。返回到uniapp端后,在template中通过组件能正常显示图片。但通过uni.previewImage预览图片的话会一直转圈:参数为:{"current": 0,"urls": ["
·
背景
自己开发的安卓原生插件,会返回安卓绝对路径形式的图片,如:file:///data/user/0/com.sample.test/cache/20220316.jpg
这是在应用的cache目录下直接写入的图片。
返回到uniapp端后,在template中通过组件能正常显示图片。但通过uni.previewImage预览图片的话会一直转圈:
参数为:
{
"current": 0,
"urls": ["file:///data/user/0/com.sample.test/cache/20220316.jpg",
"file:///data/user/0/com.sample.test/cache/20220316_2.jpg",
]
}
接口返回:{“errMsg”:“previewImage:ok”},没有错误。
解决方法
uni.previewImage只支持预览uniapp缓存路径下的文件,uniapp的缓存路径即plus.io.PRIVATE_DOC对应的路径,可通过以下代码得到:
plus.io.requestFileSystem(plus.io.PRIVATE_DOC, async (entry) => {
console.log('uniapp cache dir: ', entry.root.fullPath);
});
一般形式如:/storage/emulated/0/Android/data/com.sample.test/apps/__UNI__94CMCOL/doc/
所以原生插件返回的图片如果需要使用uni.previewImage预览的话,必须要创建在上面的目录(或子目录)下。
知道了问题,解决方法也就有了:
- 原生插件里面维护了个静态变量,用来记录uniapp的缓存目录。
- 原生插件提供一个设置存储缓存目录的静态变量值的方法供uniapp调用。
- 在App.vue启动时,调用
plus.io.requestFileSystem(plus.io.PRIVATE_DOC
获得缓存路径后,调用原生插件方法更新 - 原生插件在返回图片时,创建到uniapp缓存目录下。
再次预览:
{
"current": 0,
"urls": [
"file:///storage/emulated/0/Android/data/com.sample.test/apps/__UNI__94CMCOL/doc/temp_42eb0/20220317.jpg",
"file:///storage/emulated/0/Android/data/com.sample.test/apps/__UNI__94CMCOL/doc/temp_42eb0/20220317_2.jpg"
]
}
完整代码
原生安卓端
注意需要在app/src/main/assets/dcloud_uniplugins.json文件中注册原生插件。
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.net.Uri;
import com.alibaba.fastjson.JSONObject;
import com.taobao.weex.adapter.URIAdapter;
import java.io.File;
import java.io.FileOutputStream;
import java.util.HashMap;
import io.dcloud.feature.uniapp.annotation.UniJSMethod;
import io.dcloud.feature.uniapp.bridge.UniJSCallback;
import io.dcloud.feature.uniapp.common.UniModule;
public class MyImgUni extends UniModule {
@UniJSMethod(uiThread = false)
public void getNativeImg(JSONObject opts, UniJSCallback callback) {
if (callback == null) return;
if (opts == null) {
callback.invoke(new HashMap<String, String>() {{
put("error", "`opts` required!");
}});
return;
}
try {
String imgPath = opts.getString("path");
if(imgPath.startsWith("_")){
// 将沙盒路径转为uri路径
imgPath = mUniSDKInstance.rewriteUri(Uri.parse(imgPath), URIAdapter.FILE).toString();
}
// 转为绝对路径
imgPath = imgPath.replace("file://", "");
Bitmap bitmap = BitmapFactory.decodeFile(imgPath);
// 对图片进行处理
Bitmap outImg = bitmap.copy(Bitmap.Config.ARGB_8888, true);
Canvas canvas = new Canvas(outImg);
canvas.drawColor(Color.argb(170, 255, 0, 0));
// 【重点】获得输出目录(这里需要时沙盒目录,否则无法使用uni.previewImage预览)
File parentDir = new File(mUniSDKInstance.rewriteUri(Uri.parse("_doc/"), URIAdapter.FILE).getPath());
// 创建输出图片
File outFile = new File(parentDir, "newImg.jpg");
try (FileOutputStream outputStream = new FileOutputStream(outFile)) {
outImg.compress(Bitmap.CompressFormat.JPEG, 80, outputStream);
}
callback.invoke(new HashMap<String, String>() {{
put("resPath", "file://" + outFile.getAbsolutePath());
}});
} catch (Exception e) {
callback.invoke(new HashMap<String, String>() {{
put("error", e.toString());
}});
}
}
uniapp端调用(使用static目录下的一个图片测试)
const handler = uni.requireNativePlugin('img-handle');
const ntvData = {path: '_www/static/inner/office_green_sm.png'};
handler.getNativeImg(ntvData, ({error, resPath}) => {
if(error){
console.error('handle img error:', error);
return;
}
uni.previewImage({
current: 0,
urls:[resPath]
})
});
更多推荐
已为社区贡献6条内容
所有评论(0)