热更新-Android与Lua相互通信

http://blog.csdn.net/elsdnwn/article/details/48651585

热更新介绍

  • 什么是热更新?

客户端启动时,主动请求服务端检查版本号,并更新资源到本地。

  • 应用场景:
  • 情况一:客户端已经发布了,但突然发现有个比较严重的bug需要修复。这时需要更新客户端的代码(Lua代码)。
  • 情况二:情人节到了,需要搞个活动,在客户端中营造一个节日氛围。这时,需要更新客户端资源或增加一些功能。
  • 好处:

不需要重新打包和提交应用到市场等待审核。

Android与Lua相互通信

参考资料:

1. 在Android项目中使用Lua,需要两个步骤:

  1. 加载Lua脚本解析引擎
  2. 以Native API方式调用引擎接口

直接以JNI方式调用Lua解析引擎的接口十分麻烦,开源项目LuaJava(https://github.com/mkottman/AndroLua )对这些JNI接口进行了很好的封装,它是一个包含了LuaJava的Android平台的Lua解析器,它提供一系列映射到Lua C实现函数的Java接口。

2. 需注意的地方:

  • .lua文件可存放在assets、raw文件夹;
  • 提供给lua的回调必须是public,否则lua调不到;
  • “.”是用来调用类的方法或变量(静态方法),而“:”是用来调用对象的方法。

3. 在Lua中调用Java类:

  • newInstance(className, …) // 可以根据类名创建一个Java类,同时返回一个lua变量与Java类对应
<code class="hljs lua has-numbering"><span class="hljs-comment">-- 启动手机设置</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">launchSetting</span><span class="hljs-params">(context)</span></span>
  <span class="hljs-comment">-- 得到Intent类的实例</span>
  intent = luajava.newInstance(<span class="hljs-string">"android.content.Intent"</span>)
  c = luajava.newInstance(<span class="hljs-string">"android.content.ComponentName"</span>,<span class="hljs-string">"com.android.settings"</span>, <span class="hljs-string">"com.android.settings.Settings"</span>)
  <span class="hljs-comment">-- intent:用来调用对象的方法 </span>
  <span class="hljs-comment">-- intent.用来调用类的方法或变量(静态方法)</span>
  intent:setFlags(intent.FLAG_ACTIVITY_NEW_TASK);
  intent:setComponent(c)
  context:startActivity(intent)
<span class="hljs-keyword">end</span></code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li></ul>
  • bindClass(className) // 可以让lua中的变量对应一个Java的类(是类,不是实例),这样就可以用lua的这个变量创建实例以及调用静态类
<code class="hljs lua has-numbering"><span class="hljs-built_in">require</span> <span class="hljs-string">'import'</span>
button_cb = {}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">button_cb.onClick</span><span class="hljs-params">(ev)</span></span>
  <span class="hljs-built_in">print</span>(<span class="hljs-string">'hello,world'</span>)
  launchSetting(activity)
<span class="hljs-keyword">end</span>
<span class="hljs-comment">--[=[ 因为id是R.java里的一个静态类,所以引用Button的资源文件用下面的代码:
   id.launchButton,而不是id:launchButton ]=]</span>
<span class="hljs-keyword">local</span> id = luajava.bindClass(<span class="hljs-string">"sk.kottman.androlua.R$id"</span>)
<span class="hljs-keyword">local</span> launch = activity:findViewById(id.launchButton)
<span class="hljs-comment">-- 另外,注意类中类的引用方法,如:android.view.View$OnClickListener</span>
buttonProxy = luajava.createProxy(<span class="hljs-string">"android.view.View$OnClickListener"</span>, button_cb)
launch:setOnClickListener(buttonProxy)</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li></ul>

4. 在java中调用Lua:

  1. LuaState mLuaState = LuaStateFactory.newLuaState(); // Lua解析和执行由此对象完成
  2. mLuaState.openLibs();
  3. 调用Lua脚本语句:
<code class="hljs cs has-numbering"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">executeLuaStatemanet</span>() {
    mLuaState.LdoString(<span class="hljs-string">" varSay = 'call from android : This is string in lua script statement.'"</span>);<span class="hljs-comment">// 定义一个Lua变量</span>
    mLuaState.getGlobal(<span class="hljs-string">"varSay"</span>);<span class="hljs-comment">// 获取</span>
    displayResult1.setText(mLuaState.toString(-<span class="hljs-number">1</span>));<span class="hljs-comment">// 输出</span>
}</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li></ul>

4.调用Lua脚本文件:

<code class="hljs avrasm has-numbering">private void executeLuaFile() {
    mLuaState<span class="hljs-preprocessor">.LdoString</span>(readStream(getResources()<span class="hljs-preprocessor">.openRawResource</span>(R<span class="hljs-preprocessor">.raw</span><span class="hljs-preprocessor">.luafile</span>)))<span class="hljs-comment">;</span>
    mLuaState<span class="hljs-preprocessor">.getField</span>(LuaState<span class="hljs-preprocessor">.LUA</span>_GLOBALSINDEX, <span class="hljs-string">"functionInLuaFile"</span>)<span class="hljs-comment">;// 找到functionInLuaFile函数</span>
    mLuaState<span class="hljs-preprocessor">.pushString</span>(<span class="hljs-string">"从Java中传递的参数"</span>)<span class="hljs-comment">;// 将参数压入栈</span>
    // functionInLuaFile函数有一个参数,一个返回结果
    int paramCount = <span class="hljs-number">1</span><span class="hljs-comment">;</span>
    int resultCount = <span class="hljs-number">1</span><span class="hljs-comment">;</span>
    mLuaState<span class="hljs-preprocessor">.call</span>(paramCount, resultCount)<span class="hljs-comment">;</span>
    mLuaState<span class="hljs-preprocessor">.setField</span>(LuaState<span class="hljs-preprocessor">.LUA</span>_GLOBALSINDEX, <span class="hljs-string">"resultKey"</span>)<span class="hljs-comment">;// 将结果保存到resultKey中</span>
    mLuaState<span class="hljs-preprocessor">.getGlobal</span>(<span class="hljs-string">"resultKey"</span>)<span class="hljs-comment">;// 获取</span>
    displayResult2<span class="hljs-preprocessor">.setText</span>(mLuaState<span class="hljs-preprocessor">.toString</span>(-<span class="hljs-number">1</span>))<span class="hljs-comment">;// 输出</span>
}</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li></ul>

5.调用android API:

<code class="hljs avrasm has-numbering">private void callAndroidAPI() {
    mLuaState<span class="hljs-preprocessor">.LdoString</span>(readStream(getResources()<span class="hljs-preprocessor">.openRawResource</span>(R<span class="hljs-preprocessor">.raw</span><span class="hljs-preprocessor">.luafile</span>)))<span class="hljs-comment">;</span>
    mLuaState<span class="hljs-preprocessor">.getField</span>(LuaState<span class="hljs-preprocessor">.LUA</span>_GLOBALSINDEX, <span class="hljs-string">"callAndroidApi"</span>)<span class="hljs-comment">;// 找到callAndroidApi函数</span>
    mLuaState<span class="hljs-preprocessor">.pushJavaObject</span>(getApplicationContext())<span class="hljs-comment">; // 上下文</span>
    mLuaState<span class="hljs-preprocessor">.pushJavaObject</span>(mLayout)<span class="hljs-comment">; // 布局</span>
    mLuaState<span class="hljs-preprocessor">.pushString</span>(<span class="hljs-string">"lua call android Textview的setText()方法, 内容是:"</span> + (++count))<span class="hljs-comment">; // 内容</span>
    mLuaState<span class="hljs-preprocessor">.call</span>(<span class="hljs-number">3</span>, <span class="hljs-number">0</span>)<span class="hljs-comment">; // callAndroidApi函数需要传递3个参数,0个返回值</span>
}</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li></ul>

6.raw文件目录下luafile.lua代码:

<code class="hljs lua has-numbering"><span class="hljs-comment">-- 调用Lua脚本文件</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">functionInLuaFile</span><span class="hljs-params">(key)</span></span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">'call from android: I am in Lua file . Return : '</span>..key..<span class="hljs-string">'!'</span>
<span class="hljs-keyword">end</span>

<span class="hljs-comment">-- 调用android API</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">callAndroidApi</span><span class="hljs-params">(context,layout,tip)</span></span>
    tv = luajava.newInstance(<span class="hljs-string">"android.widget.TextView"</span>,context)
    tv:setText(tip)
    layout:addView(tv)
<span class="hljs-keyword">end</span></code>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值