摘要
在使用 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}` 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) { 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(); 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~~
微信公众号
