zoukankan      html  css  js  c++  java
  • App架构师实践指南三之基础组件

    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
    }

  • 相关阅读:
    xml=>数组
    php的session锁
    压缩服务器中的文件夹,并下载到电脑
    通过onkeydown事件来控制只允许数字
    简单算法
    memcahe安装
    HTML div css 强制 换行 不换行
    windows charles response 乱码解决办法
    根据字节流判断内容是否使用UTF-8编码
    nginx安装过程
  • 原文地址:https://www.cnblogs.com/timssd/p/10534597.html
Copyright © 2011-2022 走看看