【說明】html
名稱
|
功能介紹 | 在操做系統中的路徑 | 源碼路徑 |
aapt
(Android Asset Package Tool)
|
Android資源打包工具
|
${ANDROID_SDK_HOME} /build-tools/
ANDROID_VERSION/aapt
|
frameworks\base\tools\aap
|
aidl
(android interface definition language)
|
Android接口描述語言,java 將aidl轉化爲.java文件的工具android |
${ANDROID_SDK_HOME}/build-tools/
ANDROID_VERSION/aidl
|
frameworks\base\tools\aidl
|
javac | Java Compiler | ${JDK_HOME}/javagit c或/usr/bin/javacgithub |
|
dex |
轉化.class文件爲Davik VM
能識別的.dex文件
|
${ANDROID_SDK_HOME}/build-tools/
ANDROID_VERSION/dx
|
|
apkbuilder |
生成apk包
|
${ANDROID_SDK_HOME}/tools/
apkbuilder
|
sdk\sdkmanager\libs\sdklib\
src\com\android\sdklib\build\
ApkBuilderMain.java
|
jarsigner | .jar文件的簽名工具 | ${JDK_HOME}/jarsigner或/usr/bin/jarsigner |
|
zipalign | 字節碼對齊工具 | ${ANDROID_SDK_HOME}/toolsweb /zipalign算法 |
|
【手動】bootstrap
o爲了可以手動對齊程序包,Android 1.6及之後的SDK的tools/文件夾下都有zipalign工具。你可使用它來對齊任何版本下的程序包。你必須在簽名apk文件後進行,安全
使用如下命令:zipalign -v 4 source.apk destination.apk性能優化
【驗證對齊】
o如下的命令用於檢查程序包是否進行了對齊:zipalign -c -v 4 application.apk
【使用Android studio】
android studio 中的build.gradle文件中加入zipAlignEnabled true
相似於buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile ('proguard-android.txt' ), 'proguard-rules.txt'
zipAlignEnabled true
}
}
【參考文章1】https://www.jianshu.com/p/b524b151d35f
【參考文章2】https://www.yiibai.com/jenkins/ Jenkins教程
【說明】通常的項目開發的使用流程以下:本身遠程倉庫與項目遠程倉庫分離;
至此,整個 pull request 的過程就結束了。
【實例演示】
理解了 pull request 的含義和流程,具體操做也就簡單了。以 Github 排名最高的 https://github.com/twbs/bootstrap 爲例說明。
1. 先點擊 fork 倉庫,項目如今就在你的帳號下了
2. 在你本身的機器上 git clone 這個倉庫,切換分支(也能夠在 master 下),作一些修改。
~ git clone https://github.com/beepony/bootstrap.git
~ cd bootstrap ~ git checkout -b test-pr ~ git add . && git commit -m "test-pr" ~ git push origin test-pr
3. 完成修改以後,回到 test-pr 分支,點擊旁邊綠色的 Compare & pull request 按鈕
以上就是 pull reqesut 的整個流程
【爲何須要進行混淆】
java是一種跨平臺的解釋性語言,java的源碼會編譯成爲字節碼存在.class文件中,因爲跨平臺的須要,java的字節碼包含了許多的源碼的信息,包括變量名方法名等等;
而且能夠經過這些名稱訪問變量名和方法,這些信息不少是無用的,可是容易被編譯成爲java源碼,防止被反編譯,須要對java源碼進行混淆;
混淆就是對release版本的程序進行從新的組織和處理;處理以後的代碼具備相同的功能,可是代碼是不同的,同時代碼不容易被反編譯,即便反編譯成功以後也不容易被讀懂;
被混淆以後的代碼仍然遵循原來的格式進行調用,執行的結果同樣;對外保證了程序的安全性;對內是透明的,執行的結果是同樣的;
【參考文章】
# 代碼混淆壓縮比,在0和7之間,默認爲5,通常不須要改 -optimizationpasses 5 # 混淆時不使用大小寫混合,混淆後的類名爲小寫 -dontusemixedcaseclassnames # 指定不去忽略非公共的庫的類 -dontskipnonpubliclibraryclasses # 指定不去忽略非公共的庫的類的成員 -dontskipnonpubliclibraryclassmembers # 不作預校驗,preverify是proguard的4個步驟之一 # Android不須要preverify,去掉這一步可加快混淆速度 -dontpreverify # 有了verbose這句話,混淆後就會生成映射文件 # 包含有類名->混淆後類名的映射關係 # 而後使用printmapping指定映射文件的名稱 -verbose -printmapping proguardMapping.txt # 指定混淆時採用的算法,後面的參數是一個過濾器 # 這個過濾器是谷歌推薦的算法,通常不改變 -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* # 保護代碼中的Annotation不被混淆,這在JSON實體映射時很是重要,好比fastJson -keepattributes *Annotation* # 避免混淆泛型,這在JSON實體映射時很是重要,好比fastJson -keepattributes Signature //拋出異常時保留代碼行號,在異常分析中能夠方便定位 -keepattributes SourceFile,LineNumberTable -dontskipnonpubliclibraryclasses用於告訴ProGuard,不要跳過對非公開類的處理。默認狀況下是跳過的,由於程序中不會引用它們,有些狀況下人們編寫的代碼與類庫中的類在同一個包下,而且對包中內容加以引用,此時須要加入此條聲明。 -dontusemixedcaseclassnames,這個是給Microsoft Windows用戶的,由於ProGuard假定使用的操做系統是能區分兩個只是大小寫不一樣的文件名,可是Microsoft Windows不是這樣的操做系統,因此必須爲ProGuard指定-dontusemixedcaseclassnames選項
2,須要保留的東西
# 保留全部的本地native方法不被混淆 -keepclasseswithmembernames class * { native <methods>; } # 保留了繼承自Activity、Application這些類的子類 # 由於這些子類,都有可能被外部調用 # 好比說,第一行就保證了全部Activity的子類不要被混淆 -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 * extends android.view.View -keep public class com.android.vending.licensing.ILicensingService # 若是有引用android-support-v4.jar包,能夠添加下面這行 -keep public class com.xxxx.app.ui.fragment.** {*;} # 保留在Activity中的方法參數是view的方法, # 從而咱們在layout裏面編寫onClick就不會被影響 -keepclassmembers class * extends android.app.Activity { public void *(android.view.View); } # 枚舉類不能被混淆 -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } # 保留自定義控件(繼承自View)不被混淆 -keep public class * extends android.view.View { *** get*(); void set*(***); public <init>(android.content.Context); public <init>(android.content.Context, android.util.AttributeSet); public <init>(android.content.Context, android.util.AttributeSet, int); } # 保留Parcelable序列化的類不被混淆 -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } # 保留Serializable序列化的類不被混淆 -keepclassmembers class * implements java.io.Serializable { static final long serialVersionUID; private static final java.io.ObjectStreamField[] serialPersistentFields; private void writeObject(java.io.ObjectOutputStream); private void readObject(java.io.ObjectInputStream); java.lang.Object writeReplace(); java.lang.Object readResolve(); } # 對於R(資源)下的全部類及其方法,都不能被混淆 -keep class **.R$* { *; } # 對於帶有回調函數onXXEvent的,不能被混淆 -keepclassmembers class * { void *(**On*Event); }
# 保留實體類和成員不被混淆 -keep public class com.xxxx.entity.** { public void set*(***); public *** get*(); public *** is*(); }
一種好的作法是把全部實體都放在一個包下進行管理,這樣只寫一次混淆就夠了,避免之後在別的包中新增的實體而忘記保留,代碼在混淆後由於找不到相應的實體類而崩潰。
2,內嵌類
內嵌類常常會被混淆,結果在調用的時候爲空就崩潰了,最好的解決方法就是把這個內嵌類拿出來,單獨成爲一個類。若是必定要內置,那麼這個類就必須在混淆的時候保留,好比以下:
# 保留內嵌類不被混淆 -keep class com.example.xxx.MainActivity$* { *; }
這個$符號就是用來分割內嵌類與其母體的標誌。
3,對WebView的處理
# 對WebView的處理 -keepclassmembers class * extends android.webkit.webViewClient { public void *(android.webkit.WebView, java.lang.String, android.graphics.Bitmap); public boolean *(android.webkit.WebView, java.lang.String) } -keepclassmembers class * extends android.webkit.webViewClient { public void *(android.webkit.webView, java.lang.String) }
4,對JavaScript的處理
# 保留JS方法不被混淆 -keepclassmembers class com.example.xxx.MainActivity$JSInterface1 { <methods>; }
其中JSInterface是MainActivity的子類
5,處理反射
Class.forName("SomeClass")
SomeClass.class
SomeClass.class.getField("someField")
SomeClass.class.getDeclaredField("someField")
SomeClass.class.getMethod("someMethod", new Class[] {})
SomeClass.class.getMethod("someMethod", new Class[] { A.class })
SomeClass.class.getMethod("someMethod", new Class[] { A.class, B.class })
SomeClass.class.getDeclaredMethod("someMethod", new Class[] {})
SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class })
SomeClass.class.getDeclaredMethod("someMethod", new Class[] { A.class, B.class })
AtomicIntegerFieldUpdater.newUpdater(SomeClass.class, "someField")
AtomicLongFieldUpdater.newUpdater(SomeClass.class, "someField")
AtomicReferenceFieldUpdater.newUpdater(SomeClass.class, SomeType.class, "someField")
在混淆的時候,要在項目中搜索一下上述方法,將相應的類或者方法的名稱進行保留而不被混淆。
# 針對android-support-v4.jar的解決方案 -libraryjars libs/android-support-v4.jar -dontwarn android.support.v4.** -keep class android.support.v4.** { *; } -keep interface android.support.v4.app.** { *; } -keep public class * extends android.support.v4.** -keep public class * extends android.app.Fragment
2,其餘的第三方jar包的解決方案
這個就取決於第三方包的混淆策略了,通常都有在各自的SDK中有關於混淆的說明文字,好比支付寶以下:
# 對alipay的混淆處理 -libraryjars libs/alipaysdk.jar -dontwarn com.alipay.android.app.** -keep public class com.alipay.** { *; }
@keep @keepPublicGetterSetters public class Bean{ public boolean booleanProperty; public int intProperty; public String stringProperty; }