构建Android应用

来源:互联网 发布:js打砖块游戏图片素材 编辑:程序博客网 时间:2024/05/16 18:01

RDC Android基础构建设计

author: liuwang.zhong
version:0.1.0

    • RDC Android基础构建设计
      • 前言
      • 开发工具
      • 应用构建
        • 默认配置
        • 应用打包
        • 工程框架
      • 网络接口设计
        • Response基本格式
        • 虚拟远程服务
      • 代码规范与规定
        • JAVA基本命名规约
        • Android内的规约
      • 工具类
      • 其他

前言

对于Android的构建流程来说,更多的是关注我们的一些所谓“规定”。这些规定不一定是需要去追随,可以由我们员工们自行选择。其中的规定也会随着工程、项目而改变。这只是一些意见,我们希望可以达到一种效应:Android的代码有着自己公司员工的共同审美,接受我们这种命名、分类、流程,进而做好构建出一个个健壮应用的准备。

开发工具

一般工具有:AndroidStudio,JDK,Gradle,Git等。
对于Android Application的开发工具采用AndroidStudio。当前采用的版本号为:2.3.1。下载时尽量,下载不带SDK版本的,自带SDK版本的问题比较多。JDK的JAVA版本下载:1.8.0_112版本。Gradle版本为:3.3。工具下载地址表

工具名称 下载地址 AndroidStudio http://www.androiddevtools.cn/ JDK http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html Gradle http://pan.baidu.com/s/1pLEkm4F#list/path=%2F Git https://github.com/git-for-windows/git-sdk-64

环境变量配置情况如下:

  • java环境变量
  • adb shell 环境变量
  • SDK 环境变量
  • gradle 环境变量

配置代码如下

#Java环境变量JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_65.jdk/Contents/Homeexport JAVA_HOME#NDK环境变量export NDK_HOME=/Users/**/Library/Android/sdk/ndk-bundle/export PATH=$NDK_HOME:$PATH# android工具环境变量export ANDROID_HOME=/Users/**/Library/Android/sdkexport emulator=/Users/**/Library/Android/sdk/emulator/export PATH=$emulator:$PATHexport PATH=$ANDROID_HOME/tools:$PATHexport SDK_MANAGER=/Users/**/Library/Android/sdk/tools/bin/export PATH=$SDK_MANAGER:$PATHexport PATH=$ANDROID_HOME/platform-tools:$PATH#gradleexport GRADLE=/Users/**/gradle/gradle-3.3export PATH=$GRADLE/bin:$PATH#**代表用户名

应用构建

默认配置

  • gitignore配置

工程结构是一个Project非Module。工具结构和AndroidStudio默认的一样。代码使用Git库管理,Project的gitignore文件内容

# Gradle files.gradlebuild# Local configuration file (sdk path, etc)local.properties.idea/workspace.xml.idea/libraries# IntelliJ project files**.iml.idea# ignore the mac file.DS_Store#other.externalNativeBuildcaptures
  • projectGradle配置

工程的Project的build.gradle需要配置一下公用的配置,主要是default setting的内容,达到工程的统一配置,而且也可以避免support版本不一致导致的BUG。内容如下:

 // Top-level build file where you can add configuration options common to all sub-projects/modules.buildscript {    repositories {        jcenter()    }    dependencies {        classpath 'com.android.tools.build:gradle:2.3.1'        // NOTE: Do not place your application dependencies here; they belong        // in the individual module build.gradle files    }}allprojects {    repositories {        jcenter()    }}task clean(type: Delete) {    delete rootProject.buildDir}//default settingext {    //sdk version    base_compile_sdk_version = 25    //build tool version    base_build_tools_version = '25.0.2'    //min sdk version    base_min_sdk_version = 15    //target sdk version    base_target_sdk_version = 24    //support library version    base_support_version = '25.3.1'}

引用列子

apply plugin: 'com.android.application'android {    compileSdkVersion base_compile_sdk_version    buildToolsVersion base_build_tools_version    defaultConfig {        applicationId "com.richdataco.testandroidstudio"        minSdkVersion base_min_sdk_version        targetSdkVersion base_sdk_version        versionCode 1        versionName "1.0"        //省略}dependencies {    //省略    compile "com.android.support:appcompat-v7:$base_support_version"    compile "com.android.support:appcompat-v4:$base_support_version"}
  • 兼容包开发

工程的开发必须采用兼容包开发。使用v7,v4等来构建app,不能直接使用Activity这种开发,其次,我们的测试样机必须有三个点:Android4.4,Android5.0,Android6.0。兼有问题表如下:

常见兼有问题 常见兼容详情 解决方案 键盘兼容 对于目前的手机,有点手机采用的是软菜单键和物理按键,所以要防止,UI界面出现的软键盘挡住了,无法点击Tab 设置软键盘在UI之下,测试可以用华为的软键盘测试 AsyncTask兼容 对于AsyncTask尽量不用使用来处理大任务,要不会出现异常 采用Thread任务队列进行处理 打开网络兼容 对于低版本的手机是可以通过反射等操作进行打开移动网络,其实这些操作是危险的,而且不必要的 不要实现这些功能,是伪需求 动态权限的兼容 对于Android6.0的机器都是采用动态权限了,我们必须进行兼容,要不然,会出现在Android6.0上运行无缘无故打不开app,一安装就shutdown等问题 添加动态权限处理 动画兼容 对于使用到属性动画的技术,必须要进行兼容,因为这是在Android3.0加进来的独立动画框架 采用com.nineoldandroids:library兼容包开发 support包兼容 由于采用的support兼容包得版本不一致也会导致问题 按照我们队project的Gradle配置进行,就可达到统一版本 对于状态栏兼容 由于需要实现沉淀式的状态栏,这时候需要进行兼容,要不会出现setContentView异常 尽可能得进行多个Android版本的手机测试 向后兼用 对于向后兼容,可以看到google的support包的努力,采用这些包开发会大大减少我们向后兼容的工作 使用Support进行开发 SO库兼容 对于SO库来说,这是基于芯片进行编译的,所以一定程度上是削弱了兼容性 要拆开来看看so库提供的情况进行判断,最好可以提供arm64-v8a,x86_64,x86,armeabi,armeabi-v7a WebView兼容 对于WebView的问题说不清,但是要有意识去兼容,因为它是出现bug的交通事故多发地段 多测试,多思考

应用打包

应用打包采用Gradle进行打包。下面有一个Gradle打包模板,模板如下:

import java.text.SimpleDateFormatapply plugin: 'com.android.application'android {    compileSdkVersion base_compile_sdk_version    buildToolsVersion base_build_tools_version    defaultConfig {        applicationId "com.richdataco.base"        minSdkVersion base_min_sdk_version        targetSdkVersion base_target_sdk_version        versionCode 1        versionName "1.0"        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"        externalNativeBuild {            cmake {                cppFlags ""            }        }    }    signingConfigs {        config {            storeFile file('./keys/BaseKey.jks')            keyAlias 'BaseKey'            keyPassword 'rdc@2016'            storePassword 'rdc@2016'        }    }    buildTypes {        debug {            //配置是打印log            buildConfigField "boolean", "LOG_DEBUG", "true"            minifyEnabled false            //关联签名            signingConfig signingConfigs.config            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }        release {            //配置不打log            buildConfigField "boolean", "LOG_DEBUG", "false"            minifyEnabled false            //关联签名            signingConfig signingConfigs.config            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }    }    //打包类型    productFlavors {        //debug版本,注意applicationId最好不要和release版本一致,方便测试,        // 而且可以防止测试人员用debug版本去发布        run_debug {            applicationId "com.richdataco.demo_bug"        }        //release版本        app_release {            applicationId "com.richdataco.demo"        }    }    externalNativeBuild {        cmake {            path "CMakeLists.txt"        }    }    lintOptions {        abortOnError false    }    //输出文件    applicationVariants.all { main ->        main.outputs.each { output ->            def file = output.outputFile            output.outputFile = new File(file.parent,                    "comm_demo_" + main.buildType.name +                            "_v_" + main.versionName + "_"                            + buildTime() + ".apk");        }    }}def buildTime() {    def df = new SimpleDateFormat("yyyyMMdd")    df.setTimeZone(TimeZone.getDefault())    return df.format(new Date())}dependencies {    compile fileTree(include: ['*.jar'], dir: 'libs')    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {        exclude group: 'com.android.support', module: 'support-annotations'    })    compile "com.android.support:appcompat-v7:$base_support_version"    compile 'com.android.support.constraint:constraint-layout:1.0.2'    testCompile 'junit:junit:4.12'    compile project(':richdatacommon')}

打包命令的使用,打开Terminal进行一下命令
gradle build或者直接运行期release版本 gradle assembleRelease既可以。

工程框架

工程采用MVC或者MVP模式。这里对MVC模式忽略不讲。对于MVP模式的简要结构如下:

Created with Raphaël 2.1.0ViewViewPresenterPresenterModelModelView持有PresenterPresenter持有ModelPresenter将信息发给View绘制Model只能通过Presenter进行View的交互View只通过Presenter进行Model的交互进行事务流程,保存,刷新等View暴露所有的绘制接口给Presenter进行依赖

在MVP模式中,Presenter和Model是可以拖离SDK的,这样更加的方便单元测试。View层的测试可以通过SDK进行测试(纯UI测试)。

网络接口设计

Response基本格式

对于http的请求的返回格式采用这个基本格式,default_json

//重要数据在result里{    "isError":false,   "errorType":0,   "errorMessage":"",   "result":{         "cinemaId":1,         "cinemaName":"小明"   }}//异常的类型{    "isError":true,   "errorType":1,   "errorMessage":"网络异常",   "result":""}

isError是调用MobileAPI成功与否,errorType是错误类型(如果成功为0),errorMessage是错误消息(如果成功则为空),result是请求返回的数据结果(如果失败则为空)。这样的统一方便我们队请求数据的进行统一处理。

虚拟远程服务

对于Application的开发来说。一般都是要应用后台的接口工作,如果有完善的接口文档的话,在文档提供详细的回调格式,并且后台写一些假的数据给我前端开发,这样我们的Application还是可以前行无阻的,但是会陷入一个怪圈,Application的人在等接口,或相符沟通接口的变化,之后,还要等后台人员修改锁定的假数据。这里我参考了以往的经历和网上的资源采用了一个MockService来解决这个问题,只需要Application这端进行模拟数据。要实现的这个设计的前提是:

  • 提供良好接口文档,包括反回数据(json结构);
  • 数据返回的结构符合BaseResponse的结构;

之后在代码实现MockService既可。例子如下

//在res/xml/url.xml里添加接口//其中MockClass为虚拟的请求数据返回模型<?xml version="1.0" encoding="utf-8"?><url>    <Node        Key="getWeatherInfo"        Expires="300"        NetType="get"        MockClass="com.youngheart.mockdata.MockWeatherInfo"        Url="http://www.weather.com.cn/data/sk/101010100.html" />    <Node        Key="login"        Expires="0"        NetType="post"        MockClass="com.youngheart.mockdata.MockLoginSuccessInfo"        Url="http://www.weather.com.cn/data/sk/101010100.html" /></url>//虚拟数据public class MockWeatherInfo extends MockService {      @Override    public String getJsonData() {        WeatherInfo weather = new WeatherInfo();        weather.setCity("Shenghai");        weather.setCityid("10203");        Response response = getSuccessResponse();               response.setResult(JSON.toJSONString(weather));        return JSON.toJSONString(response);    }}//进行请求RemoteService.getInstance().invoke("getMusic", targetContext, "getMusic2", params, null, requestCallback);

主要是在MockClass进行管理需要模拟的数据,如果MockClass为空即走真实的请求。

代码规范与规定

代码规范的原则是简单易懂,不罗嗦,也可以参考google的java编程规范风格。

JAVA基本命名规约

  • 1.代码中的命均不能以下划线或者美元符号开始,也不能以下划线和美元号结束。
    反例: _name / __name / \$Object / name_ / name$

  • 2.类名使用UpperCamelCase风格,必须遵从驼峰形式
    正例: UserDO / XmlService / LoginActivity / TcpUdpDeal

  • 3.方法名、参数名、成员变量、局部变量都统一使用lowerCameCase风格,必须遵从驼峰形式。
    正例: localValue / getHttpMessage / inputUserId

  • 4.常量名全部大写,单纯间使用下划线隔开,力求语义表达清楚,不要嫌名字长。
    正例:MAX_STOCK_COUNT
    反例:MAX_COUNT

  • 5.包名统一小写,点分隔符直径仅有一个自然语义的英文单词。包名统一使用单数形式,但是类名如果有复数含义,可以使用复数形式,而且报名一般是和公司网址为开头的格式为:com.company_name.project_name。
    正例: com.richdataco.iot.util 类名为MessageUtils

  • 6.m前缀的成员变量具有广泛性,如果实现了一个类它没有涉及事务,即可用m作为前缀。
    正例:com.richdataco.view.MyView里的成员变量mPaint,mHeight,mFlag

Android内的规约

  • 1.四大组件Activity,Service,Content Provider,Broadcast Receiver的实现必须带对应的后缀。

  • 2.控件ID命名规范,控件的Id必须按照以下规则命名: 模块+类型+功能
    正例:login_btn_enter / user_space_iv_photo
    反例:btn_login / iv_user_photo(因为用户头像在很多地方都有,而且AndroidStudio的提示时可以进行快速定位,你需要的控件是在user_space下的类型为ImageView(iv)功能为photo的图片)

  • 3.控件自定义属性,除了layout相关的可以使用下划线隔开,其他的都是采用lowerCameCase风格,不用下划线。正例如下:

    <com.companyname.view.DivView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_margin="10dp"        android:layout_weight="0"        android:clickable="true"        android:enabled="true"        android:onClick="intentToMain"        android:text="crop image"        android:textAllCaps="false"        android:textColor="@color/colorAccent"/>
  • 4.layout下布局命名必须采用小写加下划线的方式,而且对于Activity和Fragment使用的需要加activity_fragment_作为前缀;ListView的item使用要带item_;
    正例:activity_main fragment_home fragment_profile item_my_favorites_food

  • 5.values下面的colors,dimens,strings都是采用全部小写加下划线的命名方式,但是对于styles的命名需要采用UpperCamelCase风格,也可以这样认为,对于Style是一个类,Style的属性是方法。正列如下:

    //---------------颜色的-------------------    <color name="mid_night">#22313f</color>    <color name="bon_jour">#E4E2E4</color>    <color name="charade">#3C3F41</color>    <color name="gallery">#EFEFEF</color>    <color name="cornell_red">#BB0F23</color>    <color name="cornell_red2">#bb0f45</color>    <color name="jaguar">#2B2B2B</color>    //---------------单位的-----------------------    <dimen name="text_size_button">14sp</dimen>    <dimen name="text_size_menu">14sp</dimen>    <dimen name="text_size_iv_tell">12sp</dimen>    <dimen name="text_size_body_1">14sp</dimen>    <dimen name="text_size_body_2">16sp</dimen>    <dimen name="text_size_sub_head">16sp</dimen>    <dimen name="text_size_title">20sp</dimen>    <dimen name="text_size_head_line">24sp</dimen>    <dimen name="text_size_display_1">34sp</dimen>    <dimen name="text_size_display_2">45sp</dimen>    <dimen name="text_size_display_3">56sp</dimen>    <dimen name="text_size_display_4">112sp</dimen>    //--------------------styles------------------    <style name="SplashStyle" parent="AppTheme">        <item name="colorPrimary">@color/athens_gray</item>        <item name="colorPrimaryDark">@color/athens_gray</item>        <item name="android:background">@color/athens_gray</item>        <item name="android:windowBackground">@null</item>    </style>

工具类

AndroidLog

是app调试log的工具,可以通过gradle进行配置log的开关。默认release版本是关闭,debug版本为打开,不用在代码中写BuildConfig,因为编译器已经默认添加了一个BuildConfig。

DensityUtils

给类是实现android的各种屏幕适配的单位转化。

BindViewTools.jar
在之前说过了android控件命名的规范后,下面简单介绍一下公共类中写的一个BindView工具的使用,使用例子如下

//默认是Activity下的findViewByIdjava -jar BindViewTool.jar -p $layout_file_path//Fragment下的java -jar BindViewTool.jar -f true -p $layout_file_path//添加忽略标识命令,对于m开头的进行忽略java -jar BindViewTool.jar -f true -i m -p $layout_file_path//返回结果示例private LinearLayout testBindLyContainer;private TextView testBindTvInfo;private Button testBindBtnLogin;private Button testBindBtnUser;private ListView testBindLvNews;public void bindViews(){        testBindLyContainer = (LinearLayout)getView().findViewById(R.id.test_bind_ly_container);        testBindTvInfo = (TextView)getView().findViewById(R.id.test_bind_tv_info);        testBindBtnLogin = (Button)getView().findViewById(R.id.test_bind_btn_login);        testBindBtnUser = (Button)getView().findViewById(R.id.test_bind_btn_user);        testBindLvNews = (ListView)getView().findViewById(R.id.test_bind_lv_news);}

其他的工具类

都可以通过java的名字推测得知。

其他

2 0