背景

自己开发的安卓原生插件,会返回安卓绝对路径形式的图片,如: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预览的话,必须要创建在上面的目录(或子目录)下。
知道了问题,解决方法也就有了:

  1. 原生插件里面维护了个静态变量,用来记录uniapp的缓存目录。
  2. 原生插件提供一个设置存储缓存目录的静态变量值的方法供uniapp调用。
  3. 在App.vue启动时,调用plus.io.requestFileSystem(plus.io.PRIVATE_DOC获得缓存路径后,调用原生插件方法更新
  4. 原生插件在返回图片时,创建到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]  
                    })  
                });
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐