为了账号安全,请及时绑定邮箱和手机立即绑定

Flutter 59: 图解 Android Native 获取 Flutter 资源文件

标签:
Android

      小菜前段时间研究了 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 的资源文件,依旧是从零探索中;如有错误请多多指导!

来源: 阿策小和尚

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
移动开发工程师
手记
粉丝
165
获赞与收藏
165

关注作者,订阅最新文章

阅读免费教程

  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消