背景
自己开发的安卓原生插件,会返回安卓绝对路径形式的图片,如:file:///data/user/0/com.sample.test/cache/20220316.jpg
这是在应用的cache目录下直接写入的图片。
返回到uniapp端后,在template中通过<image>组件能正常显示图片。但通过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沙盒目录下的文件,即 只支持下面的目录和子目录下的图片预览:
- PRIVATE_WWW 对应相对路径URL为"_www"开头的地址
- PRIVATE_DOC 对应相对路径URL为"_doc"开头的地址
- PUBLIC_DOCUMENTS 对应相对路径URL为"_documents"开头的地址
- PUBLIC_DOWNLOADS 对应相对路径URL为"_downloads"开头的地址
所以原生插件生成图片时,将图片写入上面任意一个目录下即可。
以“_doc”为例,获取绝对路径可通过下面方式:
File parentDir = new File(mUniSDKInstance.rewriteUri(Uri.parse("_doc/"), URIAdapter.FILE).getPath());
成功!
完整代码
原生安卓端
注意需要在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]
})
});