看我開(kāi)發(fā)干貨集中營(yíng)App(二)~ APP初始化

個(gè)人原因,此系列更新已停止,抱歉。

接著上一篇《看我開(kāi)發(fā)干貨集中營(yíng)App(一)~ 開(kāi)篇》,本篇將開(kāi)始我們【干貨精選】的編碼之旅,分為4部分內(nèi)容: 新建App,簽名配置,混淆代碼以及依賴開(kāi)源庫(kù)。

新建APP

使用Android Studio 2.2 Rc版本新建名為GankEssence項(xiàng)目,建立過(guò)程按需填寫(xiě)相關(guān)包名即可。

新建成功后修改我們之前的已經(jīng)設(shè)定好的顏色配置并更改APP中文名, 那么相關(guān)配置暫時(shí)如下:

color.xml

<resources>
<color name="colorPrimary">#009688</color>
<color name="colorPrimaryDark">#00796B</color>
<color name="colorAccent">#8BC34A</color>
</resources>

strings.xml

<resources>
    <string name="app_name">干貨精選</string>
    <string name="app_name_en">GankEssence</string>
</resources>

sdk相關(guān)

compileSdkVersion 24
buildToolsVersion "24.0.2"
defaultConfig {
    applicationId "com.huchiwei.gankessence"
    minSdkVersion 15
    targetSdkVersion 24
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}

其它暫時(shí)保持不變。模擬器運(yùn)行即可看見(jiàn)Hello World,顏色也跟設(shè)定一樣。

簽名配置

雖然APP離真正發(fā)布還很遠(yuǎn),按我個(gè)人習(xí)慣還是把APP必須的東西但基本不會(huì)怎么變動(dòng)的先配置了。

AS上建立簽名文件太Easy: 工具欄Build > Generate Sign Apk > create new,然后填寫(xiě)簽名相關(guān)信息即可。具體也可參考官網(wǎng)說(shuō)明

創(chuàng)建完后打開(kāi)Project Structure(windows快捷鍵ctrl+alt+shift+s),切換到app并填寫(xiě)填寫(xiě)簽名信息如下圖,, 填寫(xiě)完確定將簽名信息寫(xiě)入到app/build.grade中:

簽名配置

配置簽名后再看看我們的app/build.grade會(huì)發(fā)現(xiàn)多簽名信息:

signingConfigs {
    release {
        keyAlias 'huchiwei'
        keyPassword 'password123'
        storeFile file('E:/我的堅(jiān)果云/Android開(kāi)發(fā)/簽名文件/android.hucw.signkey.jks')
        storePassword 'password123'
    }
}
...
release {
    signingConfig signingConfigs.release
}

此時(shí)打開(kāi)AS右側(cè)Gradle面板執(zhí)行下assembleRelease任務(wù),如果正常的話,在app的build/outputs/apk能夠見(jiàn)到已經(jīng)簽名的app-release.apk。

開(kāi)啟混淆\壓縮

app/build.gradle配置如下:

release {
    minifyEnabled true          // 開(kāi)啟混淆
    shrinkResources true        // 移除無(wú)用資源
    zipAlignEnabled true        // 開(kāi)啟壓縮
    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}

proguard-android.txt android默認(rèn)混淆配置,以包含基本的混淆配置(不明白網(wǎng)上很多配置為什么要在proguard-rules.pro里面覆寫(xiě)其內(nèi)容),proguard-rules.proapp自定義混淆配置。

proguard-rules.pro配置如下:

-optimizationpasses 5                                                           # 指定代碼的壓縮級(jí)別
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*        # 混淆時(shí)所采用的算法

# 保持內(nèi)部類
-keepattributes InnerClasses,EnclosingMethod
-dontoptimize
-optimizations optimization_filter

#如果有引用v4包可以添加下面這行
-keep class android.support.v4.** { *; }
-keep public class * extends android.support.v4.**
-keep public class * extends android.app.Fragment

#如果引用了v4或者v7包,可以忽略警告
-dontwarn android.support.**

# 保持哪些類不被混淆
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService

#保持自定義組件不被混淆
-keep public class * extends android.view.View {
    public <init>(android.content.Context);
    public <init>(android.content.Context, android.util.AttributeSet);
    public <init>(android.content.Context, android.util.AttributeSet, int);
    public void set*(...);
}

因?yàn)闀簳r(shí)未依賴第三方庫(kù),所以混淆配置比較少,這樣做有一個(gè)好處:越少依賴越早開(kāi)啟測(cè)試混淆,越不容易出現(xiàn)問(wèn)題。即使出現(xiàn)問(wèn)題也能很快定位問(wèn)題,否則依賴N多包到準(zhǔn)備發(fā)包時(shí)才開(kāi)啟混淆測(cè)試,那就有得哭了。而且盡管現(xiàn)在僅依賴了appcompat-v7的包,但發(fā)布打包測(cè)試依然一堆錯(cuò)誤警告,雖然沒(méi)有中斷打包,卻讓人很不爽,直到看到這里,還有這里加入以下代碼后才解決:

# 保持內(nèi)部類
-keepattributes InnerClasses,EnclosingMethod
-dontoptimize
-optimizations optimization_filter

ok,簽名、混淆配置搞定。

多渠道打包

其實(shí)在這個(gè)剛開(kāi)始階段就配置這個(gè)多渠道打包,實(shí)在有點(diǎn)早。不過(guò)因?yàn)檫@個(gè)東西其實(shí)也不太難,而且考慮到本系列文章是由淺到深,所以就干脆提前來(lái)講講好了。

多渠道打包百度隨便一搜,N多文章介紹,這里選幾篇有代表性,大家可以看看:

同樣地,我也到友盟申請(qǐng)個(gè)App統(tǒng)計(jì)應(yīng)用,按照SDK文檔配置下。

manifest.xml

<meta-data
    android:name="UMENG_CHANNEL"
    android:value="${UMENG_CHANNEL_VALUE}" />

在app的build.gradle設(shè)置produceFlavors

// 友盟多渠道打包
productFlavors {
    wandoujia {}
    _360 {}
    baidu {}
    xiaomi {}
    tencent {}
    taobao {}
}

productFlavors.all { flavor ->
    flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}

然后格式化名稱輸出apk

def releaseTime() {
    return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}

android {
    defaultConfig {
        // dex突破65535的限制
        multiDexEnabled true
        // 默認(rèn)是umeng的渠道
        manifestPlaceholders = [UMENG_CHANNEL_VALUE: "umeng"]
    }
    
    buildTypes {
        release {
            applicationVariants.all { variant ->
                variant.outputs.each { output ->
                    def outputFile = output.outputFile
                    if (outputFile != null && outputFile.name.endsWith('.apk')) {
                        // 輸出apk名稱為gankessence_v1.0_2015-01-15_wandoujia.apk
                        def fileName = "gankessence_v${defaultConfig.versionName}_${releaseTime()}_${variant.productFlavors[0].name}.apk"
                        output.outputFile = new File(outputFile.parent, fileName)
                    }
                }
            }
        }
    }
}

最后再一次執(zhí)行assembleRelease,如果正常的話應(yīng)該可以看到如下結(jié)果:

多渠道打包

支持庫(kù)、第三方庫(kù)依賴

關(guān)于官方支持庫(kù)的依賴版本,按照Google建議是使用最新版本,當(dāng)然這個(gè)大家按照自己需求即可。

根據(jù)干貨精選的原型設(shè)計(jì)圖,基本可以看出來(lái)需要使用那些支持庫(kù):

// Android Support Libraries
compile 'com.android.support:appcompat-v7:24.2.0'
compile 'com.android.support:cardview-v7:24.2.0'
compile 'com.android.support:design:24.2.0'
compile 'com.android.support:recyclerview-v7:24.2.0'
compile 'com.android.support:support-v4:24.2.0'

網(wǎng)絡(luò)請(qǐng)求:Retrofit2,不二之選。然后使用Gson作為轉(zhuǎn)換器,okhttp3作為網(wǎng)絡(luò)請(qǐng)求客戶端,再加上網(wǎng)絡(luò)日志攔截器,簡(jiǎn)直完美! 依賴包看下面:

// Retrofit && OKHttp && GSON
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
compile 'com.squareup.okhttp3:okhttp:3.4.1'
compile 'com.squareup.okhttp3:logging-interceptor:3.4.1'
compile 'org.immutables:gson:2.2.12'

異步操作:RxJava,簡(jiǎn)潔、鏈?zhǔn)秸{(diào)用,與Retrofit2無(wú)縫結(jié)合,然后自己再簡(jiǎn)單封裝一層,媽媽就再也不用擔(dān)心異步網(wǎng)絡(luò)請(qǐng)求響應(yīng)啦:

compile 'io.reactivex.rxjava2:rxjava:2.0.0-RC2'

圖片緩存框架:比較糾結(jié),原來(lái)是想使用Android-Universal-Image-Loader,但后來(lái)看到已經(jīng)停止維護(hù)了,所以沒(méi)用它,然后通過(guò)別人文章再三對(duì)比,還有這里后使用的是:[Glide](https://github.com/bumptech/glide),相關(guān)使用配置可以先看看官方wiki,當(dāng)然后面我也會(huì)介紹對(duì)它如何封裝使用的,依賴如下:

// 要依賴com.android.support:support-v4哦
compile 'com.github.bumptech.glide:glide:3.7.0'

數(shù)據(jù)綁定:Butterknife, 我想這個(gè)應(yīng)該沒(méi)有疑問(wèn), 依賴需要多配置,我直接拷貝官網(wǎng)說(shuō)明過(guò)來(lái):

//Configure your project-level build.gradle to include the 'android-apt' plugin:
buildscript {
  repositories {
    mavenCentral()
   }
  dependencies {
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
  }
}

//Then, apply the 'android-apt' plugin in your module-level build.gradle and add the Butter Knife dependencies:

apply plugin: 'android-apt'

android {
  ...
}

dependencies {
  compile 'com.jakewharton:butterknife:8.4.0'
  apt 'com.jakewharton:butterknife-compiler:8.4.0'
}

最后加上混淆配置:

# Glide框架混淆設(shè)置
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
  **[] $VALUES;
  public *;
}
#-keepresourcexmlelements manifest/application/meta-data@value=GlideModule

# Butter Knife 混淆
-keep public class * implements butterknife.Unbinder { public <init>(...); }
-keep class butterknife.*
-keepclasseswithmembernames class * { @butterknife.* <methods>; }
-keepclasseswithmembernames class * { @butterknife.* <fields>; }

# Retrofit2
-dontnote retrofit2.Platform
-dontnote retrofit2.Platform$IOS$MainThreadExecutor
-dontwarn retrofit2.Platform$Java8
-keepattributes Signature
-keepattributes Exceptions

# Gson
-keepattributes Signature
-keepattributes *Annotation*
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
-keep class com.google.gson.examples.android.model.** { *; }

-dontwarn org.immutables.gson.**
-keep class org.immutables.gson.** { *;}

# OkHttp
-keepattributes Signature
-keepattributes *Annotation*
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn okhttp3.**
-dontwarn okio.**

# RxJava
-keep class rx.schedulers.Schedulers {
    public static <methods>;
}
-keep class rx.schedulers.ImmediateScheduler {
    public <methods>;
}
-keep class rx.schedulers.TestScheduler {
    public <methods>;
}
-keep class rx.schedulers.Schedulers {
    public static ** test();
}
-dontwarn rx.internal.util.unsafe.**
-keep class rx.internal.util.unsafe.** { *;}

如果打包出現(xiàn)如'can't find referenced class'類似混淆錯(cuò)誤,其實(shí)找不到引用的這個(gè)類是第三方包里面的,而且很多時(shí)候我們只需要打亂自己的代碼就行了,第三方包的代碼就是否要打亂就不要管了。我們可以使用
-dontwarn com.xx.bbb.**
-keep class com.xx.bbb.** { ;}
參數(shù)來(lái)保持第三方庫(kù)中的類而不亂,-dontwarn和-keep 結(jié)合使用,意思是保持com.xx.bbb.xx這個(gè)包里面的所有類和所有方法而不混淆,接著還叫ProGuard不要警告找不到com.xx.bbb.
*這個(gè)包里面的類的相關(guān)引用。

OK,重要的就是這些了,基本都是使用最新版本,其它的如Logger是否需要看個(gè)人需要。

到此,我們的APP暫時(shí)完成了一部分的配置了,再次運(yùn)行打包,應(yīng)該不會(huì)因?yàn)橐蕾嚵税鼘?dǎo)致有什么異常。

Goog Luck!!

預(yù)告,下一篇《看我開(kāi)發(fā)干貨集中營(yíng)App(三)~ 基本封裝》將介紹如何將上面依賴的庫(kù)封裝使用哦,滿滿的都是福利哦。

系列文章:

  1. 看我開(kāi)發(fā)干貨集中營(yíng)App(一)~ 開(kāi)篇
  2. 看我開(kāi)發(fā)干貨集中營(yíng)App(二)~ APP初始化

歡迎關(guān)注,轉(zhuǎn)載請(qǐng)注明原文鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容