App架构师实践指南三之基础组件

1、基础组件库
随着时间的增长,代码量的逐渐积累,新旧项目之间有太多可以服用的代码。下面是整理的公共代码库。

2、关于加密
密钥的保护以及网络传输安全是移动应用安全最关键的内容,涉及密码学(用于加密、认证和鉴定的学科)。常见的加密算法,主要分为对称加密算法、非对称加密算法和Hash算法。
---对称加密算法。安全性取决于加密算法本身和密钥的私密性,相对于非对称加密算法,密钥管理比较难,速度快几个数量级,适合大数据量的加密处理,对称加密算法流程图如图6-6所示。

---非对称加密算法。非对称加密算法中需要公开密钥(public key)和私有密钥(private key)两个密钥,密钥与数据是一一对应的。密钥容易管理,安全性高,但加解密速度慢,适合小数据量加解密或数据签名,非对称加密算法流程如图6-6(b)所示。
---Hash(哈希)算法。Hash函数是一种将任意长度的消息压缩到某一固定长度(消息摘要)的函数(该过程不可逆),可用于数字签名、消息的完整性检测、消息起源的认证检测等。Hash算法常见的有MD5、SHA、HMAC、RIPEMD、HAVAL、N-Hash、Tiger等。
具体选择和使用时,对称加密算法建议选择AES,非对称加密算法建议选择ECC或RSA,消息摘要可以用MD5,数字签名相关可以用DSA等。如果使用OkHttp网络库,可以通过OkHttp Builder等certificatePinner方法预设服务端证书等pinging值,也可以通过interceptor插入加解密代码。
---Base64.不要使用Base64来加密数据,Base64只是一种编码方式。
---随机数。使用SecureRandom代替Random类来获取随机数,但注意不要为SecureRandom设置种子。
---Hash算法。建议使用SHA-256、SHA-3算法代替MD2、MD4、MD5、SHA-1、RIPEMD算法来加密用户密码等敏感信息,后者已有很多破解算法。对多个串联字符串做Hash加密,要注意避免Hash值一样。
---消息验证算法。建议使用HMAC-SHA256算法,避免使用CBC-MAC.
---对称加密算法。DES默认的是56位的加密密钥,已经不安全,不建议使用,建议使用AES算法(不要使用Android默认的ECB模式,显示置顶位CBC或CFB模式)。
---非对称算法。密钥长度不要低于512位,建议使用2048位的密钥长度。RSA加密算法应使用Clipher.getInstance(RSA/ECB/OAEPWithSHA256AndMGF1Padding),否则会存在重放攻击的风险。

---密钥存储。动态/运行时密钥存储用Android Keystore,其提供类随机密钥生成和存储密钥功能,其key是依托于硬件的KeyChain存储在系统中,而非App目录下,其他应用是无法访问获取的,预存密钥通过so库预设key/secret存储。

3、启动引导模块
通用简单型启动引导页逻辑:用户单击启动-->启动页(延时或网络加载等)-->引导页-->主页。
如果不是第一次启动,则逻辑变为:用户单击启动-->启动页-->主页。
采用MVP模式,业务逻辑在Presenter中完成,UI相关中**view和**Activity中呈现。

4、注册登陆模块
从产品角度来看,一个App按照是否需要登陆可以分为3类:第一类是依托账号建立产品服务的(如微信),必须登陆;第二类是按需登陆的(如知乎等),浏览无需登陆,收藏/评论等需要登陆;第三类是无需登陆的,主要是工具类应用,如计算器。所以,不同应用对注册登陆模块会有不同的要求,同时用户注册/登陆也是多样性的,可以通过用户名、邮箱账号、手机账号等注册/登陆,另外,现在三方登陆(微信/qq/微博等)也是常见的一种方式。

5、编译打包
---SRC-->DEX(Dalvik Executable)/RES
---- 使用AAPT(The Android Assert Packaing Tool)编译打包资源文件,生成R.java文件、resource.arsc文件和打包资源文件。
---- 使用AIDL(Android Interface Definition Lauguage)处理.aidl文件,生成.java文件
---- 使用Java Compiler(javac)工具,将源码编译成.class文件
---DEX-->APK。使用apkbuilder工具,将资源文件和.dex文件生成未签名的APK安装文件。
---APK sign。使用jarsigner工具,进行APK签名【分为两种:一种是用于调试的debug.keystore(自动生成);另一种是用于发布的release.keystore(手动生成)】

---APK align。使用zipalign工具,将签名后的APK进行对齐处理。

6、Gradle实用技巧

Gradle是一种基于Groovy语法的项目构建工具,其运行在JVM上,借鉴了脚本语言诸多特性,兼容java,可直接使用java各种类库。
---Gradle Task。Task(任务)是Gradle中的一个核心概念,每一个声明的任务都可以看作是一个任务对象,可以拥有自己的属性和方法(默认类型是DefaultTask),同java中java.lang.Object类似。人物之间可以相互依赖,使用关键字dependsOn,还可以通过doFirst和doLast等在任务执行生命周期中插入具体业务逻辑,常见的任务类型有用于复制的Copy、用于打包的Jar、用于执行的JavaExec等。
---- gradle assemble,生成所有渠道Debug和Release包
---- gradle assembleAndroidTest,生成所有渠道的测试包。
---- gradle assembleDebug,生成所有渠道等Debug包。
---- gradle assembleRelese,生成所有渠道的Release包。
---- gradle assebleXXX,生成某个渠道的Debug和Release包。

---Gradle加速。

---- 常规设置。如开启Gradle daemon进程等(gradle.properties文件,建议使用全局配置),代码如下
org.gradle.daemon=true //开启Gradle守护进程
Org.gradle.jvmargs=-Xmx2048 -XX:MaxPermSize=512m --XX:+HeapDumpOnOutOfMemoryError //JVM内存
Org.gradle.parallel=true //并行项目执行(多module依赖复杂慎用)
org.gradle.configureondeamand=true

----开启增量编译。在对应module多build.gradle文件中,按如下设置
dexOptions{
incremental true
}

----屏蔽不需要多Task。屏蔽不需要多Task或特定的Task,按如下设置。
//屏蔽系统Task
tasks.whenTaskAdded{task ->
if(task.name.contains("lint")) //跳过lint检查
||task.name.equals("clean") //如果instant run不生效,把clean这行去掉
||task.name.equals("Aidl") //如果项目中有用到aidl,则不可以舍弃这个任务
||task.name.equals("mockableAndroidJar") //用不到测试的时候,就可以先关闭
||task.name.equals("UnitTest")
||task.name.equals("AndroidTest")
||task.name.equals("Ndk") //用不到NDK和JNI的也可以关闭掉
||task.name.equals("Jni")

){
task.enabled = false
}
}

//屏蔽指定Task XX
gradle.taskGraph.whenReady{
Tasks.each{task ->
if(task.name.contains("XX")){
task.enabled = false
}
}
}

----代理设置。在根目录的gradle.properties中配置,代码如下。
systemProp.http.proxyHost=127.0.0.1
systemProp.http.proxyPort=1010
systemProp.https.proxyHost=127.0.0.1
systemProp.https.proxyPort=1010

---Google官方关于Gradle加速的17条实用建议
---- 通过productFlavors设置build variant,针对不同product保留对应的配置信息,加速构建,类似多渠道打包。
---- 避免编译不必要的资源。如dev包通过设置resConfigs “en”“xxhdpi”,只使用英文string资源和xxhdpi的屏幕密度资源,代码如下。
productFlavors{
Dev{
...
//the following configuration limits the "dev"flavor to using
//English string resources and xxhdpi screen-density resources.
resConfigs "en","xxhdpi"
}
...
}
----配置debug构建的Crushlytics为Disable(Crushlytics为崩溃上报分析工具,Debug阶段可能并不需要),如果Debug期间需要开启Crushlytics,那也可以设置alwaysUpdateBuildId为false,避免每次都更新ID,代码如下
Android{
...
buildTypes{
debug{
ext.enableCrashlytics = false
ext.alwaysUpdateBuildId = false
}
}
}
----用静态的构建配置来构建你的Debug版,避免在Debug下使用动态配置(如version codes,version names,resources等),类似下面要阐述的版本号/依赖统一管理
----用静态的版本依赖,避免使用+号
Com.android.tools.build:gradle:2.+ //动态依赖
Com.android.tools.build:gradle:2.3.0 //静态依赖
----配置on demand 为enable状态,指定Gradle仅能配置你想要构建的Modules。
Android Studio路径为:File-->Settings-->Build-->Compiler-->check Configure on demand.
----建议使用library模块,模块化代码抽离。
----当你的构建消耗时间过长时,如果存在较复杂和独立的构建逻辑,考虑将其创建为独立的Tasks(自定义Gradle插件),按需使用。
----配置dexOptions(Android Studio 2.1新增)和开启library pre-dexing(DEX预处理)。两者都是针对DEX构建优化,dexOptions可以配置包括preDexLibraaies、maxProcesCount和javaMaxHeadSize,代码如下。
android{
...
dexOptions{
preDexLibraries true
maxProcessCount 8
//instead of setting the heap size for the DEX process, increase Gradle's
//heap size to enable dex-in-process.
//javaMaxHeapSize "2048m"
}
}
----增加Gradle堆大小(开启Dex-in-process).Dex-in-process默认允许多个DEX进程运行在一个单独的VM中,所以可以通过分配足够的内存来开启这个特性(Android Studio 2.1+)
----将图片转换成WebP格式,不用在构建时做压缩。WebP是一种具备JPEG类似的有损压缩和PNG的透明支持的高压缩质量的图片格式,同时可以减少包Size。
----禁止使用PNG crunching。也是一种禁止构建时默认压缩图片的方法。
android{
...
aaptOptions{
cruncherEnabled false
}
}
----使用Instant Run.
----使用构建缓存,Anroid Gradle插件2.3.0+默认开启了构建缓存。
----避免使用注解处理器,使用注解处理器时将导致增量构建不可用。
----Profile your build。这条主要针对那些超级App(拥有大量自定义构建逻辑等),需要知晓每个阶段/每个Task的时间消耗来优化那些耗时逻辑,build profile的生成通过在Android Studio的命令行中操作(View-->Tool Windows-->Terminal),具体如下:
------清除:gradlew clean(Windows)或./graldew clean(Mac)
------构建:gradlew-->profile-->recompile-scripts-->offline-->rerun-tasks assembleFlavorDe不过(其中,profile表示开启profiling;offline表示禁止Gradle获取离线依赖,防止Gradle更新数据影响报告;rerun-tasks表示强制Gradle返回所有Task并忽略任何Task的优化;recompile-scripts表示强制脚本重新编译跳过cache)。
-----查看:找到project-root/build/reports/profile/目录下的profile_timestamp.html文件,在浏览器中打开即可呈现完整时间消耗的构建报告。
----项目组件化。

---多渠道打包。其本质上productFlavors的使用,结合占位符与AndroidManifest的使用,可以为不同渠道设置不同包名。另外,还可以结合脚本实现快速渠道打包,开源项目packer-ng-plugin声称100个渠道打包只需要10s。

productFlavors{
dev{
applicationIdSuffix ".debug" //不同包名设置,便于线上和开发包安装同一首手机
}
google pay{}
qihoo360{}
xiaomi{}
Tencent{
manifestPlaceholders = [UMENG_CHANNEL:"Tencent"] //结合占位符
}
}

---Gradle通用技巧
----Log开关控制。定义动态编译生成对象,通过buildConfigField控制,然后在java代码中通过BuildConfig.enableLog来获取,代码如下。
buildTypes{
debug{
buildConfigField("boolean","enableLog","true")
}
release{
buildConfigField("boolean","enableLog",“false”)
}
}

----版本号/依赖统一管理。建立独立的gradle(config.gradle),然后apply from进当前gradle,通过设置project.ext,再通过rootProject.ext进行引用,以下代码为XKnife-Android的global_config.gradle文件的一部分。
ext{
abortOnLintError = false
checkLintRelease = false

android= [compileSdkVersion : 24,
buildToolsVersion : "25.0.2",
applicationId : "com.skyseraph.xknife",
applicationIdUserLogin : “com.skyseraph.xknife.module.userlogin”,
applicationIdLaunch : "com.skyseraph.xknife.module.launch",
applicationIdUpgrade : "com.skyseraph.xknife.module.upgrade",
minSdkVersion. : 15,
targetSdkVersion. : 24,
versionCode : 1,
versionName : "1.0.0",
testInstrumentationRunner: "android.support.test.runner.AndroidJUnitRunner"

]
... ...
}

//使用
applicationId rootProject.ext.android ["applicationId"]

另外,还可以在gradle.properties文件中定义一些统一的编译常量(如定义常量XX=1,然后在需要的module中通过project.XX引用)。
----APK输出名字定制化。定制化APK输出名字,自动加上版本号、时间等信息,避免手动重命名
applicationVariants.all{variant ->
variant.outputs.each{output ->
output.outputFile = new File(
output.outputile =new File(
output.outputFile.parent + "/${variant.buildType.name}","XXX-
${variant.buildType.name}-${variant.versionName}-${variant.
productFlavors[0].name.apk".toLowerCase())
}
}
----构建不同的名称、版本号和App ID等,代码如下
buildTypes{
debug{
applicationIdSuffix ".debug"
versionNameSuffix "-debug"
resValue "string","app_name","XXX(debug)"
}
release{
resValue "string","app_name","XXX"
}
}
----修改默认的Build配置文件名(settings.gradle文件)
rootProject.buildFiledName = xx.gradle

----java版本设置。在Gradle中设置java版本,代码如下。
compileOptions{
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility javaVersion.VERSION_1_8
}

App架构师实践指南三之基础组件的更多相关文章

  1. App架构师实践指南六之性能优化三

    App架构师实践指南六之性能优化三 2018年08月02日 13:57:57 nicolelili1 阅读数:190   内存性能优化1.内存机制和原理 1.1 内存管理内存时一个基础又高深的话题,从 ...

  2. App架构师实践指南五之性能优化二

    App架构师实践指南五之性能优化二 2018年07月30日 13:08:44 nicolelili1 阅读数:214   从UI和CPU方面来说App流畅体验优化,核心为流畅度/卡顿性能优化. 1.基 ...

  3. App架构师实践指南四之性能优化一

    App架构师实践指南四之性能优化一     1.性能维度常见用来衡量App性能的维度如图9-1所示.其中,性能指标包括电池(电量/温度).流量(上行流量/下行流量等).CPU(平均/最大/最小).内存 ...

  4. App架构师实践指南二之App开发工具

    App架构师实践指南二之App开发工具     1.Android Studio 2.编译调试---条件断点.右键单击断点,在弹出的窗口中输入Condition条件.---日志断点.右键单击断点,在弹 ...

  5. App架构师实践指南一之App基础语法

    第二章:App基础语法1.编程范式编程范型或编程范式(programming paradigm),是指从事软件工程的一类典型的编程风格.常见的编程范式有过程化(命令行)编程.事件驱动编程.面向对象编程 ...

  6. 网易新闻App架构重构实践:DDD正走向流行

    网易新闻App架构重构实践:DDD正走向流行 https://mp.weixin.qq.com/s/FdwrT_xn3CQqpWoRVBttvQ 小智 InfoQ 2020-05-14 作者 | 小智 ...

  7. Swift语言指南(三)--语言基础之整数和浮点数

    原文:Swift语言指南(三)--语言基础之整数和浮点数 整数 整数指没有小数的整数,如42,-23.整数可以是有符号的(正数,零,负数),也可以是无符号的(正数,零). Swift提供了8,16,3 ...

  8. 0.Python 爬虫之Scrapy入门实践指南(Scrapy基础知识)

    目录 0.0.Scrapy基础 0.1.Scrapy 框架图 0.2.Scrapy主要包括了以下组件: 0.3.Scrapy简单示例如下: 0.4.Scrapy运行流程如下: 0.5.还有什么? 0. ...

  9. Java架构师最关键三个思维转变方式,框架的合理运用

    很久没有写思维的文章,特别是在写完思维的逻辑和思维的框架后,对于理论层面的自己也不太想写,但是对于实际案例层面的写起来又比较花时间,而且案例基本在IT专业领域不是所有人都能看明白. 我们前面写过思维的 ...

随机推荐

  1. Linear Algebra(未完待续)

    [矩阵消元] The result of multiplying a matrix by some vector is a combination of the columns of the matr ...

  2. 对 Laravel 的 Controller 做 Unit Test

    之前尝试过对 Laravel 的 Controller 做 Feature Test,但是在业务变得越来越复杂之后,我感觉对 controller 里的函数也没了自信,急需对功能函数做 Unit Te ...

  3. 关于ie7下display:inline-block;不支持的解决方案。

    摘要: 声明:此文章为转载(点击查看原文),如有侵权24小时内删除.联系QQ:1522025433. 今天码的时候遇到这个问题了. 如果本身是内联元素的,把它的display属性设置设置为inline ...

  4. Bootstrap表格中,thead固定,tbody有垂直滚动条

    1.html源码:这里的table是使用的vue写法,实际生成的表格和一个一个写的tr th td无异 <div class="panel-body no-padding"& ...

  5. CSS3:HSL和HSLA

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  6. VMware虚拟机 Ubuntu 16.04 安装

    第一步:VMware虚拟机 Ubuntu 16.04 安装 第二步: 解决窗口全屏问题 linux下给root用户设置密码 修改root用户的密码 $ sudo passwd root 密码会要求重复 ...

  7. Codeforces 327E Axis Walking 状压dp

    这题真的有2500分吗... 难以置信... #include<bits/stdc++.h> #define LL long long #define fi first #define s ...

  8. Frosh Week HDU3743(逆序数)

    离散化加 求逆序数: 求逆序数的方法 一个是归并排序  一个是树状数组 #include<bits/stdc++.h> using namespace std; int n; struct ...

  9. 关于Jar包 和 war

    Jar包: 别人写好的java类打包,将这些jar包引入你的项目中,然后就可以直接使用这些jar包中的类和属性以及方法,一般都会放在lib目录下 war 是web项目

  10. Burp Suite之爬网模块(二)

    Spider功能 Burp Spider爬网介绍 Burp Spider 是一个映射 web 应用程序的工具.它使用多种智能技术对一个应用程序的内容和功能进行全面的清查. 通过跟踪 HTML 和 Ja ...