【Flutter 专题】59 图解 Android Native 获取 Flutter 资源文件

举报
阿策小和尚 发表于 2022/02/10 09:02:40 2022/02/10
【摘要】 0 基础学习 Flutter,第五十九步:尝试 Android Native 端获取 Flutter 资源文件!

      小菜前段时间研究了 Android NativeFlutter 之间的交互;若两端均需要相同资源文件,若不能共享则势必会增加整体包大小;今天小菜研究一下如何通过 Android Native 获取 Flutter 中资源文件;

      官网对于 assets 介绍很简洁,使用过程代码量也很少,虽简洁但依然值得研究;小菜以 Android 为主工程,Flutter 作为 Module 进行测试;

FlutterView

      小菜学习 AndroidFlutter 交互时会用到 FlutterView 作为桥接控件;而对于资源文件的获取也同样适用;其核心方法是 getLookupKeyForAsset

源码分析

      逐层分析源码,通过 getLookupKeyForAsset 方法我们可以获取资源文件的路径,根目录是固定的 flutter_assets 而非 Module 名;

public String getLookupKeyForAsset(String asset) {
    return FlutterMain.getLookupKeyForAsset(asset);
}
public static String getLookupKeyForAsset(String asset) {
    return fromFlutterAssets(asset);
}
private static String fromFlutterAssets(String filePath) {
    return sFlutterAssetsDir + File.separator + filePath;
}
private static String sFlutterAssetsDir = "flutter_assets";

案例测试

      小菜通过 getLookupKeyForAsset 获取文件路径,以 images/ic_launcher.png 图片为例,借助 assetManager.open 转为流信息转为 Bitmap 进行展示;

// 文件路径:flutter_assets/images/ic_launcher.png
try {
    AssetManager assetManager = getAssets();
    InputStream is = assetManager.open(flutterView.getLookupKeyForAsset("images/ic_launcher.png"));
    Bitmap bitmap = BitmapFactory.decodeStream(is);
    flutterIv.setImageBitmap(bitmap);
} catch (Exception e) {
    System.out.println("异常信息:" + e.toString());
}

      小菜测试可以用如下方式获取资源文件路径;

// Activity
flutterView.getLookupKeyForAsset("images/ic_launcher.png");
// Fragment
(FlutterView) getView().getLookupKeyForAsset("images/ic_launcher.png");
// 通用
FlutterMain.getLookupKeyForAsset("images/ic_launcher.png");

PluginRegistry.Registrar

      另一种常用的方式是以插件方式,Flutter 在使用 AndroidView 方式嵌入 Native ViewAndroid 进行交互时;核心方法同样是 lookupKeyForAsset 获取资源路径,之后便是用原生方法解析 assets 资源文件;

      小菜测试时主要注意两点:

  1. 获取 PluginRegistry.Registrar,不能直接 new 对象,需要注册自定义 Native View
  2. 在获取文件路径后尝试了 AssetFileDescriptor 方式解析数据流,完全可以用于 assetManager.open 方式解析;
// 文件路径:flutter_assets/images/ic_launcher.png
// Flutter 端
Container(
    child: AndroidView(
        viewType: "com.ace.ace_demo01/method_layout",
        creationParamsCodec: const StandardMessageCodec(),
        creationParams: {'method_layout_size': 450}),
    color: Colors.greenAccent,
    height: 200.0)
    
// Android 端
final String key = "NMethodLayout";
if (this.hasPlugin(key)) return;
PluginRegistry.Registrar registrar = this.registrarFor(key);
registrar.platformViewRegistry()
    .registerViewFactory("com.ace.ace_demo01/method_layout", new NMethodLayoutFactory(registrar.messenger()));

try {
    AssetManager assetManager = registrar.context().getAssets();
    String assetKey = registrar.lookupKeyForAsset("images/ic_launcher.png");
    AssetFileDescriptor fileDescriptor = assetManager.openFd(assetKey);
    Bitmap bitmap = BitmapFactory.decodeStream(fileDescriptor.createInputStream());
    mIv.setImageBitmap(bitmap);
} catch (Exception e) {
    e.printStackTrace();
}

注意事项

      无论是 FlutterView 还是 PluginRegistry.Registrar 方式均需 lookupKeyForAsset 获取 Flutter 端资源文件路径,且获取类型与原生 assets 中一致;小菜测试获取一个 json 文件进行解析;

final String key = "NMethodLayout";
if (this.hasPlugin(key)) return;
PluginRegistry.Registrar registrar = this.registrarFor(key);
registrar.platformViewRegistry()
    .registerViewFactory("com.ace.ace_demo01/method_layout", new NMethodLayoutFactory(registrar.messenger()));

try {
    AssetManager assetManager = registrar.context().getAssets();
    Log.e("===getJson===", getJson(registrar.lookupKeyForAsset("images/star.json")));
} catch (Exception e) {
    e.printStackTrace();
}

public String getJson(String fileName) {
    StringBuilder stringBuilder = new StringBuilder();
    try {
        //获取assets资源管理器
        AssetManager assetManager = getAssets();
        //通过管理器打开文件并读取
        InputStreamReader inputReader = new InputStreamReader( assetManager.open(fileName) );
        BufferedReader bufReader = new BufferedReader(inputReader);
        String line="", result="";
        while((line = bufReader.readLine()) != null)
            result += line;
        return result;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return stringBuilder.toString();
}
// ===getJson===: {  "stars": [    {      "name": "水瓶座",      "name_en": "Aquarius"    },    {      "name": "双鱼座",      "name_en": "Pisces"    },    {      "name": "白羊座",      "name_en": "Aries"    },    {      "name": "金牛座",      "name_en": "Taurus"    },    {      "name": "双子座",      "name_en": "Gemini"    },    {      "name": "巨蟹座",      "name_en": "Cancer"    },    {      "name": "狮子座",      "name_en": "Leo"    },    {      "name": "处女座",      "name_en": "Virgo"    },    {      "name": "天秤座",      "name_en": "Libra"    },    {      "name": "天蝎座",      "name_en": "Scorpio"    },    {      "name": "射手座",      "name_en": "Sagittarius"    },    {      "name": "摩羯座",      "name_en": "Capricorn"    }  ]}


      小菜还未成功尝试 Flutter 获取 Native 的资源文件,依旧是从零探索中;如有错误请多多指导!

来源: 阿策小和尚

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。