CocosCreator之KUOKUO带你搞反射-jsb读取相册图片

摘要

在使用 CocosCreator 打包的原生应用中,我们可以通过引擎封装好的反射机制调用 Java 的静态方法,从而实现提示、相册、支付跳转等功能。本次内容为利用 jsb 读取相册图片。

正文

先看效果

版本说明
  • CocosCreator 为 2.2.1 版本。
  • AndroidStudio 为 3.5.2 版本。
  • JDK 为 13 版本。(具体:13.0.1)
  • NDK 为 20 版本。(具体:20.1.5948944)
  • SDK 安装了 API 23 的。
  • 模拟器为 AVD。(可以在 AndroidStudio 内安装)
布局与脚本

在 CocosCreator 中布局好一个按钮、一个文本和一个用于显示图片的精灵,在脚本中写个方法并绑定至按钮,如图。

脚本

const UPNG = require("upng-js")
const UJPG = require("jpeg-js")

cc.Class({
    extends: cc.Component,

    properties: {
        label: cc.Label,
        sprite: cc.Sprite
    },

    onLoad () {
        cc.showImg = (path, w, h) => {
            // 用于显示信息
            this.label.string = `宽:${w}高:${h}路径:${path}`
            // 给数据传递留点时间,100ms即可
            setTimeout (() => {
                const width = parseInt(w)
                const height = parseInt(h)
                const data = jsb.fileUtils.getDataFromFile(path)
                let buffer = null
                // 这里简单处理了,应该判断末尾
                if (path.includes("png")) {
                    const img = UPNG.decode(data)
                    buffer = UPNG.toRGBA8(img)[0]
                } else {
                    buffer = UJPG.decode(data).data
                }
                const array = new Uint8Array(buffer)
                const tex = new cc.Texture2D()
                tex.initWithData(array, cc.Texture2D.PixelFormat.RGBA8888, width, height)
                this.sprite.spriteFrame = new cc.SpriteFrame(tex)
            }, 100)
        }
    },

    getImgData () {
        const className = "org/cocos2dx/javascript/AppActivity"
        jsb.reflection.callStaticMethod(className, "getImgData", "()V")
    }

});

其中的 getImgData 就是绑定至按钮的方法。upng-js 库与 jpeg-js 库可直接 npm 下载,给出指令:

npm install upng-js
npm install jpeg-js

这两个库封装好了方法,我们可以直接使用,因为 jsb.fileUtils.getDataFromFile(path) 返回的数据不是像素信息,而是格式化后的,需要解码,这两个一个是 jpg 格式解码库,一个是 png 格式解码库。

Java写法

构建后找到 Java 文件 “/app/src/org/cocos2dx/javascript/AppActivity.java”,然后我们添加对应的静态方法:(关于 AndroidStudio 如何调起相册,网上很多,就不详解了。)

public static void getImgData () {
    Intent intent_album = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    app.startActivityForResult(intent_album, 2);
}

这样就完成了调起相册。然后接下来我们要往下翻找到一下代码:

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // ......
    }

上面的方法会在你选择好图片后进行回调,我们处理返回的 data 即可!如下全部代码:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    SDKWrapper.getInstance().onActivityResult(requestCode, resultCode, data);
    if (data != null) {
        // 得到图片的全路径写法,可以copy
        Uri uri = data.getData();
        String[] filePathColumns = { MediaStore.Images.Media.DATA };
        Cursor c = getContentResolver().query(uri, filePathColumns, null, null, null);
        c.moveToFirst();
        int columnIndex = c.getColumnIndex(filePathColumns[0]);
        String imagePath = c.getString(columnIndex);
        // 获取后显示下图片路径
        Toast.makeText(app, imagePath, Toast.LENGTH_LONG).show();
        // 根据路径读取图片来获取下图片宽高
        Bitmap srcBmp = BitmapFactory.decodeFile(imagePath);
        int w = srcBmp.getWidth();
        int h = srcBmp.getHeight();
        // 拼接执行语句 cc.showImg("imagePath", "w", "h")
        StringBuilder evalString = new StringBuilder();
        evalString.append("cc.showImg(\"");
        evalString.append(imagePath);
        evalString.append("\",\"");
        evalString.append(w);
        evalString.append("\",\"");
        evalString.append(h);
        evalString.append("\")");
        app.runOnGLThread(new Runnable() {
            @Override
            public void run() {
                Cocos2dxJavascriptJavaBridge.evalString(evalString.toString());
            }
        });
    }
}

需要注意的是,在执行 Cocos2dxJavascriptJavaBridge.evalString 时要在 GL 线程中,而且其中变量要用 “\”” 这种写法包上。

权限获取

在高版本的安卓机器上现在都是动态的权限获取,我们这个实现要求存储权限(读写),我们要先在 AndroidManifest.xml 加入两条权限:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

然后在代码中,动态获取一下,我写在了初始化中,如图:

这样如果开始没权限,会弹出授权选项。(闪退就是没权限,再不图片过大!)

真机测试

结语

有意思吧,我们下一次做个电量管理软件!
O(∩_∩)O~~

微信公众号

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

KUOKUO众享

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值