安卓相关学习步骤 - GameKong/restaurant GitHub Wiki

学习的模块

对于cocos2dx-lua工程涉及到的安卓内容有:

  • 对接Android SDK
  • 构建安卓工程、打包、发布
  • 解决cocos安卓工程中的bug

对接Android SDK

cocos2dx-lua安卓工程中,使用外部SDK提供的功能的代码基本运行流程:

  1. 游戏中的lua逻辑代码调用c++原生代码。 需要学习lua与c++交互的基础知识,之后结合cocos工程的c++代码学习如何将c++类注册到lua栈中供lua直接调用的
  2. c++原生代码调用Android SDK提供的Java接口。需要学习简单的Java语法,Android工程基本结构,Android库的使用。(学习Android过程中可以发现Android SDK实质就是预构建库或Android库模块,例如:.jar文件(java)或.aar文件(android库))
  3. Java执行完毕后会继续运行c++代码(如果Java运行后有返回值,也会将返回值返回到c++然后传到lua栈中传给lua),c++通过cocos提供的LuaJavaBridge继续将运行焦点至lua代码中。这个流程是cocos通过LuaJavaBridge封装好的,即lua -> c++ -> java -> c++ ->lua。 有时我们也需要一种java直接调用c++原生代码,而不是由lua发起的一个调用栈。例如看一个激励视频广告,过程中点击广告关闭按钮是由java处代码发起的一个调用,需要传送一些信息给c++,然后传给lua。所以这里需要学习如何使用java调用c++原生代码,这里涉及到到有:1.定义Java的native接口函数(映射c++代码)用于在Java中使用。2.定义被映射的c++函数,函数名的形式是 Java_包名_类名_java函数名。3.如何将c++原生函数加入到安卓工程中,需要学习cmake或ndk_build(它们是native库构建工具,可将利用ndk将c++代码编译成.so库,java可与.so库进行交互),4.android的gradle相关知识(gradle是安卓构建工具),配置好模块级的.gradle构建脚本后,gradle构建工具可将.so库打包到apk中

构建安卓工程

了解安卓一定要了解安卓的工程结构构建apk的方式、以及安卓平台提供的四大组件以及常用的一些工具类,如intent。 直接看安卓官方文档就行,很全面。

代码减缩、混淆、优化、加密,资源减缩流程和内部原理

  • 代码减缩、混淆:通过代码缩减和混淆可以在一定程度上减少代码占用包体的大小,同时混淆可以阻止他人直接阅读apk中的源码。在安卓工程的build.gradle当中配置minifyEnabled=true可以开启java代码减缩混淆。为了缩减应用的代码,R8 首先会根据组合的配置文件集确定应用代码的所有入口点,列出应用在运行时可能会访问的所有方法、成员变量和其他类。没有访问过的代码会将其移除。但是jni相关的代码或通过反射调用的代码可能不会被检测到从而被误删,例如调用流程可能是lua->cpp->java,所以这里可能检测不到是否被使用从而被移除。同时通过反射调用的代码在代码混淆后会无法找到反射到指定类或方法,所以需要在对应模块的build.gradle中配置proguardFiles属性来配置混淆文件,通过在混淆规则文件中使用-keep将需要的类、方法保留或阻止混淆,保留类、方法、字段名。也可以直接将相应模块gradle文件中的minifyEnabled=false来取消代码的缩减混淆,因为cocos安卓工程中java代码一般相对较少,代码缩减混淆对整个包体大小的优化意义不大,所以此方法也是可行的。
  • 代码优化:代码优化可以进一步缩减代码,使代码更加简洁。例如,r8可以会移除if-else中从未采用过的else,或者一个方法只在一处调用的话,会移除该方法并且内嵌在调用点。 资源缩减:在安卓工程的对应模块的build.gradle当中配置shrinkResources=true开启资源缩减,资源缩减必须是在代码缩减之后,因为通过缩减后的代码才可以判断,资源是否被使用过,如果没有被使用,则会移除掉,从而减缩包体大小。在严格缩减模式下当在运行时计算出的资源名可能会被认为不被使用的,从而移除掉,则可以通过配置一个xml文件来强制移除某个文件或者保留某个文件。
  • 加密:使用我们自己的脚本进行加密。lua代码会先使用luac编译lua代码为二进制文件,可以缩短在运行时lua代码的加载时间,同时防止直接阅读源码,然后通过项目的加密工具(cocos的zilb压缩库和xxtea对称加密库制作的工具)配合自定义的密钥、加密签名、压缩签名对lua代码进一步加密。对于部分美术资源也使用该加密工具进行加密,防止破译。

app发布流程遇到的问题

  • 尝试在google、应用宝、小米、360、搜狗、魅族等渠道发布app,但是大部分国内渠道需要软著和版号,所以在上传app后大部分都审核不通过。Google没有这些限制还在审核当中。 打包上传不同渠道过程发现魅族渠道需要在包名后增加.mz的后缀,本以为修改玩manifest和gradle文件中的包名就可以了,结果由于测试工程中接了一个广告sdk,所以使用到了应用的包名,所以代码中应用到包名的地方都要改,看了一下我们项目的魅族安卓工程也有类似的引用,通过这个反思了一下,尽量不在代码中直接使用app包名,或集中提取到某个模块,以防止打包中修改多处代码。

小记

安卓基础概念(官方文档很全)
目录结构、资源与build.gradle关系、资源含义
build.gradle参数含义
manifest参数含义
依赖项:外部依赖项、本地moudel、jar、aar
应用构建过程
使用命令行(gradlew工具)或AndroidStudio打包apk
使用命令行或配置gradle对apk签名

     {	证书:公钥,私钥信息等
密钥库	密钥:私钥
     }

如果我们加入GooglePlay签名计划,需要提供一个上传密钥和应用签名密钥,上传密钥用于在上传AppBundle或apk前对应用进行签名,应用签名密钥用于给应用签名,用于为用户设备上安装的 APK 签名的密钥。作为 Android 安全更新模型的一部分,应用签名密钥在应用的整个生命周期内保持不变。

在gradle配置文件中进行相关配置,可以在构建过程中进行自动进行代码缩减、资源缩减、代码混淆、优化,从而缩减包体大小。AndroidStudio创建工程会默认创建一个proguard-rules.pro混淆缩减规则文件,可以在指定构建变体的proguardFiles属性中配置该文件,然后在编辑该文件,可以自定义代码的混淆缩减规则,例如 jni相关的java native接口是不能被混淆的,如果混淆后无法通过 Java_packageName_className_methodName的方式找到对应的native方法中,也无法通过给定包名、类名和方法名调用对应的java方法,所以应该在proguard-rules.pro中通过keep*操作阻止相关的混淆。运行时通过反射的方式找到对应类也是一个道理

为了缩减应用的代码,R8 首先会根据组合的配置文件集确定应用代码的所有入口点。这些入口点包括 Android 平台可用来打开应用的 Activity 或服务的所有类。从每个入口点开始,R8 会检查应用的代码来构建一张图表,列出应用在运行时可能会访问的所有方法、成员变量和其他类。系统会将与该图表没有关联的代码视为执行不到的代码,并可能会从应用中移除该代码。但是有的java代码的调用入口可能并不是java代码,可能是lua->cpp->java,所以这里可能检测不到是否被使用从而被移除,这里可以通过混淆规则文件中使用-keep将需要的类保留。也可以直接将相应模块gradle文件中的minifyEnabled=false来取消代码的缩减混淆,因为cocos安卓工程中java代码一般相对较少,代码缩减混淆对整个包体大小的优化意义不大,所以此方法也是可行的。

保留构建apk生成的mapping.txt文件,用于去混淆处理,从而能够获取包含正确行号且可读性更强的堆栈轨迹。

 原生代码相关:
    原生代码构建过程(cmakeList文件配置以及build.gradle中cmake相关配置,cmake模块文件和cmakeList文件的用法)
原生预构建库的导入
不同abi架构的包体
cpp与java相互调用、cpp与lua相互调用
    JNI