前言 
也是androlua入门教程?
这里用到一个框架https://github.com/nirenr/AndroLua_pro
作者是:泥人(nirenr谐音,圈子里的叫法)
当然这个项目已经非常久没有更新了
所有需要用到一些社区的编辑器,比如
- OpenLuaX+(https://github.com/znzsofficial/OpenLuaX_Open-Source,已停更),
 - NeLuaJ+(https://github.com/znzsofficial/NeLuaJ),
 - AndLua+(如开源,一般用来写外挂绘制,已停更),
 - Fusionapp2(一个木寒开发者开发,用于网页打包app,不开源,已停更),
 - Aide Lua(https://github.com/AideLua/AideLua)
 
这里推荐用NeLuaJ+,拥有比较新的依赖库(支持Material Design 3)
简单介绍一下开发流程
- 起名,包括包名,应用名称
 - 写布局
 - 写业务逻辑
 - 调试(具体来说应该边写边调)
 - 打包
 
第一个app 
0.下载相关软件 
- 推荐一下代码手册,可以发布代码,实时运行,(别忘了关注一下我awa
 
1.创建项目 
这里拿NeLuaj+来写
首先点积右上角…→项目→创建项目
输入软件名称和包名,模块目前不用选。
来到项目目录,点左上角三个横,详情如图↓

以及res目录详情,
 我们先回到main.lua
看到它的代码
import "java.lang.*","java.util.*" --导入库
import "android.os.*","android.app.*" 
activity {  --当前界面
  Title = res.string.app_title,  --标题
  ContentView = res.layout.main  --布局
}显然不是标准的lua语法,这是因为androlua有自己的语法糖,适应一下就好。
我们来写一个base64编码app
2.布局 
首先需要写一个布局,输入框,按钮,输出的文字等
来到res/layout/main.lua,可以看到return后的一个表(lua中万能的类型),俗称布局表,
return {  
  LinearLayout,  --线性布局
  orientation="vertical",  --竖向排列
  layout_width="match",  --宽度最大
  layout_height="match",  --高度最大
  gravity="center",  --子空间居中
  {
    AppCompatTextView, --文本控件
    text="Hello NeLuaJ+", --文字
   },
 }是不是非常好理解,其实和xml布局非常类似,但是lua中写法精简,可以提升效率。
这了我们要写一个输入框,2个按钮(编码和解码),一个输出文字框。
这了简单写了一下。
return {
  LinearLayout,
  orientation="vertical",
  layout_width="match",
  layout_height="match",
  gravity="center",
  {
    EditText,--编辑框
    hint="请输入要base64编码的文本",--提示文字
    id="编辑框",--这了的id是唯一的,在后续可以通过id访问控件
  },
  {Button,--按钮
    text="编码",
    id="编码",--为了方便理解,用了中文,虽然androlua支持中文函数,但是还是建议自己开发时用英文命名
  },
  {Button,
    text="解码",
    id="解码",
  },
  {TextView,--文本
    text="输出内容",
    id="输出文本",
    textIsSelectable=true,--这了让我们的文字可以被选中复制
  },
}然后点击右上角三角,运行项目,即可看到效果。

ok!布局搞定啦
3.业务逻辑 
回到我们/main.lua,在最下面开始写处理编码的功能
function Base64编码(data)
  local Base64=luajava.bindClass("android.util.Base64")
  return Base64.encodeToString(String(data).getBytes(),Base64.NO_WRAP);
end
function Base64解码(data)
  local Base64=luajava.bindClass("android.util.Base64")
  return String(Base64.decode(data,Base64.DEFAULT)).toString()
end
编码.onClick=function()--调用编码按钮的点击事件,
  输出文本.setText(Base64编码(输入框.text))
  --这了应该比较好理解,.text就是获取文本,setText就是设置文本
  --语法糖也可以这样写↓
  --输出文本.text=Base64编码(输入框.text)
end
--[[当然点击函数也可以这样写↓
function 编码.onClick()
end
]]
解码.onClick=function(_)--这了函数会接收到他自己的类,这里用不到
  输出文本.text=Base64解码(输入框.text)
end这样你的app也就基本完成了✅
美化 
这部分其实可有可无,但是如果你喜欢设计漂亮的app界面也可以看一下,可能涉及很多控件等,不会一一解释。
1.主题
首先来到init.lua,看到NeLuaJ_Theme 把值改成"Theme_NeLuaJ_Material3",一个md3主题
2.顶栏
在main.lua加
activity.getSupportActionBar().hide()
--隐藏默认顶栏3.适配全屏
if Build.VERSION.SDK_INT >= 21 then
  window = activity.getWindow()
  window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
  window.setStatusBarColor(Color.TRANSPARENT);
  window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
  window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
 else
  window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
end4.爆改布局
如下/res/layout/main.lua
import "android.widget.*", "androidx.appcompat.widget.*";
import "android.widget.EditText"
import "androidx.core.widget.NestedScrollView"
import "android.widget.LinearLayout"
import "android.widget.Button"
import "android.widget.TextView"
import "com.google.android.material.appbar.AppBarLayout"
import "androidx.coordinatorlayout.widget.CoordinatorLayout"
import "com.google.android.material.appbar.MaterialToolbar"
import "android.os.Build"
import "android.view.WindowManager"
import "android.graphics.Color"
import "com.google.android.material.button.MaterialButton"
import "com.google.android.material.textview.MaterialTextView"
import "android.view.View"
import "com.google.android.material.card.MaterialCardView"
R=import "com.google.android.material.R"
if Build.VERSION.SDK_INT >= 21 then
  window = activity.getWindow()
  window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
  window.setStatusBarColor(Color.TRANSPARENT);
  window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
  window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION)
 else
  window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
  window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
end
function 状态栏高度()
  if Build.VERSION.SDK_INT >= 19 then
    resourceId = activity.getResources().getIdentifier("status_bar_height", "dimen", "android")
    return activity.getResources().getDimensionPixelSize(resourceId)
   else
    return 0
  end
end
return {CoordinatorLayout;
  layout_width=-1;
  layout_height=-1;
  {
    AppBarLayout,
    layout_width="fill",
    layout_height="130dp",
    liftOnScroll="false",
    {
      MaterialToolbar,
      layout_scrollFlags="noScroll",
      title="Base64",
      layout_marginTop=状态栏高度(),
      id="toolbar",
      layout_width="fill",
      layout_height="56dp",
    },
  },
  {
    LinearLayout,
    orientation="vertical",
    layout_width="fill",
    layout_height="match",
    gravity="center",
    layout_marginTop="-120dp",
    layout_behavior="@string/appbar_scrolling_view_behavior",
    {MaterialCardView,
      id="edit卡片",
      layout_height="wrap",
      layout_width="wrap";
      layout_marginTop="20dp",
      layout_gravity='center',
      cardBackgroundColor=0,--卡片背景色
      cardElevation="0dp",--卡片阴影强度
      radius="8dp",--卡片圆角幅度
      strokeColor=0xff999999,
      strokeWidth="1dp",
      {
        EditText,
        layout_marginLeft="16dp",
        layout_marginRight="16dp",
        hint="请输入文本",
        id="输入框",
        layout_width="70%w",
        backgroundColor=0,
      },
    },
    {LinearLayout,
      layout_marginTop="18dp",
      Orientation=0,
      w="fill",
      h="wrap",
      {MaterialButton,
        text="编码",
        id="编码",
        layout_margin="8dp",
        layout_marginRight="32dp",
      },
      {MaterialButton,
        text="解码",
        id="解码",
        layout_margin="8dp",
        layout_marginLeft="32dp",
      },
    },
    {LinearLayout,
      Orientation=0,
      w="fill",
      h="wrap",
      {MaterialTextView,
        layout_marginTop="12dp",
        text="输出内容",
        style=R.attr.textAppearanceTitleLarge,
        textIsSelectable=true,
        paddingLeft="18dp",
        paddingRight="18dp",
        w="wrap",
        id="输出文本",
      }
    }
  }
}/main.lua如下
import "java.lang.*","java.util.*"
import "android.os.*","android.app.*"
import "github.daisukiKaffuChino.utils.LuaThemeUtil"
activity {
  Title = res.string.app_title,
  ContentView = res.layout.main
}
activity.getSupportActionBar().hide()
function Base64编码(data)
  local Base64=luajava.bindClass("android.util.Base64")
  return Base64.encodeToString(String(data).getBytes(),Base64.NO_WRAP);
end
function Base64解码(data)
  local Base64=luajava.bindClass("android.util.Base64")
  return String(Base64.decode(data,Base64.DEFAULT)).toString()
end
编码.onClick=function()--调用编码按钮的点击事件,
  输出文本.setText(Base64编码(输入框.text))
  --这了应该比较好理解,.text就是获取文本,setText就是设置文本
  --语法糖也可以这样写↓
  --输出文本.text=Base64编码(输入框.text)
end
--[[当然点击函数也可以这样写↓
function 编码.onClick()
end
]]
解码.onClick=function(_)--这了其实函数会接受到他自己的类,这里用不到
  输出文本.text=Base64解码(输入框.text)
end
function dp2px(n)
  return n*activity.resources.displayMetrics.scaledDensity+0.5
end
local themeUtil=LuaThemeUtil(this)
MDC_R=luajava.bindClass"com.google.android.material.R"
primary=themeUtil.getAnyColor(MDC_R.attr.colorPrimary)
输入框.setOnFocusChangeListener{
  onFocusChange=function(v,b)
    if b then
      edit卡片.strokeColor=primary
      edit卡片.strokeWidth=dp2px(2)
     else
      edit卡片.strokeColor=0xff999999
      edit卡片.strokeWidth=dp2px(1)
    end
end}大功告成!

最后打包,在右上角项目里打包,即可
优势 
- lua语言简单小巧,写起来十分快捷
 - 随时随地都能写
 - 可以调用dex,so几乎可以实现所有app功能
 - lua层可以编译混淆
 
缺点 
- 圈子小,轮子少
 - lua层容易被hook,不是很安全
 - 某些复杂的功能可能需要反编译patch实现,(安卓小组件,增加xml图片的R类等等,Aide Lua除外,可以自己写xml,java等,打包会自动编译)
 - 打包的项目可能比较大,因为需要很多依赖,用不到的库也可能打包进app里(Aide Lua除外,可自选所需依赖库)