您的位置:首页 > 编程语言 > Lua

热更新-Android与Lua相互通信

2016-01-06 16:56 465 查看
http://blog.csdn.net/elsdnwn/article/details/48651585

热更新介绍

什么是热更新?

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

应用场景:

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

好处:

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

Android与Lua相互通信

参考资料:

Lua 5.1 在线参考手册
开源项目LuaJava

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

加载Lua脚本解析引擎
以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:

LuaState mLuaState = LuaStateFactory.newLuaState(); // Lua解析和执行由此对象完成
mLuaState.openLibs();
调用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>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: