小程序基础库与Android之间通信优化的可能

这篇具有很好参考价值的文章主要介绍了小程序基础库与Android之间通信优化的可能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

最近在学习graalvm,发现有一个graaljs项目,项目中介绍可以让java与JavaScript做数据转换,比如JavaScript中可以使用java的数据类型与结构。突然想到之前遇到的一个问题,小程序中开发的代码和基础库的部分代码都是j2v8来执行的,其中的数据通信是通过bridge去做的,其实就是把数据结构都转换为字符串,这样就存在问题,比如Android这边的网络请求、音视频帧数据、文件流对外都是通过java封装的对象,无法直接在JavaScript中使用,只能是通过转换为base64来做,而且一个buffer数据基本需要两次转换,sdk转一次,基础库转一次,比较消耗性能。

如果JavaScript和java之间的结构互通,那是不是就解决这个问题了,理论上来说如果js引擎是通过java编写的解释器去执行,那确实是可以这样的。

GraalJs

GraalJs核心代码如下:

BufferedReader br = null;
try {
    br = new BufferedReader(new FileReader("/Users/xxx/tmp/index.md"));
} catch (FileNotFoundException e) {
    throw new RuntimeException(e);
}
try (Context context = Context.newBuilder().allowAllAccess(true).build()) {
    Set<String> languages = context.getEngine().getLanguages().keySet();
    for (String id : languages) {
        context.initialize(id);
        if (id.equals("js")) {
            context.eval("js", "function main(data) { console.log(data.readLine()); }");
            Value funMain = context.getBindings("js").getMember("main");
            funMain.execute(br);
        }
    }
}

这里我们使用GraalVM的jdk是可以运行的,可以看到JavaScript中接收到的data其实是java的BufferedReader,执行之后就发现JavaScript中的data.readLine成功执行并打印了文件内容,WC,如果Android可以这样那就太强了。可惜,GraalJs必须使用GraalVM提供的jdk,也不好直接替换android中使用的jdk。。。
那有没有其他办法?对了,GraalVM是可以将java代码生成分享库的,比如.so,Android也正好可以加载so库。有没有可能这样搞。最终项目如下https://github.com/schizobulia/GraalJs-Android ,可以看到releases中tag为v0.0.8中有arrch64和armv7的so库
小程序基础库与Android之间通信优化的可能,小程序,android
可惜拿到so库之后去Android中使用发现,这个so库不是ABI。麻了…
然后查了相关资料发现GraalVM目前也没有计划支持Android。

不过好在最后发现ChatGPT确实是个好东西,现在查资料基本都是先问问ChatGPT,上面项目中的GitHub Action配置文件也是ChatGPT写的。

参考资料:
Android 关于CPU类型的so文件兼容问题(ABI) - 掘金
一分钟搞明白Android的.so文件、ABI和CPU的关系-CSDN博客

J2V8

那有没有可能从j2v8入手,比如node很多内置函数其实在v8中也是没有的,如果可以在v8中实现这些函数然后提供给JavaScript调用好像有可以,然后开始查node这部分功能的实现原理,最后看到一篇博客:Node.js的底层原理 - 掘金其中说到这个部分的实现是V8的自定义拓展实现的,好像确实可以。不过后来试了试,发现还是不行。

主要原因有:比如文件流、帧数据在Android端对外都是通过java封装的对象,v8的自定义扩展需要c++或者v8提供的语言来编写,依然存在语言之间数据结构转换的问题。

次要原因:实在不想看c++的代码

Rhino

然后通过ChatGPT最终选择试试Rhino,因为他也是java写的,缺点是性能可能没没v8那么强,JavaScript中新的语法糖或者全局属性可能没那么快支持到(不过可以使用一些打包库和第三方静态分析库去优化)。
小程序中存在大量的数据交互,如果使用Rhino说不定会有更好的效果,以下为示例代码,可以看到JavaScript中可以使用java的数据结构,这得益于解释器是使用java写的,节省了不同语言之间数据结构的转换。

var System = java.lang.System;
System.out.println(myClass.add(1, 2));
function test(str) {
    myClass.show(str);
}

通过下面代码的测试,发现读取一个53kb的文件从调用test方法到show方法的触发基本没消耗时间。而且根据这种方式其实也很节省内存,因为数据其实只保存在了jvm中,按j2v8的思路同一份数据需要在v8、jvm中各保存一份。
以下为完整代码:

package com.example.myapplication

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.myapplication.ui.theme.MyApplicationTheme
import org.mozilla.javascript.Context
import org.mozilla.javascript.Function
import org.mozilla.javascript.Scriptable
import org.mozilla.javascript.ScriptableObject
import java.nio.ByteBuffer
import java.nio.CharBuffer
import java.nio.charset.Charset


class MainActivity : ComponentActivity() {
    class MyFunctions {
        fun add(a: Int, b: Int): Int {
            return a + b
        }

        fun show(buffer: ByteArray) {
            println("这是js传递过来的:")
            println(System.currentTimeMillis())
            println(buffer)
//            val text = String(buffer)
//            println("File Content: $text")
        }
    }
    class JsEngine {
        public val rhino: Context = Context.enter()
        public val scope: Scriptable

        init {
            rhino.optimizationLevel = -1
            scope = rhino.initStandardObjects()

        }

        fun evaluate(jsCode: String) {
            try {
                ScriptableObject.putProperty(scope,"myClass", Context.javaToJS(MyFunctions(), scope))
                ScriptableObject.putProperty(scope, "javaContext", Context.javaToJS(this, scope))
                ScriptableObject.putProperty(scope, "javaLoader", Context.javaToJS(JsEngine::class.java.classLoader, scope))
                rhino.evaluateString(scope, jsCode, JsEngine::class.java.simpleName, 1, null)
            } finally {
//                Context.exit()
            }
        }

        fun callFunction(functionName: String, vararg args: Any): Any? {
            try {
                val function = scope[functionName, scope] as Function
                return function.call(rhino, scope, scope, args)
            } finally {
//                Context.exit()
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MyApplicationTheme {
                // A surface container using the 'background' color from the theme
                Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
                    Greeting("Android")
                }
            }
        }

        val inputStream = resources.assets.open("data.txt");
        val size = inputStream.available()
        val buffer = ByteArray(size)
        inputStream.read(buffer)
        inputStream.close()
        Thread {
            val jsCode = """
            var System = java.lang.System;
            System.out.println(myClass.add(1, 2));
            function test(str) {
                myClass.show(str);
            }
                """.trimIndent()
            val jsEngine = JsEngine()
            jsEngine.evaluate(jsCode)
            println(System.currentTimeMillis())
            jsEngine.callFunction("test", buffer)
        }.start()
    }
}

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(
            text = "Hello $name!",
            modifier = modifier
    )
}

@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    MyApplicationTheme {
        Greeting("Android")
    }
}

最后:ChatGPT真👍🏻文章来源地址https://www.toymoban.com/news/detail-802010.html

到了这里,关于小程序基础库与Android之间通信优化的可能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • android开发实战经典,设计思想与代码质量优化+程序性能优化+开发效率优化

    android开发实战经典,设计思想与代码质量优化+程序性能优化+开发效率优化

    一、关于Handler面试那些问题 1、Handler Looper Message 关系是什么? 2、Messagequeue 的数据结构是什么?为什么要用这个数 据结构? 3、如何在子线程中创建 Handler? 4、Handler post 方法原理? 5、Android 消息机制的原理及源码解析 6、Android Handler 消息机制 7、Android 消息机制 … 二、关于

    2024年03月11日
    浏览(49)
  • 小程序FMP优化实录,android面试必看书籍

    小程序FMP优化实录,android面试必看书籍

    一面 面试官:先介绍一下自己吧,做过哪些项目,掌握哪些技能 我内心:(简历都有写的,你自己不会看么?只好照着简历里写的说了一遍) 熟悉Android Framework,组件化开发及MVC/MVP/MVVM程序设计框架;熟悉UI/ NDK开发,掌握TCP/IP,HTTP网络通信机制,有OkHttp使用包装经验,熟悉

    2024年03月23日
    浏览(8)
  • Android核心知识点,小程序FMP优化实录

    Android核心知识点,小程序FMP优化实录

    面试问题还记得一些,一部分已经忘记了,为了防止再忘记,所以写出来。 1:你是如何理解Android操作系统的。 2:是否熟悉framework层,如果熟悉,那就对framework做个简介。 3:是否熟悉多线程,如果熟悉,介绍下线程。 4:对象锁和类锁是否会互相影响,会举例子让你判断锁

    2024年04月11日
    浏览(11)
  • Android修行手册-基础优化系列图片篇,ios音视频面试内容

    Android修行手册-基础优化系列图片篇,ios音视频面试内容

    图片款=(480/480)*400=400 占用内存为300*400*4=480000 那么它占用内存为什么是变化的? Android会先解析图片文件本身的数据格式,然后还原成Bitmap对象,Bitmap的大小就跟上面的计算方式相关联。 再举例1080*452的png图片,图片占用存储空间大小为56kb,内存如图: 上图一目了然,不

    2024年04月27日
    浏览(19)
  • Android 打包可能遇到的报错

    Android 打包可能遇到的报错

    问题一:com.android.ide.common.signing.KeytoolException: Failed to read key testxlk from store “E:AndroidAndroid Keystestkey.jks”: Invalid keystore format 升高gradle JDK版本,我这里用了JDK11 问题二:Integrity check failed: java.security.NoSuchAlgorithmException: Algorithm HmacPBESHA256 not available 在解决问题一时升级到JDK1

    2024年04月11日
    浏览(16)
  • Android开发基础4:事件处理和交互实现程序设计

    Android开发基础4:事件处理和交互实现程序设计

    应用前提:Android开发中,事件是用户对图形界面的操作,Android应用程序通过事件和信息来实现人机交互。 事件 包括:按下、弹起、滑动、双击。 信息 包括:信息框、对话框、通知。 本节学习和Android中与事件处理和交互相关的组件及知识。 每个工程下面的模块必须做的工

    2023年04月24日
    浏览(12)
  • Android 使用modbus协议与可能遇到的问题解决一览

    本篇文章主要演示android的串口通讯功能,其中需要使用serialport模块(下载链接),注意: 串口通讯需要root权限,需要将应用设置成‘android:sharedUserId=“android.uid.system”’即可,如果出现串口通讯无法访问设备,首先看串口名称与波特率是否一致,如果都一致看看是否是打开串口

    2024年02月14日
    浏览(14)
  • 探析STM32标准库与HAL库之间的差异与优劣

    探析STM32标准库与HAL库之间的差异与优劣

    引言: 在嵌入式开发领域,STMicroelectronics的STM32系列芯片广受欢迎。STM32提供了两种主要的软件库,即标准库和HAL库,用于开发各种应用。本文将探讨这两种库之间的差异,比较它们的优劣,并分析在选择库时需要考虑的因素。   正文: STM32标准库: STM32标准库是STMicroelect

    2024年02月13日
    浏览(7)
  • 可能会解决你Android studio中gradle安装的问题

    可能会解决你Android studio中gradle安装的问题

    我的电脑让我不小心弄出了很多小毛病,我忍不了了,重装了系统 然后在我配置as时发现gradle竟然出现了好多问题,看了好多的帖子发现都对我没用!!! 概括 问题是下载gradle超时 检查是否有.gradle这个文件,有则改名,没有的话就先下载,看报不报错,报错了就看下一步(

    2024年02月03日
    浏览(10)
  • Android TelephonyManager双卡获取数据开启状态异常的可能原因

    Android TelephonyManager双卡获取数据开启状态异常的可能原因

    背景 应用内不指定subId获取数据状态可能会错误,因为可能拿到voice的能力,而非data。 代码逻辑 1、通过TelephonyManager的isDataEnabled()没有指定subId时,调用内部方法isDataEnabledForReason,传入getId()参数以指定subid,然后会执行到SubscriptionManager的getDefaultDataSubscriptionId()以获取默认值

    2024年02月15日
    浏览(9)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包