当前位置:   article > 正文

Unity2018导出Android工程并自行生成apk(总)_exportasgoogleandroidproject

exportasgoogleandroidproject

https://docs.unity3d.com/2018.4/Documentation/Manual/android-gradle-overview.html

以下内容都是在unity2018.4.19下的情况

本文讲解的是使用unity导出android工程以后,对android工程做一些修改,使用gradle打包apk

unity构建使用的api接口都是BuildPipeline.BuildPlayer——打包apk(导出android工程或者是直接生成apk),ios,pc最终都是调用的这个接口。

构建的设置可以通过编辑器模式下的buildsetting和playersetting中进行设置,或者也可以使用对应的api在代码中设置。

目录

Unity中的构建设置

1.buildsetting设置以及对应的api

2.playersetting设置以及对应的api

CustomGradleTemplate的修改

3.查找界面对应的api方法

4.其他的一些设置

Api Compatibility Level如何选择

Unity导出android工程

1.androidsdk的设置

2.进行导出android工程

3.导出过程中出现的错误

对导出的工程进行处理以及使用gradle打包

1.接入某sdk

2.使用androidstudio打开,解决错误直到生成成功

3.使用脚本进行自动打包

接androidsdk库工程

1.sdk方针对的是源工程是unity

2.sdk方针对的源工程是androidstudio工程

Unity导出android工程做的事情

PS.使用unity直接进行build成apk(选用的internal)的步骤大概:

Android工程打包apk的事情

Google发布的经典的Apk打包流程图

AndroidStudio中的打包

ps0.APK中的目录

ps1.Android工程的资源管理

资源相关目录:

R类资源-R.java

ps2.打包工具相关

Gradle

1)wrapper文件夹

2)xxxx.gradle文件

3)xxx.properties文件

Android资源打包工具aapt

ps3.android开发工具的下载

ps4.android sdk的目录介绍

接sdk中遇到的一些问题:

1.targetsdkversion设置


Unity的设置

1.buildsetting设置以及对应的api

对应api:

EditorUserBuildSettings.exportAsGoogleAndroidProject = true;
EditorUserBuildSettings.androidBuildSystem = AndroidBuildSystem.Gradle;

EditorUserBuildSettings.SetBuildLocation(_buildTarget, targetFolder); //设置导出路径

2.playersetting设置以及对应的api

UnityEditor.PlayerSettings.Android.useAPKExpansionFiles = true;//生成 obb

customgradletemplate这个没有找到对应的api。但是发现当勾选上以后,会自动在显示出来的路径上(Plugin/Android)添加一个gradle文件,而如果把勾选取消,就自动把.gradle文件的后缀改成了 .gradle.DISABLE。  

CustomGradleTemplate的修改

勾选了这个以后会在Plugin/Android目录下自动生成一个默认的 mainTemplate.gradle 文件。

一般都会对这个文件进行自定义的修改来覆盖默认的配置或者新增一些配置(比如适配后续需要添加的android库工程,比如要去远端下载库文件,比如导入googleservice插件)

下面是项目中对 mainTemplate.gradle 文件进行的修改,左边是默认生成的,后边是修改的:

可以在对应的模块内增加内容;也可以删除他本身的宏,使用自己写的(对比下面的第二张第三张图)

在导出的过程中,**XXXX**中的都会被的设置上对应的值

如果不想用**XXXX**(Unity Editor中Playersetting中设置的值)就直接替换了就可以,比如上面的minsdkversion、targetsdkversion、applicationid,以及下面的versionCodeversionName

关于gradle的各个含义下文会介绍。

3.查找界面对应的api方法

对比两次界面修改后projectsettings文件夹下面的.asset文件(转成txt 用对比工具看)的修改,然后大概就知道api的接口名字了。

一般都是在PlayerSettings类EditorUserBuildSettings类中。

4.其他的一些设置

Api Compatibility Level如何选择

.net配置不是很懂

https://zhuanlan.zhihu.com/p/44559662

通过Player设置中的Api Compatibility Level选项为Player构建选择.NET配置。Unity支持的两个.NET配置是:

  • .NET Standard 2.0
  • .NET 4.x.

.NET Standard 2.0

配置与.NET Foundation发布的同名配置匹配。这个配置非常适合新的Unity项目。它比.NET 4.x小,适用于内存受限的平台,如手机。此外,此配置适用于Unity支持的所有平台。如果你为Unity开发dll库,你也应该选择这个配置选项。

.NET 4.x

配置提供最新的.NET 4 API,包括.NET Framework类库中提供的所有代码。它也支持所有.NET Standard 2.0配置,因此它可以与基于.NET Standard 2.0构建的托管程序集一起使用。虽然它提供了大量API的访问,但某些API无法在所有平台上运行。如果你的项目需要.NET Standard中未公开的功能或具有遗留代码,.NET 4.x可能是一个不错的选择。


Unity导出android工程

1.androidsdk的设置

2.进行导出android工程

导出的过程中,中间文件夹都在Temp目录下。有时候会提示一些错误,都可以在这里目录下进行查找。(如果是自己进行build生成apk,如果生成apk失败但是看不出原因,可以在这个Temp目录下找到中间的gradle工程,可以使用androidstudio打开进行构建,在androidstudio中构建看看有什么详细的错误信息)

3.导出过程中出现的错误


对导出的工程进行处理以及使用gradle打包

1.接入某sdk

针对某sdk的要求,把sdk方的库工程放到导出的Android工程中,并增加一些配置文件。

(因为这些都是在Unity导出工程的时候无法自动导出的。)

2.使用androidstudio打开,解决错误直到生成成功

对修改过后的android工程选择导入,因为并不能保证他就是没有错误的,可能第三方库和unity工程中的某些jar包有冲突之类的,先用androidstduio进行构建,方便解决错误。

选OK

gradle sync failed 看提示修改,如果是gradle插件版本问题

如果是gradle插件版本问题,修改gradle插件版本(我的gradle版本是5.4.1)

    dependencies {
        //classpath 'com.android.tools.build:gradle:2.1.0'  默认导出的工程是这句
        classpath 'com.android.tools.build:gradle:3.5.3'
    }

或者是库的问题 

    repositories {
        google()
        jcenter()
        //下面是新加的
        maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/' } 
        maven{ url'http://maven.aliyun.com/nexus/content/repositories/jcenter'}
    }

https://blog.csdn.net/u012138730/article/details/90734179  中还记录了几种Gradle Sync失败的情况 ) 

gradle sync 成功以后,就可以进行build看有什么错误依次解决。

3.使用脚本进行自动打包

针对上面的一些错误的修正使用脚本实现对导出的Android工程先做一些处理

然后使用 gradle 打包(找到gradle所在目录,调用gradle命令)

整个流程实现自动化打包


接androidsdk库工程

1.sdk方针对的是源工程是unity

那么添加到plugin/android下面的库工程根目录必须有以下文件:

  • 包含文件 project.properties 

内容:

android.library=true

如果文件夹不包含  project.properties ,那么unity在生成apk或者导出android工程后不会包含此文件夹。 

  • 包含一个AndroidManifest.xml

如果文件夹包含project.properties,但是不包含AndroidManifest.xml,导出也会报错。

2.sdk方针对的源工程是androidstudio工程

一般在AndroidStudio中创建的库工程目录结构是如下所示的,但是上述说到直接放在Unity的Android文件夹下的库工程的根目录下需要有AndroidManifest.xml,所以AndroidStudio中创建的库工程不能直接放到Unity中使用。

一般是在unity导出了android工程以后再把库工程添加进去。


Unity导出android工程做的事情

待补充

PS.使用unity直接进行build成apk(选用的internal)的步骤大概:

Building player ———— building scene ; building resources folder
Fetching assembly references ———— building list of referenced assemblies
Building player ———— Packaging assets xxxxxxxxxxxxxxxxxxx globalgamemanagers.assets sharedassetsxx.assets
Postprocessing Player
Splitting assets ———— Splitting large asset files

Process plugins ———— Processing native plugins
Processing AAR plugins ———— Preparing and unpacking AAR plugins
Creating Android manifest ———— Merging AndroidManifest.xml files
Fetching assembly references ———— building list of referenced assemblies
Compiling resources ———— Repackaging and recompiling resources
Buiding Dex ———— Converting Java classes to dex-format
Preparing streaming assets ———— Copying streaming assets
AAPT: Compiling all assets into one archive ———— Building streaming package , Building asset package
Creating APK package ———— Building target package from assets archive and pre-built binaries
Optimizing target package alignment
Moving output package ———— Moving final Android package


Android工程 打包成 apk的过程

https://www.jianshu.com/p/8d691b6bf8b4
https://cloud.tencent.com/developer/article/1037072

Google发布的经典的Apk打包流程图

ApplicationResources:res文件夹下的文件 后面会讲到 (OtherResources:assets文件夹的
ApplicationSourceCode:java源代码

R.java文件:根据App中的资源文件自动生成,可以理解为资源字典。

涉及到的工具:

  • aapt工具:资源打包工具
  • aidl工具:aidl打包成java接口类
  • java编译器:.java-》.class
  • dex工具:将java字节码转换成Dalvik字节码,在此过程中会压缩常量池,消除一些冗余信息等
  • apkbuilder工具没有编译的资源(assets下面的)+.arsc索引的资源+.dex文件——》打包到apk中。
  • jarsigner工具:对上述apk进行签名,通过配置的签名文件(debug和release都有),得到一个签名后的signed.apk (有关Apk中的签名的介绍可以查看另外一篇文章。)
  • zipAlign工具:对上述signed.apk进行对齐处理,所谓对齐,主要过程是将APK包中所有的资源文件距离文件起始偏移为4字节整数倍,这样通过内存映射访问apk文件时的速度会更快。对齐的作用主要是为了减少运行时内存的使用。

资源+代码

ps0.最终的APK中的目录结构和内容

APK: android platform package 安卓平台包。apk文件其实是zip格式。(apk后缀改成zip,再解压可以看内容。跟ios一样)

内容主要包括:

  • Java 代码文件:classes*.dex,
  • Native 代码文件lib目录下面的 .so 文件,
  • 资源文件:包括 assets 目录res 目录以及 resources.arsc 索引表文件
  • AndroidManifest.xml:清单文件,直接解压apk使用apktool反编译apk都能获得AndroidManifest.xml,但直接解压获得的AndroidManifest.xml是乱码的,无法直接查看。

classes.dex文件:classes.dex是应用程序的可执行文件,java文件(.java)编译后(生成.class)再通过DX工具打包而成的。Dex是Dalvik VM executes的全称。Dalvik是 Android特有的虚拟机,非常适合在移动终端上使用。所以.dex并非Java ME的字节码而是Dalvik字节码

lib目录:该目录存放的是应用程序依赖的不同 ABI 类型.so 文件。子目录有:armeabi armeabi-v7a x86对应不同的cpu架构(关于android的cpu架构,看https://blog.csdn.net/u012138730/article/details/90734179)等。把重要信息封装到.so库文件里,这些信息是无法被反编译。运行时会根据当前CPU的架构来选择对应的so文件,即不同的abi目录下的so文件。但是并不一定要每个so都要各个平台各一份,有时候这些so文件是可以在不同的CPU架构上执行的,只是在不对应的架构上执行速度会慢一些,所以当追求速度的时候可以给针对每个架构输出对应的so文件,当追求包体大小的时候输出一个armeabi的so文件就可以了。

ps:

启动应用,看打印的日志,可以看到大概有这么一行信息,就知道读取的是哪个目录下的lib了

I Unity   : Built from '2018.4/china_unity/release' branch, Version '2018.4.23f1 (c33343718ef4)', Build type 'Release', Scripting Backend 'il2cpp', CPU 'armeabi-v7a' 

assets目录:来自工程目录下assets文件夹,可以存放例如图片资源文件、JSON 配置文件、渠道配置文件、二进制数据文件、HTML5离线资源文件等

res目录:经过工程目录下res文件夹,经过编译以后的资源文件,这个目录下面的资源都会出现在资源清单文件 R.java 的索引中。(在解压出来的中 AndroidManifest.xml中的资源地址都是用@一个二进制来指示的,说明这就是一个资源ID,打包以后都变成了资源ID了)

resources.arsc文件:资源索引表,用来描述具有ID值的资源的配置信息(res目录下的资源)

AndroidManifest.xml文件:它描述了包名(package="com.xx.xx"),应用的名字(android:label)、版本(android:versionCode 和 android:versionName)、权限(<uses-permission>)、引用的库文件等信息,以及Android项目的系统清单文件,Android应用的四大组件(Activity、Service、BroadcastReceiver 和 ContentProvider )均需要在此配置和声明

META-INF目录:保存有签名相关的信息,用来保证apk包的完整性和系统的安全。在Android手机上安装apk包时,应用管理器会按照同样的算法对包里的文件做校验,如果校验结果META-INF下的内容不一致,系统就不会安装这个apk。保证了apk包里的文件不能被随意替换。

ps1.Android工程中的资源管理

资源相关的两个目录:

  • assets文件夹

assets目录下保存的是一些原始的文件,可以以任何方式来进行组织。这些文件最终会被原装不动地打包在apk文件中(apk直接解压出来就是有assets目录的内容和原始的是一样的)。

使用AssetManager类来完成对资源的访问,输入文件名即可:

  1. AssetManager am= getAssets();
  2. InputStream is = am.open("filename");

  • res文件夹

里面的资源文件名只能以小写字母和下划线做首字母,随后的名字中只能出现 [a-z0-9_.] 这些字符

res目录下的大多数文件都会被编译,可以看apk直接解压出来res目录下的文件原始文件的区别(\res\raw还是原始的文件;xml是变成二进制,png会进行优化等)

这些资源并且都会被赋予资源ID,这些资源ID被保存在R.java文件中;同时,会生成一个resources.arsc资源索引文件

使用Resources类 和 AssetManager类来完成对资源的访问,Resources是通过resources.arsc把Resource的ID转化成资源文件的名称,然后交由AssetManager来加载。

R类资源是什么-R.java

R.java生成在build文件夹中


R.java文件中的R类默认attrdrawablelayoutstring四个静态内部类,每个静态内部类分别对应着一种类型的资源。这些资源本身存在于res文件夹下。res文件夹下的资源文件R.java文件里面类的对应关系,分成两类:

  • 对于drawable-xxx、layout、menu文件夹下

每一个文件都分别会在R.java文件里面生成drawablelayoutmenu类的一个常量,常量的名字就是文件名字,常量值就是该资源的资源ID
比如layout目录下的main.xml文件,那么生成在R.java中的就是:

public static final class layout {
        public static final int main= 0x7f090000;

  • 对于values文件夹下

是根据文件里面的内容来生成相应的类常量,此文件夹下xml文件的根节点是resources,里面的标签名就是类名,属性就是常量名
比如strings.xml 下的内容为,标签名是string,name属性值是 app_name

  1. <resources>
  2. <string name="app_name">sdk</string>
  3. </resources>

 那么生成在R.java中的就是:

  1. public static final class string {
  2. public static final int app_name= 0x7f0b0000;

R类资源R.java用途:

  1. 自动标示资源的索引功能
  2. 如果res目录中的某个资源在应用中没有被使用到,在该应用被编译的时候系统就不会把对应的资源编译到该应用的APK包中,节省Android手机的资源。java代码中引用R类资源:
  • java代码中引用R类资源:

R.Static_inner_classes_name.resource_name

其中Static_inner_classes_name代表的就是在R.java文件中定义的静态类。

比如如果要引用【drawable-Xhpi】下的icon.png,而该图片在R.java文件的映射为drawable内部类下icon常量,所以,获取该资源写法为:

R.drawable.icon

引用Android系统本身自带了很多的资源,只需要再前面加上“Android.”以声明该资源来自Android系统,即:

Android.R.resource_type.resouce_name

  • XML文件中引用R类资源:

@[package:]Static_inner_classes_name/resouce_name

“@”代表的是R.java类,比如:

@drawable/icon 就是上述列子中的
@id/button
@string/app_name

如果访问的是Android系统中自带的文件,则要添加包名“android:”。例如:

android:textColor="@android:color/red" 

比如后面有个问题就是不能用android 因为他不是android系统中的,而是在v7兼容包中的。

  • 在XML文件中向R类添加资源ID

在布局文件中当我们需要为一些组件添加Id属性作为标识,可以使用如下的表达式:
@+id/button
“+”表示在R.java的名为id的内部类中添加一条记录。
在R.java文件中的id这个静态内部类添加一条常量名为button,该常量就是该资源的标识符。如果 id这个静态内部类不存在,则会先生成它。

ps2.打包工具相关

AndroidStudio的构建工具——Gradle

AndroidStudio采用 Gradle 来构建工程的。 (Gradle 是一个项目构建工具,不仅可以构建Android工程,还可以构建java工程,C++工程等)

Gradle 是用一种基于 Groovy DSL(领域特定语言 Demain Specific Language)来声明项目设置。(ANT和 Maven 采用的XML来声明项目设置,Make 用的makefile)

而Groovy:是一种基于JVM虚拟机的动态脚本语言,它的语法和Java非常相似,由Java入门学习Groovy基本没有障碍。Groovy完全兼容Java,又在此基础上增加了很多动态类型和灵活的特性,比如支持密保,支持DSL。

Gradle就是对工程的管理,帮我们做了依赖(去下载相关的依赖项目),打包,部署,发布,各种渠道的差异管理等工作。在一个工程中我们会看到wrapper文件夹,xxxx.gradle文件,xxx.properties文件。其中最重要的是gradle配置文件里面,里面可配置的项目有很多,具体可以用到的时候再查。

1)wrapper文件夹

Wrapper是对Gradle的一层包装,便于在团队开发过程中统一的Gradle版本构建。

gradle-wrapper.properties的内容:

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
//会到本地的C:\Users\XXXX\.gradle\wrapper\dists下面去看有没有可用的包,没有就会去下面那个地址下载了
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip

在Android工程导入到AndroidStudio的时候可能会要求重新生成,使用本地支持的Gradle版本

2)xxxx.gradle文件

最少有三个,分别介绍:1个settings.gradle,在根目录下,2个或者多个 build.gradle 文件,一个在根目录下,一个在 app 目录下(如果有其他模块,就在其他模块下)。

下面介绍这三种类型的具体配置项目

  • 根目录下的settings.gradle

定义哪些module(关于 Module的概念) 应该被加入到编译过程,对于单个module(单个的话,那就是app模块目录了吧) 的项目可以不用需要这个文件,否则就是必须得配置。

这个文件里面的代码初始化阶段就会被执行,用于初始化以及工程树的配置

比如下面添加了2个模块

include':app',':lib'

或者多级目录,顶层目录就不用:号也可以,下面是工程中的一个例子

include ':Common:commonres'         ————代表的是./Common/commonres/
include ':Channel:1111:channelres'   ————代表的是./Channel/1111/channelres/
include 'GCloudVoice'                       ————代表的是./GCloudVoice/,是Unity中的Android库工程
include 'unity-android-resources'      ————代表的是./unity-android-resources/,Unity导出Android工程自带的

不管是什么工程,总得要告诉编译器编译哪些文件对吧。

可以理解为包含VS中编译哪些工程

  • 根目录下的build.gradle顶级配置文件

所有子项目/模块添加常见的配置选项。边看本地的这个文件边看这个注释

1)buildscript{ }块——gradle脚本自身需要使用的资源

             repositories{ }——仓库,配置Gradle代码托管库,设置之后可以在项目中轻松引用仓库上的开源项目了。Gradle预先配置了远程支持JCenter、Maven、Central和lvy等存储区,当然也可以指定本地自定义的远程存储库

                    google()——google的官方仓库

                    jcenter(),mavenCentral()——出名的公共中央仓库

              dependencies{ }——依赖,默认设置了项目依赖Gradle的插件版本路径;指的是gradle脚本自身执行所需依赖(Gradle插件) 所以如果你没有引入远程的Gradle插件,那么就不用在buildscript {}下的dependencies下添加依赖。

  1. buildscript {
  2. repositories {
  3. google()
  4. jcenter()
  5. // 导入XXSDK仓库
  6. maven{
  7. url "http://repo.xxxxxxxxx.com/bale/repo"
  8. }
  9. }
  10. dependencies {
  11. classpath 'com.android.tools.build:gradle:3.4.0'
  12. classpath 'com.google.gms:google-services:4.3.3'
  13. // NOTE: Do not place your application dependencies here; they belong
  14. // in the individual module build.gradle files
  15. }
  16. }

在AS中可以看到gradle的版本号gradle插件的版本号

 

2)allprojects{ }块——配置所有模块中都需要使用的依赖项

这个是项目本身需要的依赖(普通代码库);
上面说的buildscript是gradle这个工具本身需要的依赖。

  1. allprojects {
  2. repositories {
  3. google()
  4. jcenter()
  5. // 导入XXSDK仓库
  6. maven{
  7. url "http://repo.xxxxxxx.com/bale/repo"
  8. }
  9. }
  10. }

3)可以定一些自定义的task——语法

比如 cleantask

  1. task clean(type: Delete) {
  2. delete rootProject.buildDir
  3. }

运行gradle clean时,执行此处定义的task。该任务继承自Delete,删除根目录中的build目录。相当于执行Delete.delete(rootProject.buildDir)。其实这个任务的执行就是可以删除生成的Build文件的,跟Android Studio的clean是一个道理。

task更多介绍 见 https://blog.csdn.net/u012138730/article/details/90734179

可以理解VS中对于整个解决方案的配置。

  • 模块目录下的build.gradle模块配置文件(比如默认的app)

多个模块,就是多个配置文件,分别在模块文件夹的根目录下。详细看这里
介绍以下四个部分的定义:

  • apply plugin:——应用插件
  • android{ }       ——编译版本,打包工具版本,包名、版本号、minsdkversion、targetsdkversion等基本信息,debug release等基本配置,证书的配置
  • productFlavors {}——多渠道的配置
  • dependencies{ }      ——依赖的库,这个模块依赖哪些其他模块(可以是本地,可以是托管库中的),即依赖关系。这个比较重要。

1)插件应用 apply plugin:xxx(plugin id

xxx(plugin id 插件ID)一般是以下三个:

com.android.application ——就是应用了com.android.application这个插件,这个插件是App应用工程插件,帮助生成一个可运行的apk应用
com.android.library         ——这个插件是Library库工程插件,它可以生成AAR包给其他的App工程公用
com.android.test             ——这个插件是表明Test测试工程,用于对App工程或者Library库工程进行单元测试

比如如下:

apply plugin:'com.android.application' ——如果此模块是应用程序的时候,就引入这个
apply plugin:'com.android.library'        ——如果此模块是库模块,就引入这个。

apply plugin:’×××’    VS      apply from:’×××’

apply plugin:’×××’:xxx是pluginid。整句话就是应用一个二进制插件。二进制插件一般都是被打包在一个jar里独立发布的,比如我们自定义的插件,再发布的时候我们也可以为其指定plugin id,这个plugin id最好是一个全限定名称,就像你的包名一样。比如上面的com.android.application就是一个plugin id

apply from:’×××’:  xxx是一个文件名。整句话是相当于引入一个脚本,文件名可以是远程的url,也可以是相对于本地的文件路径。本地的话就填针对这个build.gradle相对路径

因为我们会把庞大的脚本文件,进行分块、分段整理,拆分成一个个共用、职责分明的文件,然后使用apply from来引用它们:

比如我们可以把常用的函数放在一个Utils.gradle脚本里,供其他脚本文件引用。

比如我们把 App的版本名称版本号单独放在一个version.gradle脚本里,可以使用自动化对该文件自动处理,生成版本。

由此可见,虽然常用的几个gradle是必须的,我们也可以定义其他的gradle文件。

2)android{ }——android构建的特定配置;

compileSdkVersion  ——指定项目编译需要SDK API版本,即编译时用的api。(相当于vs中用的v100,还是v90,的平台库版本)

buildToolsVersion    ——指定SDK build-tools构建工具的版本,包括了打包工具aapt、dx等等,位于sdk目录下的build-tools目录下对应的版本;(编译打包这个android工程的时候,用到的工具的版本)

defaultConfig{}    ——applicationId:用于指定项目的包名,如果包名进行修改这里做对应修改;(包名)

                                         minSdkVersion:项目最小兼容版本;

                                         targetSdkVersion:项目的目标版本,在此版本进过充分测试,如果高版本提供了新功能,就不会启用;(安装到手机上的时候用)

                                         versionCode:项目的版本编号;(上传应用商店的时候更新用)

                                         versionName:项目的版本名称;(字符串的版本号)

                                         multiDexEnabled用于配置该BuildType是否启用自动拆分多个Dex的功能。一般用程序中代码太多,超过了65535个方法的时候;

                                         ndk{}多平台编译,有so文件的时候使用,在abiFilters{}设置需要的abi目录,比如:

  1. defaultConfig {
  2. minSdkVersion 17
  3. targetSdkVersion 29
  4. applicationId 'com.xxx.xxx'
  5. ndk {
  6. abiFilters 'armeabi-v7a', 'arm64-v8a'
  7. }
  8. versionCode 16
  9. versionName '1.2.0'
  10. }

sourceSets{}    ——源代码集合,是Java插件用来描述和管理源代码及资源的一个抽象概念,是一个Java源代码文件和资源文件的集合,我们可以通过sourceSets更改源集的Java目录或者资源目录等。

                                     如下图通过sourceSets告诉Gradle关于jni so包的存放路径就在app/libs/ABI目录上(不定义的话,肯定有个默认路径的,默认是放在 main/jniLibs/ABI目录 上的)

  1. sourceSets{
  2. main{
  3. jniLibs.srcDirs = ['libs']
  4. }
  5. }

buildTypes{}    ——构建类型,内置了release{}和debug{}。应该还可以自己定义新的名字。release{}和debug{}这两种模式主要区别在于,能否在设备上调试以及签名不一样,其他代码和文件资源都是一样的。一般设置代码混淆,minifyEnabled=true就会开启混淆:

                                   (可以理解vs的debug还是release版本,其实就是可以对应设置不同的参数,可能跟ios包的dev证书和dis证书比较相似)

  1. buildTypes {
  2. release {
  3. minifyEnabled false
  4. proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
  5. }
  6. }

signingConfigs{}  ——默认情况下,debug构建类型的签名已经被配置好了,使用的就是Android SDK自动生成的debug证书,它一般位于$HOME/.android/debug.keystore,key和密码是已经知道的,一般情况下我们不需要单独配置debug模式的签名信息

3)productFlavors{} ——可选,配置多渠道打包工具,根据配置不同的逻辑、构建部分来实现版本的差异化

直接定义了两个渠道,一个是free,一个是paid,设置不同的applicationId:

  1. productFlavors {
  2.     free {
  3. applicationId 'com.example.myapp.free'
  4.     }
  5.     paid {
  6. applicationId 'com.example.myapp.paid'
  7.     }
  8. }

或者定义为空,但是在app/src下面,分别创建和main同级目录的文件夹free, paid, 这两个文件夹里面都各只有一个AndroidManifest.xml文件,free下的AndroidManifest.xml文件只需要如下(猜的):

  1. productFlavors{
  2. free { }
  3. paid { }
  4. }
  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp.free">
  2. <application>
  3. </application>
  4. </manifest>

另外,可以用manifestPlaceholders占位符(Gradle Android插件里的一个功能)的例子:

  1. productFlavors {
  2.         free {
  3.             applicationId 'com.example.myapp.free'
  4.             manifestPlaceholders= [APP_ICON: "@drawable/ic_launcher",APP_NAME:applicationId]
  5.         }
  6. }

上面定义了 APP_ICON="@drawable/ic_launcher" APP_NAME='com.example.myapp.free',然后就可以在 AndroidManifest.xml 文件中使用这两个manifestPlaceholders占位符了(在 AndroidManifest.xml 文件中通过 "${APP_ICON}" 这种方式来调用) 

所以在AndroidManifest.xml 中看到占位符${XXXX}",就可以在build.gradle中看看有没有定义productFlavors以及manifestPlaceholders

4)dependencies{ }   ——指定当前模块的依赖关系,本地依赖库、远程依赖库和库模块依赖

本地依赖——本地依赖是对本地的Jar包目录添加依赖关系。比如 implementation fileTree(,ext jar)是一个本地依赖的声明,它表示将libs目录下所有的.jar后缀文件添加到项目的构建路径当中。

implementation fileTree(include: ['*.jar'], dir: 'libs')

compile(name:'AAR的名字', ext:'aar')

到哪里去找这个aar文件呢,在下面这个命令中设置:添加本地引用目录(存放的路径声明)

    repositories{
        flatDir{
            dirs 'libs'
            dirs 'libs','../xxx/xxx/xxx/xxx'
        }
    }

库依赖——对项目中的库模块(库工程)添加依赖关系。下面是一个例子的:(要事先在settings.gradle中配置了要编译这些工程)

dependencies {
    implementation project(':GCloudVoice')
    implementation project(':unity-android-resources')
}

远程依赖——对jcenter库上的开源项目添加依赖关系appcompatconstraint属于远程依赖。先build.gradle 中添加远程仓库地址的引用:

  1. allprojects {
  2. repositories {
  3. // google的官方仓库
  4. google()
  5. // 出名的公共中央仓库
  6. jcenter()
  7. mavenCentral()
  8. //如果有私库,也要添加链接
  9. //....
  10. }
  11. }

然后在目标 module 的 build.gradle 中添加具体 aar 的依赖(implementation):

  1. dependencies {
  2. implementation 'com.android.support:support-v4:25.3.1'
  3. }

依赖的类型有——jar包、aar包、so包。
引入依赖的声明——implementation、api、compile only、runtime only。具体区别和用法:文章1文章2官网介绍

  1. apply plugin: 'com.android.application'
  2. android {
  3. compileSdkVersion 28
  4. buildToolsVersion '26.0.2'
  5. signingConfigs {
  6. release {
  7. storeFile file("xxx")
  8. storePassword "xxx"
  9. keyAlias "xxx"
  10. keyPassword "xxx"
  11. }
  12. }
  13. defaultConfig {
  14. applicationId "com.xxx.xxx"
  15. minSdkVersion 19
  16. targetSdkVersion 28
  17. versionCode 1
  18. versionName "1.0.0"
  19. }
  20. lintOptions {
  21. abortOnError false
  22. }
  23. buildTypes {
  24. debug {
  25. minifyEnabled false
  26. proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  27. }
  28. release {
  29. minifyEnabled false
  30. proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
  31. signingConfig signingConfigs.release
  32. }
  33. }
  34. packagingOptions {
  35. exclude 'META-INF/ASL2.0'
  36. exclude 'META-INF/LICENSE'
  37. exclude 'META-INF/NOTICE'
  38. exclude 'META-INF/DEPENDENCIES'
  39. exclude 'META-INF/LICENSE.txt'
  40. }
  41. repositories{
  42. flatDir{
  43. dirs 'libs'
  44. dirs 'libs','../xxx/xxx/xxx/xxx'
  45. }
  46. }
  47. }
  48. dependencies {
  49. compile fileTree(include: ['*.jar'], dir: 'libs')
  50. compile project(':xxx:xxx:xxx')
  51. }
  52. apply plugin: 'com.google.gms.google-services'

3)xxx.properties文件

gradle.properties——位于项目根目录下,主要设置Gradle后台进程JVM内存大小日记级别;设置全局常量,可以供build.gradle中使用;

local.properties——为Gradle配置环境变量,例如sdk、ndk路径;

(properties文件,groovy文件,gradle文件,每种文件如果是内容如其名的话,都是有相应的格式的。properties文件就是键值对的格式)

Android资源的打包工具aapt

aapt——Android Asset Packaging Tool(Android 资源打包工具
aapt.exe程序所在路径——在androidsdk的build-tools目录下,比如我的 C:\Android\android-sdk\build-tools\28.0.3,其下可以看到有aapt.exe,在此打开命令行 输入 :

aapt help 就可以看到aapt命令支持的参数了

查看apk包名、主activity、版本等信息命令:

aapt dump badging D:\xxxx.apk > log.txt

aapt源码分析以及命令详解:https://www.jianshu.com/p/8d691b6bf8b4

在Google发布的经典的Apk打包流程图中可以看到aapt有两个箭头:

第一次对res文件夹下文件生成R.java类(资源索引表),用来参与javac编译。
第二次对res文件夹下文件生成CompiledRes(对res里面的资源文件编译为二进制文件+资源索引文件resource.arsc

ps3.android开发工具的下载

如果需要增加新的android sdk,可以在android studiosetting中搜android找到sdk进行下载: 

也可以不在界面中,而是使用命令行sdkmanager进行下载,cd到C:\Android\android-sdk\tools\bin下,比如下level27的

sdkmanager "platform-tools" "platforms;android-27"——安装软件包

在安装了android studio ,然后新建一个项目,启动的时候就会去下载 gradle了,下载地址的地址就是如下图所示,下载完了会放到C:\Users\XXXX\.gradle\wrapper\dists中去。(如果想用本地其他版本的Gradle,在其他目录,就选择Use local Gradle distribution 并设置本地路径

如果是直接安装gradle,那么要先安装JDK,并配置JAVA_HOME环境变量(因为Gradle是用Groovy编写的,而Groovy基于JAVA。另外,Java版本要不小于1.5),然后进行Gradle下载

关于jdk的介绍看 https://blog.csdn.net/u012138730/article/details/90734179 。

  • 其他地址 感觉不靠谱

https://www.androiddevtools.cn/

ps4.android sdk的目录介绍

  • tools工具

bin下面有个sdkmanager(https://developer.android.google.cn/studio/command-line/sdkmanager命令:

上面也看到sdkmanager 可以用来下载sdk。其实就是管理sdk工具包的。

sdkmanager --version ——显示tools本身的版本号 26.1.1

sdkmanager --list——展示了已经安装的包,可以安装的包,和可以更新的包。下面截图安装的包和可以更新的包:

其实打开android studio的setting的android sdk中看更加清楚看到上述信息

Android8.0 ApiLevel 26
Android8.1 ApiLevel 27
Android9.0 ApiLevel 28
Android10.0 ApiLevel 29

记不住这个level打开看看就行 

https://developer.android.google.cn/about/dashboards

sdkmanager "platform-tools" "platforms;android-28"——安装软件包

  • platform-tools

有adb

  • build-tools构建工具

这里包含:

我的unity打包apk,使用的构建工具就是29
platformBuildVersionCode="29" platformBuildVersionName="10"

  • platforms平台

SDK Platform 该版本编译好的SDK,必须装的

使用unity打包apk,使用编译sdk版本就是29
compileSdkVersion="29" compileSdkVersionCodename="10"

  • sources源码 

源代码,一个是学习Google优秀的源代码,二个是查看源码方便调错。


遇到的一些问题:

1.targetsdkversion设置

unity使用的android sdk版本是29,但是一个第三方的sdk的目标level是28,打出的apk的targetsdkversion就是29的。而这个包在android29的系统中会崩溃,因为第三方sdk的目标level是最高是28的。

所以unity中targetsdkversion也是设置成28,这样打出来的包的targetsdkversion就是28的了。在android level29中就不会崩溃。

2.在.gradle中自定义copytask执行失败

 

如果第一张 into 的图中的 目录文件夹中包含加锁的文件的话,就会出现如下错误。加入into的文件夹是 android studio工程中根目录中有 .gradle文件夹,如果拷贝到这个目录下就不行,会出错。 

有关Gradle中的task的介绍可以查看另外一篇文章

3.使用sdkmanager下载新的buildtool和platform

因为要把targetSDKVersioncompileSdkVersion改到29。compileSdkVersion改到29,就要下对应的编译工具:
首先cd到sdkmanager的位置,使用命令行下载最新的platforms和build-tools(buildtool的版本有https://developer.android.google.cn/studio/releases/build-tools

sdkmanager "platform-tools" "platforms;android-29" "build-tools;29.0.2"

4.AAPT:resource not found 

          android:theme="@android:style/Theme.AppCompat.Light.DarkActionBar" />

去掉android:: 改成

           android:theme="@style/Theme.AppCompat.Light.DarkActionBar" />

就好了

 v7的兼容包不能加Android

5.兼容安卓10分区存储的 android:requestLegacyExternalStorage="true"

在Android 10之前的版本上,我们在做文件的操作时都会申请存储空间的读写权限

但是这些权限完全被滥用,造成的问题就是手机的存储空间中充斥着大量不明作用的文件,并且应用卸载后它也没有删除掉

为了解决这个问题,Android 10 中引入了 Scoped Storage 的概念,通过添加外部存储访问限制来实现更好的文件管理。


最简单粗暴的方法就是在 AndroidManifest.xml 中添加 android:requestLegacyExternalStorage="true" 来请求使用旧的存储模式。
在下一个版本的Android中,此条配置将会失效,将强制采用外部储存限制

https://www.jb51.net/article/181745.htm

6.android不能在mainThread有网络请求

因为不知道这个,在主线程中进行了网络请求,app也没有显示什么异常,但是其实有输入错误日志

https://stackoverflow.com/questions/13270372/android-os-networkonmainthreadexception-when-trying-to-connect-over-wifi-using
类似于这种输出,System.err(17185): android.os.NetworkOnMainThreadException

各个android系统报错不一样,有的是anr有的是一个错误 界面卡着不动
anr是什么
就是android自己有一个超时无响应 application not response

7.apk的签名不对

上传的时候提示跟上一次签名不对应,是自己签名文件使用的有问题

可以自己检查一下签名是不是对了,再上传:

解压一下apk,然后:

keytool -printcert -file xxx.rsa

或者直接看:

keytool -printcert -jarfile XXXX.apk

 有关Apk中的签名的介绍可以查看另外一篇文章

7.Unity打包Android 一启动游戏就弹出请求权限的框

排除是其他代码中的请求以后,是因为manifest需要添加一句:

<application> <meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" /></application>

如果不加这句,Unity打包运行到Android平台,每次进入Unity模块时,都会弹出一些权限提示框(即使是Android6.0以下的手机也会弹出)。

8.查找一些权限都是在工程中哪里有申请的

1)在Unity原工程下 查找 manifest里面有没有申请

2)在Unity原工程下的aar包中的manifest有没有申请( 有关aar可以查看另外一篇文章。)

3)Unity当调用某些特定的Unity api是否有自动添加的权限(导出Android工程或生成apk的时候),比如ACCESS_FINE_LOCATION 权限,查看这里

Git bash Error: Could not fork child process: There are no available terminals (-1)

windows gitbash终端开太多了吧

androidstudio中的gradle的存在位置

要安装gradle,然后发现没有单独下载的,好像都要用androidstudio下载才行。

下载androidstudio看看gradle的版本:

file--》project structure:

本地存放地址:

C:\Users\用户名\.gradle\wrapper\dists\gradle-5.4.1-all\3221gyojl5jsh0helicew7rwx\gradle-5.4.1\bin

file-》settings:搜gradle

gradle打包时报错 Could not dispatch a message to the daemon.

Could not dispatch a message to the daemon。这个问题是 进程被抢占,解决办法是把其他无关程序全部关闭。我这个是关闭了AndroidStudio。

Unity导出Android工程的时候,错误failed to allocate 190397160 bytes for output file: Not enough space 空间不够

c盘空间不够了

AndroidStudio安装的时候有个错误Unable to install Intel® HAXM

好像是跟模拟器有关的,先不管了

https://stackoverflow.com/questions/28418450/i-cant-install-intel-haxm

Execution failed for task ':app:packageDebug'.
> A failure occurred while executing com.android.build.gradle.tasks.PackageAndroidArtifact$IncrementalSplitterRunnable
> com.android.ide.common.signing.KeytoolException: Failed to read key AndroidDebugKey

打包的时候出错,看着是签名的时候。

所以应该是androidsdk的路径没有设置好
打包工具,要使用androidsdk 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/265404
推荐阅读
相关标签
  

闽ICP备14008679号