赞
踩
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在代码中设置。
目录
2.使用androidstudio打开,解决错误直到生成成功
PS.使用unity直接进行build成apk(选用的internal)的步骤大概:
对应api:
EditorUserBuildSettings.exportAsGoogleAndroidProject = true;
EditorUserBuildSettings.androidBuildSystem = AndroidBuildSystem.Gradle;EditorUserBuildSettings.SetBuildLocation(_buildTarget, targetFolder); //设置导出路径
UnityEditor.PlayerSettings.Android.useAPKExpansionFiles = true;//生成 obb
customgradletemplate这个没有找到对应的api。但是发现当勾选上以后,会自动在显示出来的路径上(Plugin/Android)添加一个gradle文件,而如果把勾选取消,就自动把.gradle文件的后缀改成了 .gradle.DISABLE。
勾选了这个以后会在Plugin/Android目录下自动生成一个默认的 mainTemplate.gradle 文件。
一般都会对这个文件进行自定义的修改来覆盖默认的配置或者新增一些配置(比如适配后续需要添加的android库工程,比如要去远端下载库文件,比如导入googleservice插件)
下面是项目中对 mainTemplate.gradle 文件进行的修改,左边是默认生成的,后边是修改的:
可以在对应的模块内增加内容;也可以删除他本身的宏,使用自己写的(对比下面的第二张第三张图)
在导出的过程中,**XXXX**中的都会被的设置上对应的值
如果不想用**XXXX**(Unity Editor中Playersetting中设置的值)就直接替换了就可以,比如上面的minsdkversion、targetsdkversion、applicationid,以及下面的versionCode和versionName:
关于gradle的各个含义下文会介绍。
对比两次界面修改后projectsettings文件夹下面的.asset文件(转成txt 用对比工具看)的修改,然后大概就知道api的接口名字了。
一般都是在PlayerSettings类和EditorUserBuildSettings类中。
.net配置不是很懂
https://zhuanlan.zhihu.com/p/44559662
通过Player设置中的Api Compatibility Level选项为Player构建选择.NET配置。Unity支持的两个.NET配置是:
.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可能是一个不错的选择。
导出的过程中,中间文件夹都在Temp目录下。有时候会提示一些错误,都可以在这里目录下进行查找。(如果是自己进行build生成apk,如果生成apk失败但是看不出原因,可以在这个Temp目录下找到中间的gradle工程,可以使用androidstudio打开进行构建,在androidstudio中构建看看有什么详细的错误信息)
针对某sdk的要求,把sdk方的库工程放到导出的Android工程中,并增加一些配置文件。
(因为这些都是在Unity导出工程的时候无法自动导出的。)
对修改过后的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看有什么错误依次解决。
针对上面的一些错误的修正使用脚本实现对导出的Android工程先做一些处理
然后使用 gradle 打包(找到gradle所在目录,调用gradle命令)
整个流程实现自动化打包
那么添加到plugin/android下面的库工程根目录必须有以下文件:
内容:
android.library=true
如果文件夹不包含 project.properties ,那么unity在生成apk或者导出android工程后不会包含此文件夹。
如果文件夹包含project.properties,但是不包含AndroidManifest.xml,导出也会报错。
一般在AndroidStudio中创建的库工程目录结构是如下所示的,但是上述说到直接放在Unity的Android文件夹下的库工程的根目录下需要有AndroidManifest.xml,所以AndroidStudio中创建的库工程不能直接放到Unity中使用。
一般是在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
https://www.jianshu.com/p/8d691b6bf8b4
https://cloud.tencent.com/developer/article/1037072
ApplicationResources:res文件夹下的文件 后面会讲到 (OtherResources:assets文件夹的)
ApplicationSourceCode:java源代码
R.java文件:根据App中的资源文件自动生成,可以理解为资源字典。
涉及到的工具:
资源+代码
APK: android platform package 安卓平台包。apk文件其实是zip格式。(apk后缀改成zip,再解压可以看内容。跟ios一样)
内容主要包括:
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包里的文件不能被随意替换。
assets目录下保存的是一些原始的文件,可以以任何方式来进行组织。这些文件最终会被原装不动地打包在apk文件中(apk直接解压出来就是有assets目录的内容和原始的是一样的)。
使用AssetManager类来完成对资源的访问,输入文件名即可:
- AssetManager am= getAssets();
- InputStream is = am.open("filename");
里面的资源文件名只能以小写字母和下划线做首字母,随后的名字中只能出现 [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.java生成在build文件夹中
R.java文件中的R类默认有attr、drawable、layout、string四个静态内部类,每个静态内部类分别对应着一种类型的资源。这些资源本身存在于res文件夹下。res文件夹下的资源文件与R.java文件里面类的对应关系,分成两类:
每一个文件都分别会在R.java文件里面生成drawable、layout、menu类的一个常量,常量的名字就是文件名字,常量值就是该资源的资源ID。
比如layout目录下的main.xml文件,那么生成在R.java中的就是:
public static final class layout {
public static final int main= 0x7f090000;
是根据文件里面的内容来生成相应的类常量,此文件夹下xml文件的根节点是resources,里面的标签名就是类名,属性就是常量名。
比如strings.xml 下的内容为,标签名是string,name属性值是 app_name:
- <resources>
- <string name="app_name">sdk</string>
- </resources>
那么生成在R.java中的就是:
- public static final class string {
- public static final int app_name= 0x7f0b0000;
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
@[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兼容包中的。
在布局文件中当我们需要为一些组件添加Id属性作为标识,可以使用如下的表达式:
@+id/button
“+”表示在R.java的名为id的内部类中添加一条记录。
在R.java文件中的id这个静态内部类添加一条常量名为button,该常量就是该资源的标识符。如果 id这个静态内部类不存在,则会先生成它。
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配置文件里面,里面可配置的项目有很多,具体可以用到的时候再查。
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版本
最少有三个,分别介绍:1个settings.gradle,在根目录下,2个或者多个 build.gradle 文件,一个在根目录下,一个在 app 目录下(如果有其他模块,就在其他模块下)。
下面介绍这三种类型的具体配置项目:
定义哪些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中编译哪些工程
为所有子项目/模块添加常见的配置选项。边看本地的这个文件边看这个注释
1)buildscript{ }块——gradle脚本自身需要使用的资源
repositories{ }——仓库,配置Gradle代码托管库,设置之后可以在项目中轻松引用仓库上的开源项目了。Gradle预先配置了远程支持JCenter、Maven、Central和lvy等存储区,当然也可以指定本地自定义的远程存储库。
google()——google的官方仓库
jcenter(),mavenCentral()——出名的公共中央仓库
dependencies{ }——依赖,默认设置了项目依赖Gradle的插件版本路径;指的是gradle脚本自身执行所需依赖(Gradle插件) 所以如果你没有引入远程的Gradle插件,那么就不用在buildscript {}下的dependencies下添加依赖。
- buildscript {
- repositories {
- google()
- jcenter()
- // 导入XXSDK仓库
- maven{
- url "http://repo.xxxxxxxxx.com/bale/repo"
- }
- }
- dependencies {
- classpath 'com.android.tools.build:gradle:3.4.0'
- classpath 'com.google.gms:google-services:4.3.3'
-
- // NOTE: Do not place your application dependencies here; they belong
- // in the individual module build.gradle files
- }
- }
在AS中可以看到gradle的版本号和gradle插件的版本号:
2)allprojects{ }块——配置所有模块中都需要使用的依赖项
这个是项目本身需要的依赖(普通代码库);
上面说的buildscript是gradle这个工具本身需要的依赖。
- allprojects {
- repositories {
- google()
- jcenter()
- // 导入XXSDK仓库
- maven{
- url "http://repo.xxxxxxx.com/bale/repo"
- }
- }
- }
3)可以定一些自定义的task——语法
比如 cleantask
- task clean(type: Delete) {
- delete rootProject.buildDir
- }
运行gradle clean时,执行此处定义的task。该任务继承自Delete,删除根目录中的build目录。相当于执行Delete.delete(rootProject.buildDir)。其实这个任务的执行就是可以删除生成的Build文件的,跟Android Studio的clean是一个道理。
task更多介绍 见 https://blog.csdn.net/u012138730/article/details/90734179
可以理解VS中对于整个解决方案的配置。
多个模块,就是多个配置文件,分别在模块文件夹的根目录下。详细看这里
介绍以下四个部分的定义:
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目录,比如:
- defaultConfig {
- minSdkVersion 17
- targetSdkVersion 29
- applicationId 'com.xxx.xxx'
- ndk {
- abiFilters 'armeabi-v7a', 'arm64-v8a'
- }
- versionCode 16
- versionName '1.2.0'
- }
sourceSets{} ——源代码集合,是Java插件用来描述和管理源代码及资源的一个抽象概念,是一个Java源代码文件和资源文件的集合,我们可以通过sourceSets更改源集的Java目录或者资源目录等。
如下图通过sourceSets告诉Gradle关于jni so包的存放路径就在app/libs/ABI目录上(不定义的话,肯定有个默认路径的,默认是放在 main/jniLibs/ABI目录 上的)
- sourceSets{
- main{
- jniLibs.srcDirs = ['libs']
- }
- }
buildTypes{} ——构建类型,内置了release{}和debug{}。应该还可以自己定义新的名字。release{}和debug{}这两种模式主要区别在于,能否在设备上调试以及签名不一样,其他代码和文件资源都是一样的。一般设置代码混淆,minifyEnabled=true就会开启混淆:
(可以理解vs的debug还是release版本,其实就是可以对应设置不同的参数,可能跟ios包的dev证书和dis证书比较相似)
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- }
- }
signingConfigs{} ——默认情况下,debug构建类型的签名已经被配置好了,使用的就是Android SDK自动生成的debug证书,它一般位于$HOME/.android/debug.keystore,其key和密码是已经知道的,一般情况下我们不需要单独配置debug模式的签名信息。
3)productFlavors{} ——可选,配置多渠道打包工具,根据配置不同的逻辑、构建部分来实现版本的差异化
直接定义了两个渠道,一个是free,一个是paid,设置不同的applicationId:
- productFlavors {
- free {
- applicationId 'com.example.myapp.free'
- }
- paid {
- applicationId 'com.example.myapp.paid'
- }
- }
或者定义为空,但是在app/src下面,分别创建和main同级目录的文件夹free, paid, 这两个文件夹里面都各只有一个AndroidManifest.xml文件,free下的AndroidManifest.xml文件只需要如下(猜的):
- productFlavors{
-
- free { }
-
- paid { }
-
- }
- <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myapp.free">
-
- <application>
-
- </application>
-
- </manifest>
另外,可以用manifestPlaceholders占位符(Gradle Android插件里的一个功能)的例子:
- productFlavors {
- free {
- applicationId 'com.example.myapp.free'
- manifestPlaceholders= [APP_ICON: "@drawable/ic_launcher",APP_NAME:applicationId]
- }
- }
上面定义了 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库上的开源项目添加依赖关系。appcompat和constraint属于远程依赖。先build.gradle 中添加远程仓库地址的引用:
- allprojects {
- repositories {
- // google的官方仓库
- google()
-
- // 出名的公共中央仓库
- jcenter()
- mavenCentral()
-
- //如果有私库,也要添加链接
- //....
- }
- }
然后在目标 module 的 build.gradle 中添加具体 aar 的依赖(implementation):
- dependencies {
- implementation 'com.android.support:support-v4:25.3.1'
- }
依赖包的类型有——jar包、aar包、so包。
引入依赖的声明——implementation、api、compile only、runtime only。具体区别和用法:文章1,文章2,官网介绍。
- apply plugin: 'com.android.application'
-
- android {
- compileSdkVersion 28
- buildToolsVersion '26.0.2'
-
- signingConfigs {
- release {
- storeFile file("xxx")
- storePassword "xxx"
- keyAlias "xxx"
- keyPassword "xxx"
- }
- }
- defaultConfig {
- applicationId "com.xxx.xxx"
- minSdkVersion 19
- targetSdkVersion 28
- versionCode 1
- versionName "1.0.0"
- }
- lintOptions {
- abortOnError false
- }
- buildTypes {
- debug {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
- }
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
- signingConfig signingConfigs.release
- }
- }
-
- packagingOptions {
- exclude 'META-INF/ASL2.0'
- exclude 'META-INF/LICENSE'
- exclude 'META-INF/NOTICE'
- exclude 'META-INF/DEPENDENCIES'
- exclude 'META-INF/LICENSE.txt'
- }
- repositories{
- flatDir{
- dirs 'libs'
- dirs 'libs','../xxx/xxx/xxx/xxx'
- }
- }
-
- }
-
- dependencies {
- compile fileTree(include: ['*.jar'], dir: 'libs')
- compile project(':xxx:xxx:xxx')
- }
- apply plugin: 'com.google.gms.google-services'
gradle.properties——位于项目根目录下,主要设置Gradle后台进程JVM内存大小;日记级别;设置全局常量,可以供build.gradle中使用;
local.properties——为Gradle配置环境变量,例如sdk、ndk路径;
(properties文件,groovy文件,gradle文件,每种文件如果是内容如其名的话,都是有相应的格式的。properties文件就是键值对的格式)
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)
如果需要增加新的android sdk,可以在android studio的setting中搜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/
在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打开看看就行
sdkmanager "platform-tools" "platforms;android-28"——安装软件包
有adb
这里包含:
我的unity打包apk,使用的构建工具就是29
platformBuildVersionCode="29" platformBuildVersionName="10"
SDK Platform 该版本编译好的SDK,必须装的
使用unity打包apk,使用编译sdk版本就是29
compileSdkVersion="29" compileSdkVersionCodename="10"
源代码,一个是学习Google优秀的源代码,二个是查看源码方便调错。
unity使用的android sdk版本是29,但是一个第三方的sdk的目标level是28,打出的apk的targetsdkversion就是29的。而这个包在android29的系统中会崩溃,因为第三方sdk的目标level是最高是28的。
所以unity中targetsdkversion也是设置成28,这样打出来的包的targetsdkversion就是28的了。在android level29中就不会崩溃。
如果第一张 into 的图中的 目录文件夹中包含加锁的文件的话,就会出现如下错误。加入into的文件夹是 android studio工程中根目录中有 .gradle文件夹,如果拷贝到这个目录下就不行,会出错。
有关Gradle中的task的介绍可以查看另外一篇文章。
因为要把targetSDKVersion和compileSdkVersion改到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"
把
android:theme="@android:style/Theme.AppCompat.Light.DarkActionBar" />
去掉android:: 改成
android:theme="@style/Theme.AppCompat.Light.DarkActionBar" />
就好了
v7的兼容包不能加Android
在Android 10之前的版本上,我们在做文件的操作时都会申请存储空间的读写权限。
但是这些权限完全被滥用,造成的问题就是手机的存储空间中充斥着大量不明作用的文件,并且应用卸载后它也没有删除掉。
为了解决这个问题,Android 10 中引入了 Scoped Storage 的概念,通过添加外部存储访问限制来实现更好的文件管理。
最简单粗暴的方法就是在 AndroidManifest.xml 中添加 android:requestLegacyExternalStorage="true" 来请求使用旧的存储模式。
在下一个版本的Android中,此条配置将会失效,将强制采用外部储存限制。
https://www.jb51.net/article/181745.htm
因为不知道这个,在主线程中进行了网络请求,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
上传的时候提示跟上一次签名不对应,是自己签名文件使用的有问题
可以自己检查一下签名是不是对了,再上传:
解压一下apk,然后:
keytool -printcert -file xxx.rsa
或者直接看:
keytool -printcert -jarfile XXXX.apk
有关Apk中的签名的介绍可以查看另外一篇文章。
排除是其他代码中的请求以后,是因为manifest需要添加一句:
<application> <meta-data android:name="unityplayer.SkipPermissionsDialog" android:value="true" /></application>
如果不加这句,Unity打包运行到Android平台,每次进入Unity模块时,都会弹出一些权限提示框(即使是Android6.0以下的手机也会弹出)。
1)在Unity原工程下 查找 manifest里面有没有申请
2)在Unity原工程下的aar包中的manifest有没有申请( 有关aar可以查看另外一篇文章。)
3)Unity当调用某些特定的Unity api是否有自动添加的权限(导出Android工程或生成apk的时候),比如ACCESS_FINE_LOCATION 权限,查看这里。
windows gitbash终端开太多了吧
要安装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
Could not dispatch a message to the daemon。这个问题是 进程被抢占,解决办法是把其他无关程序全部关闭。我这个是关闭了AndroidStudio。
c盘空间不够了
好像是跟模拟器有关的,先不管了
https://stackoverflow.com/questions/28418450/i-cant-install-intel-haxm
打包的时候出错,看着是签名的时候。
所以应该是androidsdk的路径没有设置好
打包工具,要使用androidsdk
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。