Native (iOS and Android) read ReactNative local pictures

The source code has been uploaded to Github: https://github.com/songxiaoliang/native-read-rn-image

In ReactNative the development process, and sometimes need to display RN in the picture in the original Shengduan, so that the benefits can be hot update to update the APP in the picture, without the need to release a native version, but ReactNative in the picture path is relative, similar to './xxximage.png'the In writing, the native end cannot resolve such paths, so what if the RN's picture is passed to the native end?

solution

1. If the picture uses a network picture, it only needs to pass the url string address to the native. This method requires time and the network environment to load the picture. It is not a local picture and is not the best way for this solution.

2. The lazy approach is to generate a base64 string from the RN's local picture and pass it to the native for parsing. If the picture is too large, the string will be quite long, which is also not considered the best solution.

In fact, RN provides related solutions, as follows:

resolveAssetSource()

Image.resolveAssetSource(source);

Resolves an asset reference into an object which has the properties uriwidth, and height.

Parameters:

NAME TYPE REQUIRED DESCRIPTION
source number, object Yes A number (opaque type returned by require('./foo.png')) or an ImageSource.

ImageSource is an object like { uri: '<http location || file path>' }

resolveAssetSource 方法可以将资产引用解析为具有uri,width和height属性的对象。参数为一个数字(由require('。/ foo.png')返回的opaque类型)或 ImageSource。

The sample code is as follows:

    const myImage = require('./Images/icon_splash.jpg');
    const resolveAssetSource = require('react-native/Libraries/Image/resolveAssetSource');
    const resolvedImage = resolveAssetSource(myImage);
    console.log(resolvedImage);

The print result of resolveImage is as follows:

can be seen,resolveAssetSource 方法不仅返回了图片到宽高,还有Uri及scale属性值。

上图中,Uri的值为 http:// 开头的链接,这就涉及到RN对于Uri的定义规则:

(1)开发者模式下,图片会由Package Server 本地服务器加载,Uri会返http的本地链接。

(2)发布模式下,图片已经被打包到原生目录下,例如Android端res下的drawable资源目录

So we can get the picture resources defined in rn through Uri on the native side.

Android side

/**
     *  release模式下 uri为图片名称,例如, 在rn项目的Images目录下有张icon_splash名称的图片
     *  那么 uri 为 images_icon_splash
     *  开发者模式下,图片格式为package server 地址,例如: http: // 192.xxx
     * @param params
     */
    @ReactMethod
    public void showRNImage(ReadableMap params) {
        String rnImageUri;
        try {
            rnImageUri = params.getString("uri");
            Log.i("showRNImage", "uri : " + rnImageUri);
            BitmapUtil.loadImage(rnImageUri);
        } catch (Exception e) {
            return;
        }
    }

The loadImage method receives Uri parameters. Look at how the loadImage method is implemented:

    public static Drawable loadImage(String iconUri) {
        if (TextUtils.isEmpty(iconUri)) {
            return null;
        }
        Log.e("BitmapUtil", "isDebug: " + MainApplication.instance.isDebug());
        if (MainApplication.instance.isDebug()) {
            return JsDevImageLoader.loadIcon(iconUri);
        } else {
            Uri uri = Uri.parse(iconUri);
            if (isLocalFile(uri)) {
                // 本地文件
                return loadFile(uri);
            } else {
                return loadResource(iconUri);
            }
        }
    }

First of all, we judge whether it is the developer mode, if it is, then execute the loadIcon method to load directly from the local directory. Otherwise, load from the local directory of the mobile phone or according to the resource ID.

In development mode, Uri is in link mode, so we can get it by streaming

    @NonNull
    private static Drawable tryLoadIcon(String iconDevUri) throws IOException {
        URL url = new URL(iconDevUri);
        Bitmap bitmap = BitmapFactory.decodeStream(url.openStream());
        BitmapDrawable bitmapDrawable = new BitmapDrawable(MainApplication.instance.getResources(), bitmap);
        Log.e("JsDevImageLoader", "bitmap drawable width:" + bitmapDrawable.getIntrinsicWidth());
        return bitmapDrawable;
    }

The release mode is as follows:

    /**
     * 加载手机本地目录图片
     * @param uri
     * @return
     */
    private static Drawable loadFile(Uri uri) {
        Bitmap bitmap = BitmapFactory.decodeFile(uri.getPath());
        return new BitmapDrawable(MainApplication.instance.getResources(), bitmap);
    }

    /**
     * 加载drawable目录下的图片
     * @param iconUri
     * @return
     */
    private static Drawable loadResource(String iconUri) {
        return ResourceDrawableIdHelper
                .instance
                .getResourceDrawable(MainApplication.instance, iconUri);
    }

iOS edge

The iOS side is much simpler than Android, and only needs to be directly parsed into a UIImage:

#import <React/RCTConvert.h>

RCT_EXPORT_METHOD(showRNImage:(id)rnImageData){
    dispatch_async(dispatch_get_main_queue(), ^{
    UIImage *rnImage = [RCTConvert UIImage:rnImageData];
    ...
    });
}

to sum up

Reading the RN picture on the native side, whether it is hybrid development or pure RN development, involves many usage scenarios. For example, dynamically update Splash. So mastering this skill will help us make better applications.

Published 214 original articles · praised 371 · 920,000 views

Guess you like

Origin blog.csdn.net/u013718120/article/details/90522127
Recommended