Android 开发最佳实践

原文地址:https://github.com/futurice/android-best-practices/blob/master/translations/Chinese/README.cn.md

Futurice公司Android开发人员中学到的经验。 遵循下面准则,避免反复发明轮子。

若您对开发iOS或Windows Phone 有兴趣, 请看iOS Good Practices 和 Windows client Good Practices 这两篇文章。

摘要

  • 使用 Gradle 和它推荐的project结构
  • 把password和敏感数据放在gradle.properties
  • 不要自己写 HTTP client,使用Volley或OkHttp库
  • 使用Jackson库解析JSON数据
  • 避免使用Guava同一时候使用一些类库来避免65k method limit(一个Android程序中最多能运行65536个方法)
  • 使用 Fragments来呈现UI视图
  • 使用 Activities 仅仅是为了管理 Fragments
  • Layout 布局是 XMLs代码,组织好它们
  • 在layoutout XMLs布局时。使用styles文件来避免使用反复的属性
  • 使用多个style文件来避免单一的一个大style文件
  • 保持你的colors.xml 简短DRY(不要反复自己),仅仅是定义调色板
  • 总是使用dimens.xml DRY(不要反复自己),定义通用常数
  • 不要做一个深层次的ViewGroup
  • 在使用WebViews时避免在client做处理。当心内存泄露
  • 使用Robolectric单元測试,Robotium 做UI測试
  • 使用Genymotion 作为你的模拟器
  • 总是使用ProGuard 和 DexGuard混淆来项目

Android SDK

将你的Android SDK放在你的home文件夹或其它应用程序无关的位置。 当安装有些包括SDK的IDE的时候,可能会将SDK放在IDE同一文件夹下,当你须要升级(或又一次安装)IDE或更换的IDE时。会很麻烦。 此外,若果你的IDE是在普通用户。不是在root下执行。还要避免吧SDK放到一下须要sudo权限的系统级别文件夹下。

构建系统

你的默认编译环境应该是Gradle. Ant 有非常多限制,也非常冗余。使用Gradle。完毕下面工作非常方便:

  • 构建APP不同版本号的变种
  • 制作简单类似脚本的任务
  • 管理和下载依赖
  • 自己定义秘钥
  • 很多其它

同一时候,Android Gradle插件作为新标准的构建系统正在被Google积极的开发。

project结构

有两种流行的结构:老的Ant & Eclipse ADT project结构,和新的Gradle & Android Studio project结构, 你应该选择新的project结构,假设你的project还在使用老的结构。考虑放弃吧,将project移植到新的结构。

老的结构:

old-structure
├─ assets
├─ libs
├─ res
├─ src
│  └─ com/futurice/project
├─ AndroidManifest.xml
├─ build.gradle
├─ project.properties
└─ proguard-rules.pro

新的结构

new-structure
├─ library-foobar
├─ app
│  ├─ libs
│  ├─ src
│  │  ├─ androidTest
│  │  │  └─ java
│  │  │     └─ com/futurice/project
│  │  └─ main
│  │     ├─ java
│  │     │  └─ com/futurice/project
│  │     ├─ res
│  │     └─ AndroidManifest.xml
│  ├─ build.gradle
│  └─ proguard-rules.pro
├─ build.gradle
└─ settings.gradle

基本的差别在于,新的结构明白的分开了'source sets' (main,androidTest)。Gradle的一个理念。

你能够做到。比如。加入源组‘paid’和‘free’在src中,这将成为您的应用程序的付费和免费的两种模式的源码。

你的项目引用第三方项目库时(比如,library-foobar)。拥有一个顶级包名app从第三方库项目区分你的应用程序是很实用的。

然后settings.gradle不断引用这些库项目,当中app/build.gradle能够引用。

Gradle 配置

经常使用结构 參考Google's guide on Gradle for Android

小任务 除了(shell, Python, Perl, etc)这些脚本语言,你也能够使用Gradle 制作任务。

很多其它信息请參考Gradle's documentation

password 在做版本号release时你app的 build.gradle你须要定义 signingConfigs.此时你应该避免下面内容:

不要做这个 . 这会出如今版本号控制中。

signingConfigs {
    release {
        storeFile file("myapp.keystore")
        storePassword "password123"
        keyAlias "thekey"
        keyPassword "password789"
    }
}

而是,建立一个不增加版本号控制系统的gradle.properties文件。

KEYSTORE_PASSWORD=password123
KEY_PASSWORD=password789

那个文件是gradle自己主动引入的,你能够在buld.gradle文件里使用,比如:

signingConfigs {
    release {
        try {
            storeFile file("myapp.keystore")
            storePassword KEYSTORE_PASSWORD
            keyAlias "thekey"
            keyPassword KEY_PASSWORD
        }
        catch (ex) {
            throw new InvalidUserDataException("You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.")
        }
    }
}

使用 Maven 依赖方案取代使用导入jar包方案 假设在你的项目中你明白使用率 jar文件,那么它们可能成为永久的版本号,如2.1.1.下载jar包更新他们是非常繁琐的, 这个问题Maven非常好的攻克了,这在Android Gradle构建中也是推荐的方法。

你可 以指定版本号的一个范围,如2.1.+,然后Maven会自己主动升级到制定的最新版本号,比如:

dependencies {
    compile 'com.netflix.rxjava:rxjava-core:0.19.+'
    compile 'com.netflix.rxjava:rxjava-android:0.19.+'
    compile 'com.fasterxml.jackson.core:jackson-databind:2.4.+'
    compile 'com.fasterxml.jackson.core:jackson-core:2.4.+'
    compile 'com.fasterxml.jackson.core:jackson-annotations:2.4.+'
    compile 'com.squareup.okhttp:okhttp:2.0.+'
    compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.+'
}

IDEs and text editors

IDE集成开发环境和文本编辑器

不管使用什么编辑器,一定要构建一个良好的project结构 编辑器每一个人都有自己的 选择,让你的编辑器依据project结构和构建系统运作。那是你自己的责任。

当下首推Android Studio,由于他是由谷歌开发,最接近Gradle,默认使用最新的project结构,已经到beta阶段 (眼下已经有release 1.0了),它就是为Android开发定制的。

你也能够使用Eclipse ADT ,可是你须要对它进行配置,由于它使用了旧的project结构 和Ant作为构建系统。你甚至能够使用纯文版编辑器如Vim,Sublime Text,或者Emacs。假设那样的话。你须要使用Gardle和adb命令行。假设使用Eclipse集成Gradle 不适合你,你仅仅是使用命令行构建project。或迁移到Android Studio中来吧。

不管你使用何种开发工具。仅仅要确保Gradle和新的项目结构保持官方的方式构建应用程序,避免你的编辑器配置文件增加到版本号控制。比如,避免增加Ant build.xml文件。 特别假设你改变Ant的配置,不要忘记保持build.gradle是最新和起作用的。同一时候,善待其它开发人员,不要强制改变他们的开发工具和偏好。

类库

Jackson 是一个将java对象转换成JSON与JSON转化java类的类库。

Gson 是解决问题的流行方案,然而我们发现Jackson更高效,由于它支持替代的方法处理JSON:流、内存树模型,和传统JSON-POJO数据绑定。只是,请记住, Jsonkson库比起GSON更大,所以依据你的情况选择,你可能选择GSON来避免APP 65k个方法限制。其他选择: Json-smart and Boon JSON

网络请求。缓存,图片 运行请求后端server,有几种交互的解决方式,你应该考虑实现你自己的网络client。

使用 VolleyRetrofit

Volley 同一时候提供图片缓存类。

若果你选择使用Retrofit,那么考虑使用Picasso 来载入图片和缓存,同一时候使用OkHttp作为高效的网络请求。Retrofit,Picasso和OkHttp都是有同一家公司开发(注: 是由Square 公司开发),所以它们能非常好的在一起执行。OkHttp 相同能够和Volley在一起使用 Volley.

RxJava 是函数式反应性的一个类库。换句话说。能处理异步的事件。

这是一个强大的和有前途的模式,同一时候也可能会造成混淆,由于它是如此的不同。 我们建议在使用这个库架构整个应用程序之前要慎重考虑。

有一些项目是使用RxJava完毕的,假设你须要帮助能够跟这些人取得联系: Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen. 我们也写了一些博客: [1][2][3][4].

如若你之前有使用过Rx的经历,開始从API响应应用它。 另外,从简单的UI事件处理開始运用,如单击事件或在搜索栏输入事件。

若对你的Rx技术有信心,同一时候想要将它应用到你的总体架构中,那么请在复杂的部分写好Javadocs文档。

请记住其它不熟悉RxJava的开发者。可能会很难理解整个项目。

尽你的的全力帮助他们理解你的代码和Rx。

Retrolambda 是一个在Android和预JDK8平台上的使用Lambda表达式语法的Java类库。

它有助于保持你代码的紧凑性和可读性,特别当你使用如RxJava函数风格编程时。

使用它时先安装JDK8,在Android Studioproject结构对话框中把它设置成为SDK路径,同一时候设置JAVA8_HOMEJAVA7_HOME环境变量, 然后在project根文件夹下配置 build.gradle:

dependencies {
    classpath 'me.tatarka:gradle-retrolambda:2.4.+'
}

同一时候在每一个module 的build.gradle中加入

apply plugin: 'retrolambda'

android {
    compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}

retrolambda {
    jdk System.getenv("JAVA8_HOME")
    oldJdk System.getenv("JAVA7_HOME")
    javaVersion JavaVersion.VERSION_1_7
}

Android Studio 提供Java8 lambdas表带是代码提示支持。假设你对lambdas不熟悉,仅仅需參照下面開始学习吧:

  • 不论什么仅仅包括一个接口的方法都是"lambda friendly"同一时候代码能够被折叠成更紧凑的语法
  • 假设对參数或类似有疑问,就写一个普通的匿名内部类,然后让Android Status为你生成一个lambda。

当心dex方法数限制,同一时候避免使用过多的类库 Android apps,当打包成一个dex文件时,有一个65535个应用方法强硬限制[1] [2] [3]

当你突破65k限制之后你会看到一个致命错误。因此,使用一个正常范围的类库文件。同一时候使用dex-method-counts 工具来决定哪些类库能够再65k限制之下使用。特别的避免使用Guava类库。由于它包括超过13k个方法。

Activities and Fragments

Fragments应该作为你实现UI界面默认选择。你能够反复使用Fragments用户接口来 组合成你的应用。我们强烈推荐使用Fragments而不是activity来呈现UI界面,理由例如以下:

  • 提供多窗格布局解决方式 Fragments 的引入主要将手机应用延伸到平板电脑。所以在平板电脑上你可能有A、B两个窗格,可是在手机应用上A、B可能分别充满 整个屏幕。

    假设你的应用在最初就使用了fragments。那么以后将你的应用适配到其它不同尺寸屏幕就会很easy。

  • 屏幕间数据通信 从一个Activity发送复杂数据(比如Java对象)到另外一个Activity,Android的API并没有提供合适的方法。只是使用Fragment,你能够使用 一个activity实例作为这个activity子fragments的通信通道。即使这样比Activity与Activity间的通信好。你也想考虑使用Event Bus架构,使用如 Otto 或者 greenrobot EventBus作为更简洁的实现。 假设你希望避免加入另外一个类库。RxJava相同能够实现一个Event Bus。

  • Fragments 一般通用的不仅仅有UI 你能够有一个没有界面的fragment作为Activity提供后台工作。

    进一步你能够使用这个特性来创建一个fragment 包括改变其他fragment的逻辑 而不是把这个逻辑放在activity中。

  • 甚至ActionBar 都能够使用内部fragment来管理 你能够选择使用一个没有UI界面的fragment来专门管理ActionBar,或者你能够选择使用在每一个Fragment中 加入它自己的action 来作为父Activity的ActionBar.參考.

非常不幸,我们不建议广泛的使用嵌套的fragments,由于 有时会引起matryoshka bugs

我们仅仅有当它有意义(比如,在水平滑动的ViewPager在 像屏幕一样fragment中)或者他的确是一个明智的选择的时候才广泛的使用fragment。

在一个架构级别。你的APP应该有一个顶级的activity来包括绝大部分业务相关的fragment。你也可能另一些辅助的activity ,这些辅助的activity与主activity 通信非常easy限制在这两种方法 Intent.setData() 或 Intent.setAction()或类似的方法。

Java 包结构

Android 应用程序在架构上大致是Java中的Model-View-Controller结构。

在Android 中 Fragment和Activity通常上是控制器类(http://www.informit.com/articles/article.aspx?p=2126865). 换句话说,他们是用户接口的部分,相同也是Views视图的部分。

正是由于如此,才非常难严格的将fragments (或者 activities) 严格的划分成 控制器controlloers还是视图 views。

最还是将它们放在自己单独的 fragments 包中。仅仅要你遵循之前提到的建议,Activities 则能够放在顶级文件夹下。 若果你规划有2到3个以上的activity,那么还是相同新建一个activities包吧。

然而,这样的架构能够看做是还有一种形式的MVC。 包括要被解析API响应的JSON数据,来填充的POJO的models包中。

和一个views包来包括你的自己定义视图、通知、导航视图,widgets等等。 适配器Adapter是在数据和视图之间。然而他们通常须要通过getView()方法来导出一些视图。 所以你能够将adapters包放在views包里面。

一些控制器角色的类是应用程序级别的,同一时候是接近系统的。 这些类放在managers包以下。

一些繁杂的数据处理类,比方说"DateUtils",放在utils包以下。 与后端交互负责网络处理类。放在network包以下。

总而言之,以最接近用户而不是最接近后端去安排他们。

com.futurice.project
├─ network
├─ models
├─ managers
├─ utils
├─ fragments
└─ views
   ├─ adapters
   ├─ actionbar
   ├─ widgets
   └─ notifications

资源文件 Resources

  • 命名 遵循前缀表明类型的习惯,形如type_foo_bar.xml

    比如:fragment_contact_details.xml,view_primary_button.xml,activity_main.xml.

组织布局文件 若果你不确定怎样排版一个布局文件。遵循一下规则可能会有帮助。

  • 每个属性一行。缩进4个空格
  • android:id 总是作为第一个属性
  • android:layout_**** 属性在上边
  • style 属性在底部
  • 关闭标签/>单独起一行。有助于调整和加入新的属性
  • 考虑使用Designtime attributes 设计时布局属性,Android Studio已经提供支持,而不是硬编码android:text (译者注:墙内也能够參考stormzhang的这篇博客链接)。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <TextView
        android:id="@+id/name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:text="@string/name"
        style="@style/FancyText"
        />

    <include layout="@layout/reusable_part" />

</LinearLayout>

作为一个经验法则,android:layout_****属性应该在 layout XML 中定义,同一时候其他属性android:**** 应放在 styler XML中。此规则也有例外,只是大体工作 的非常好。

这个思想总体是保持layout属性(positioning, margin, sizing) 和content属性在布局文件里,同一时候将全部的外观细节属性(colors, padding, font)放 在style文件里。

例外有下面这些:

  • android:id 明显应该在layout文件里
  • layout文件里android:orientation对于一个LinearLayout布局通常更有意义
  • android:text 因为是定义内容,应该放在layout文件里
  • 有时候将android:layout_width 和 android:layout_height属性放到一个style中作为一个通用的风格中更有意义,可是默认情况下这些应该放到layout文件里。

使用styles 差点儿每一个项目都须要适当的使用style文件,由于对于一个视图来说有一个反复的外观是非经常见的。 在应用中对于大多数文本内容。最起码你应该有一个通用的style文件,比如:

<style name="ContentText">
    <item name="android:textSize">@dimen/font_normal</item>
    <item name="android:textColor">@color/basic_black</item>
</style>

应用到TextView 中:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/price"
    style="@style/ContentText"
    />

你也许须要为button控件做相同的事情,不要停止在那里。将一组相关的和反复android:****的属性放到一个通用的style中。

将一个大的style文件切割成多个文件 你能够有多个styles.xml 文件。Android SDK支持其他文件,styles这个文件名并没有作用,起作用的是在文件 里xml的<style>标签。

因此你能够有多个style文件styles.xml,style_home.xml,style_item_details.xml,styles_forms.xml。 不用于资源文件路径须要为系统构建起的有意义,在res/values文件夹下的文件能够随意命名。

colors.xml是一个调色板 在你的colors.xml文件里应该仅仅是映射颜色的名称一个RGBA值。而没有其他的。

不要使用它为不同的button来定义RGBA值。

不要这样做

<resources>
    <color name="button_foreground">#FFFFFF</color>
    <color name="button_background">#2A91BD</color>
    <color name="comment_background_inactive">#5F5F5F</color>
    <color name="comment_background_active">#939393</color>
    <color name="comment_foreground">#FFFFFF</color>
    <color name="comment_foreground_important">#FF9D2F</color>
    ...
    <color name="comment_shadow">#323232</color>

使用这样的格式,你会非常easy的開始反复定义RGBA值,这使假设须要改变基本色变的非常复杂。同一时候。这些定义是跟一些环境关联起来的。如button或者comment, 应该放到一个button风格中,而不是在color.xml文件里。

相反,这样做:

<resources>

    <!-- grayscale -->
    <color name="white"     >#FFFFFF</color>
    <color name="gray_light">#DBDBDB</color>
    <color name="gray"      >#939393</color>
    <color name="gray_dark" >#5F5F5F</color>
    <color name="black"     >#323232</color>

    <!-- basic colors -->
    <color name="green">#27D34D</color>
    <color name="blue">#2A91BD</color>
    <color name="orange">#FF9D2F</color>
    <color name="red">#FF432F</color>

</resources>

向应用设计者那里要这个调色板,名称不须要跟"green", "blue", 等等同样。

"brand_primary", "brand_secondary", "brand_negative" 这种名字也是全然能够接受的。 像这样规范的颜色很easy改动或重构,会使应用一共使用了多少种不同的颜色变得很清晰。 通常一个具有审美价值的UI来说。降低使用颜色的种类是很重要的。

像对待colors.xml一样对待dimens.xml文件 与定义颜色调色板一样,你同一时候也应该定义一个空隙间隔和字体大小的“调色板”。 一个好的样例,例如以下所看到的:

<resources>

    <!-- font sizes -->
    <dimen name="font_larger">22sp</dimen>
    <dimen name="font_large">18sp</dimen>
    <dimen name="font_normal">15sp</dimen>
    <dimen name="font_small">12sp</dimen>

    <!-- typical spacing between two views -->
    <dimen name="spacing_huge">40dp</dimen>
    <dimen name="spacing_large">24dp</dimen>
    <dimen name="spacing_normal">14dp</dimen>
    <dimen name="spacing_small">10dp</dimen>
    <dimen name="spacing_tiny">4dp</dimen>

    <!-- typical sizes of views -->
    <dimen name="button_height_tall">60dp</dimen>
    <dimen name="button_height_normal">40dp</dimen>
    <dimen name="button_height_short">32dp</dimen>

</resources>

布局时在写 margins 和 paddings 时,你应该使用spacing_****尺寸格式来布局。而不是像对待String字符串一样直接写值。 这样写会很有感觉,会使组织和改变风格或布局是很easy。

避免深层次的视图结构 有时候为了摆放一个视图,你可能尝试加入还有一个LinearLayout。

你可能使用这样的方法解决:

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <RelativeLayout
        ...
        >

        <LinearLayout
            ...
            >

            <LinearLayout
                ...
                >

                <LinearLayout
                    ...
                    >
                </LinearLayout>

            </LinearLayout>

        </LinearLayout>

    </RelativeLayout>

</LinearLayout>

即使你没有很明白的在一个layout布局文件里这样使用。假设你在Java文件里从一个view inflate(这个inflate翻译只是去,大家理解即可) 到其它views其中。也是可能会发生的。

可能会导致一系列的问题。你可能会遇到性能问题,由于处理起须要处理一个复杂的UI树结构。 还可能会导致下面更严重的问题StackOverflowError.

因此尽量保持你的视图tree:学习怎样使用RelativeLayout, 怎样 optimize 你的布局 和怎样使用 <merge> 标签.

小心关于WebViews的问题. 假设你必须显示一个web视图。 比方说对于一个新闻文章。避免做client处理HTML的工作, 最好让后端project师协助,让他返回一个 "" HTML。 WebViews 也能导致内存泄露 当保持引他们的Activity,而不是被绑定到ApplicationContext中的时候。 当使用简单的文字或button时,避免使用WebView,这时使用TextView或Buttons更好。

測试框架

Android SDK的測试框架还处于0基础阶段,特别是关于UI測试方面。Android Gradle 眼下实现了一个叫connectedAndroidTest的測试, 它使用一个JUnit 为Android提供的扩展插件 extension of JUnit with helpers for Android.能够跑你生成的JUnit測试,

仅仅当做单元測试时使用 Robolectric ,views 不用 它是一个最求提供"不连接设备的"为了加速开发的測试, 很时候做 models 和 view models 的单元測试。 然而,使用Robolectric測试时不精确的,也不全然对UI測试。

当你对有关动画的UI元素、对话框等,測试时会有问题, 这主要是由于你是在 “在黑暗中工作”(在没有可控的界面情况下測试)

*Robotium 使写UI測试很easy。 * 对于UI測试你不需 Robotium 跑与设备连接的測试。

但它可能会对你故意。是由于它有很多来帮助类的获得和分析视图。控制屏幕。

測试用例看起来像这样简单:

solo.sendKey(Solo.MENU);
solo.clickOnText("More"); // searches for the first occurence of "More" and clicks on it
solo.clickOnText("Preferences");
solo.clickOnText("Edit File Extensions");
Assert.assertTrue(solo.searchText("rtf"));

模拟器

假设你全职开发Android App,那么买一个Genymotion emulatorlicense吧。

Genymotion 模拟器执行更快的秒帧的速度,比起典型的AVD模拟器。他有演示你APP的工具,高质量的模拟网络连接。GPS位置。等等。

它同一时候还有理想的连接測试。

你若涉及适配使用非常多不同的设备。买一个Genymotion 版权是比你买非常多真设备廉价多的。

注意:Genymotion模拟器没有装载全部的Google服务,如Google Play Store和Maps。你也可能需 要測试Samsung指定的API,若这种话你还是须要购买一个真实的Samsung设备。

混淆配置

ProGuard 是一个在Android项目中广泛使用的压缩和混淆打包的源代码的工具。

你是否使用ProGuard取决你项目的配置。当你构建一个release版本号的apk时,通常你应该配置gradle文件。

buildTypes {
    debug {
        minifyEnabled false
    }
    release {
        signingConfig signingConfigs.release
        minifyEnabled true
        proguardFiles 'proguard-rules.pro'
    }
}

为了决定哪些代码应该被保留。哪些代码应该被混淆。你不得不指定一个或多个实体类在你的代码中。 这些实体应该是指定的类包括main方法,applets,midlets,activities,等等。

Android framework 使用一个默认的配置文件,能够在SDK_HOME/tools/proguard/proguard-android.txt 文件夹下找到。自己定义的project指定的 project-specific 混淆规则,如在my-project/app/proguard-rules.pro中定义, 会被加入到默认的配置中。

关于 ProGuard 一个普遍的问题,是看应用程序是否崩溃并报ClassNotFoundException 或者 NoSuchFieldException 或类似的异常, 即使编译是没有警告并执行成功。 这意味着下面两种可能:

  1. ProGuard 已经移除了类,枚举。方法,成员变量或注解,考虑是否是必要的。
  2. ProGuard 混淆了类,枚举。成员变量的名称,可是这些名字又被拿原始名称使用了,比方通过Java的反射。

检查app/build/outputs/proguard/release/usage.txt文件看有问题的对象是否被移除了。 检查app/build/outputs/proguard/release/mapping.txt 文件看有问题的对象是否被混淆了。

In order to prevent ProGuard from stripping away needed classes or class members, add a keep options to your proguard config: 以防 ProGuard 剥离 须要的类和类成员,加入一个 keep选项在你的 proguard 配置文件里:

-keep class com.futurice.project.MyClass { *; }

防止 ProGuard 混淆 一些类和成员,加入 keepnames:

-keepnames class com.futurice.project.MyClass { *; }

查看this template's ProGuard config 中的一些样例。 很多其它样例请參考Proguard

在构建项目之初,公布一个版本号 来检查ProGuard规则是否正确的保持了重要的部分。 同一时候不管何时你加入了新的类库。做一个公布版本号,同一时候apk在设备上跑起来測试一下。

不要等到你的app要公布 "1.0"版本号了才做版本号公布,那时候你可能会碰到好多意想不到的异常,须要一些时间去修复他们。

Tips每次公布新版本号都要写 mapping.txt。每公布一个版本号,假设用户遇到一个bug。同一时候提交了一个混淆过的堆栈跟踪。

通过保留mapping.txt文件,来确定你能够调试的问题。

DexGuard 若果你须要核心工具来优化。和专门混淆的公布代码,考虑使用DexGuard, 一个商业软件,ProGuard 也是有他们团队开发的。 它会非常easy将Dex文件切割,来解决65K个方法限制问题。

致谢

感谢Antti Lammi, Joni Karppinen, Peter Tackage, Timo Tuominen, Vera Izrailit, Vihtori Mäntylä, Mark Voit, Andre Medeiros, Paul Houghton 这些人和Futurice 开发人员分享他们的Android开发经验。

License

Futurice Oy Creative Commons Attribution 4.0 International (CC BY 4.0)

Translation

Translated to Chinese by andyiac

原文地址:https://www.cnblogs.com/yjbjingcha/p/7236080.html