編輯:關於Android編程
搞安卓的開發應該知道開發好的apk都是需要上傳到應用市場給用戶下載的,當然有些公司的產品是不用上傳到應用市場的(比如我們公司放七牛雲)但是也需要放在雲上面給用戶下載。react-native直接run-android默認是產生一個debug的版本apk顯然這是不符合開發需求的,理由很簡單debug版本apk是沒有進行代碼混淆的這是很危險的,所以我們需要個release的版本,下面我們來詳細看一下怎麼樣進行簽名打包React Native應用並且多渠道打包。
先下載反編譯工具包:dex2jar-2.0、jd-gui、apktool
先把apk解壓獲取classes.dex,再獲得classes-dex2jar.jar
使用jd-gui查看源代碼(debug版本效果)
當然這裡只是helloword做個例子,並沒有寫什麼代碼即使混淆了也看不出什麼效果(因為第三方的包都不能混淆),但是混淆後效果還是好點:看下其他的例子(直接偷郭霖的圖):(release版本效果)
Android簽名文件包含2種格式:.keystore和.jks
安卓簽名文件的生成不外乎2種方式:我現在給大家講解兩種簽名生成的方法:①:keytool命令方式生成 ,②:Android Studio IDE和Eclipse IDE進行生成。
keytool命令生成keystore文件(如果沒有安裝androidStudio或eclispe)以前我也有寫過用藍貝兒多渠道打包裡面介紹了使用自帶的keytool命令生成簽名文件,這裡再來介紹一下
keytool -genkey -v -keystore losileeya.keystore -alias losileeya(別名) -keyalg RSA(算法) -keysize 2048(密鑰長度) -validity 10000(有效期,天單位)
vcq9o6zPwsPmztLDx8C0v7TSu8/Cyfqzycepw/u1xL7fzOWyvdboOjwvcD4NCjxwPklERSC5pL7fyfqzycepw/vOxLz+PC9wPg0KPHA+MS5BbmRyb2lkIFN0dWRpbyBJREXJ+rPJamtzzsS8/jwvcD4NCjxjZW50ZXI+DQoJJm5ic3A7PC9jZW50ZXI+DQo8cD4mbmJzcDs8L3A+DQo8YmxvY2txdW90ZT4NCgk8cD5idWlsZCZtZGFzaDsmZ3Q7R2VuZXJhdGUgU2lnbmVkIGFwazwvcD4NCjwvYmxvY2txdW90ZT4NCjxwPjxpbWcgYWx0PQ=="" src="/uploadfile/Collfiles/20160530/20160530092541244.png" title="\" />接下來:
2.Eclipse IDE生成keystore文件
Gradle配置
(1)把剛才生成的.jks文件考入到項目android/app文件夾下面
(2)直接在工程目錄下得android/app/build.gradle中以下節點添加如下內容:
方法一:gradle的全局配置:
修改項目中gradle.properties文件MYAPP_RELEASE_STORE_FILE=losileeya.jks MYAPP_RELEASE_KEY_ALIAS=losileeya MYAPP_RELEASE_STORE_PASSWORD=losileeya MYAPP_RELEASE_KEY_PASSWORD=losileeya
直接在工程目錄下得android/app/build.gradle中以下節點添加如下內容:
signingConfigs { release { storeFile file(MYAPP_RELEASE_STORE_FILE) storePassword MYAPP_RELEASE_STORE_PASSWORD keyAlias MYAPP_RELEASE_KEY_ALIAS keyPassword MYAPP_RELEASE_KEY_PASSWORD } } buildTypes { release { ... signingConfig signingConfigs.release } }
方法二:gradle的局部配置:
signingConfigs { release { storeFile file("C://Users/Administrator/ZyReact/android/app/losileeya.jks")//這裡可以寫絕對位置或者相對位置 storePassword "losileeya" keyAlias "losileeya" keyPassword "losileeya" } } buildTypes { release { minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" signingConfig signingConfigs.release } }
看圖:
記得把enableProguardInReleaseBuilds改為true,最好把enableSeparateBuildPerCPUArchitecture = true,然後各種簽名參數的值都不能錯否則打包失敗,基本上build.gradle的配置也就這些了。當然代碼混淆文件proguard-rules.pro自己配置。
例如我上個項目:# This is a configuration file for ProGuard. # http://proguard.sourceforge.net/index.html#manual/usage.html # 指定代碼的壓縮級別0~7 -optimizationpasses 5 # 是否使用大小寫混合 -dontusemixedcaseclassnames # 是否混淆第三方jar -dontskipnonpubliclibraryclasses # 混淆時是否做預校驗 -dontpreverify #重命名 -renamesourcefileattribute SourceFile #保護給定的可選屬性,例如LineNumberTable, LocalVariableTable, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses. -keepattributes SourceFile,LineNumberTable # 混淆時是否記錄日志 -verbose -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* ##壓縮 #不壓縮輸入的類文件 -dontshrink ##優化 #不優化輸入的類文件 -dontoptimize #優化時允許訪問並修改有修飾符的類和類的成員 -allowaccessmodification #混淆庫 -libraryjars libs/volley.jar -libraryjars libs/android-support-v4.jar -libraryjars libs/gson-2.3.1.jar -libraryjars libs/locSDK_6.13.jar -libraryjars libs/zxing-core-3.1.0.jar #-libraryjars libs/MarsorUtils-1.0.0-SNAPSHOT.jar -libraryjars libs/dom4j-2.0.0-RC1.jar -libraryjars libs/mta-sdk-1.6.2.jar -libraryjars libs/open_sdk_r5509.jar -libraryjars libs/libammsdk.jar -libraryjars libs/WeiboSDKCore_3.1.2.jar -libraryjars libs/alipaySDK-20150724.jar -libraryjars libs/CMISUBTSwiper_sdk_v1.3.jar -libraryjars libs/CMSETSwiper_SDK_V3.6.jar -libraryjars libs/dspread_android_sdk_2.4.6.jar -libraryjars libs/message_lib.jar -libraryjars libs/meSdk-1.1.7snapshot_ruiyin.jar -libraryjars libs/disklrucache-2.0.1.jar -libraryjars libs/httpclient-4.2.5.jar -libraryjars libs/httpcore-4.2.4.jar -libraryjars libs/universal-image-loader-1.9.5.jar -keepattributes *Annotation* -keep class android.** {*; } -keep public class * extends android.view -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.pm -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.app.Fragment -keep public class com.android.vending.licensing.ILicensingService -keep class android.support.v4.app.** { *; } -keep class android.support.v7.** { *; } -keep class com.google.gson.** { *; } -keep class com.baidu.mapapi.** { *; } -keep class com.baidu.platform.** { *; } -keep class com.baidu.vi.** { *; } -keep class com.baidu.location.** { *; } -keep class org.apache.http.** { *; } -keep class org.json.** { *; } -keep class com.nostra13.universalimageloader.** { *; } # keep 所有的 javabean -keep class com.richerpay.ryshop.bean.** { *; } # volley # # ------------------------------------------- # # ############### volley混淆 ############### # # ------------------------------------------- -keep class com.android.volley.** {*;} -keep class com.android.volley.toolbox.** {*;} -keep class com.android.volley.Response$* { *; } -keep class com.android.volley.Request$* { *; } -keep class com.android.volley.RequestQueue$* { *; } -keep class com.android.volley.toolbox.HurlStack$* { *; } -keep class com.android.volley.toolbox.ImageLoader$* { *; } -keep class org.dom4j.** { *; } -keep class android.support.annotation.** { *; } -keep class com.tencent.mm.sdk.** {*;} -keep class com.tencent.tauth.** {*;} -keep class com.tencent.open.TDialog$* -keep class com.tencent.open.TDialog$* {*;} -keep class com.tencent.open.PKDialog -keep class com.tencent.open.PKDialog {*;} -keep class com.alipay.android.app.IAlixPay{*;} -keep class com.alipay.android.app.IAlixPay$Stub{*;} -keep class com.alipay.android.app.IRemoteServiceCallback{*;} -keep class com.alipay.android.app.IRemoteServiceCallback$Stub{*;} -keep class com.alipay.sdk.app.PayTask{ public *;} -keep class com.alipay.sdk.app.AuthTask{ public *;} -keep class com.misu.btswiper.**{*;} -keep class com.shxy.cardswiper.**{*;} -keep class com.dspread.xpos.QPOSService.**{*;} -keep class com.bypay.swiper.**{*;} -keep class com.newland.ruiyin.**{*;} # 保持自己定義的類不被混淆 -keep class com.richerpay.ryshop.view.**{*;} -keep class com.richerpay.ryshop.volly.**{*;} -keep class com.richerpay.ryshop.widget.**{*;} -dontwarn org.apache.http.** -keepclassmembers class * { public
(org.json.JSONObject); } -keep public class com.hrbcb.studentloans.R$*{ public static final int *; } # 微信 -keep class com.tencent.mm.sdk.openapi.WXMediaMessage {*;} -keep class com.tencent.mm.sdk.openapi.** implements com.tencent.mm.sdk.openapi.WXMediaMessage$IMediaObject {*;} # 新浪微博 -keep class com.sina.**{*;} #枚舉不被混淆 -keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); } # 保持自定義控件類不被混淆 -keepclasseswithmembers class * { public (android.content.Context, android.util.AttributeSet); } -keepclasseswithmembers class * { public (android.content.Context, android.util.AttributeSet, int); } #點擊事件不被混淆 -keepclasseswithmembers class * { void onClick*(...); } #回調 -keepclasseswithmembers class * { *** *Callback(...); } #get 和set -keepclassmembers public class * extends android.view.View { void set*(***); *** get*(); } #本地方法 -keepclasseswithmembernames class * { native ; } # activity -keepclassmembers class * extends android.app.Activity { public void *(android.view.View); } #實現Parcelable 接口的不被混淆 -keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; } #R文件屬性不被混淆 -keepclassmembers class **.R$* { public static ; } #缺省proguard 會檢查每一個引用是否正確,但是第三方庫裡面往往有些不會用到的類,沒有正確引用。如果不配置的話,系統就會報錯。 -dontwarn android.support.** # 實現Serializable 接口的不被混淆 -keepnames class * implements java.io.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(); public ; } #dom4j不被混淆 -keepclassmembers class org.dom4j.** {*;} #百度定位 -keepclassmembers class com.baidu.location.** {*;} -keepattributes Signature # Gson混淆 ## ---------------------------------- ## ########## Gson混淆 ########## ## ---------------------------------- -keepclassmembers class com.google.gson.** {*;} -keep class sun.misc.Unsafe { *; } -keep class com.google.gson.stream.** { *; } -keep class com.google.gson.examples.android.model.** { *; } # Application classes that will be serialized/deserialized over Gson ##---------------End: proguard configuration for Gson ---------- -ignorewarnings -dontwarn org.xmlpull.v1.XmlSerializer -keepattributes Signature 這個只是規則可以參考下,畢竟react-native沒有什麼activity這寫東西,如果你對這個還是不了解,可以去看郭神的反編譯與混淆技術完全解析(下)
打包文件的生成2種方式
對存在react.gradle文件的項目打包
命令很簡單:
cd android && ./gradle assembleRelease
網速渣的一逼:5min
不存在react.gradle文件的項目打包
對不存在react.gradle文件那麼我們就需要生成assets文件夾,並且生成index.android.bundle文件
方法一:利用curl生成
命令如下:cd ZyReact(定位到你的工程根目錄) curl -k "http//localhost:8081/index.android.bundle" >android/app/src/main/assets/index.android.bundle
如圖:
這裡使用的curl.exe要自己去下載,記得需要開啟服務。生成成功後如下:
方法二:
首先命令切換到該react native項目的主目錄,然後運行以下的命令,生成assets文件夾mkdir -p android/app/src/main/assets
緊接著運行以下命令,進行生成index.android.bundle文件
react-native bundle --platform android --dev false --entry-file index.android.js \ --bundle-output android/app/src/main/assets/index.android.bundle \ --assets-dest android/app/src/main/res/
總之不管哪種方法打包都要執行
cd android && ./gradle assembleRelease
下面我們來看一下release包的效果:
安裝apk
上面的步驟我們已經完成了項目的簽名打包在對應的目錄中生成中apk文件,下面我們直接運行以下的命令進行將apk安裝到設備中。
cd android && ./gradle installRelease
看圖:
美團多渠道極速打包
為什麼要進行多渠道打包?
不搞安卓開發的或許不知道什麼是多渠道打包,ios呢也就一般放appstore裡面,然而打包安卓應用商店(一個商店也叫做一個渠道,如360,baidu,xiaomi,應用寶)眾多,大大小小幾百個,我們發布應用之後需要統計各個渠道的用戶下載量,所以才有了多渠道打包。
怎麼樣統計各個渠道的下載量呢?
現在有比較成熟的第三方應用幫我們實現統計功能(比如友盟),統計的本質就是收集用戶信息傳輸到後台,後台生成報表,幫助我們跟蹤分析並完善app。通過系統的方法已經可以獲取到,版本號,版本名稱,系統版本,機型,地區等各種信息,唯獨應用商店(渠道)的信息我們是沒有辦法從系統獲取到的,所以我們就人為的在apk裡面添加渠道信息(其實就用一個字段進行標識,如360,baidu),我們只要把這些信息打包到apk文件並將信息傳輸到後台,後台根據這個標識,可以統計各個渠道的下載量了,並沒有多麼的高大上。
說了那麼多,其實多渠道打包只需要關注兩件事情:1.將渠道信息寫入apk文件
2.將apk中的渠道信息傳輸到統計後台
常見的多渠道打包方法有哪些?
1.插件打包法
2.Android的productFlavors打包法
下面帶你輕松搞定美團多渠道打包
下載安裝python環境 Python下載地址
下載python腳本 AndroidMultiChannelBuildTool
將ChannelUtil.java代碼集成到工程裡面,在app啟動時獲取渠道號傳送給後台(如友盟:AnalyticsConfig.setChannel(ChannelUtil.getChannel(this)); 在PythonTool/Info/channel.txt中編輯渠道列表,以換行隔開,工程中有示例 打包apk,將apk文件復制到PythonTool目錄下(與py同級),運行(直接雙擊.py文件或者在命令行輸入 python MultiChannelBuildTool.py )py腳本即可打包完成。(生成的渠道apk包在output_** 目錄下)由於我們配置環境的時候下載安裝了python ,只需下載AndroidMultiChannelBuildTool壓縮包解壓後是這樣的:
把簽好名的apk放到py同級目錄下,點擊不到10秒鐘就生成output文件夾並且下面生成了多個渠道包:
總結
時間不早了就寫到這裡,打包的知識又復習了一遍,寫個博客各種截圖也是相當的累,其實打包React-Native沒有幾句代碼。
生成自己的簽名文件 (.jks或。keystore) 配置gradle文件 寫代碼混文件 有必要的話生成assets文件夾,並且寫入index.android.bundle gradle assembleRelease執行打包命令 有需求的話多渠道打包
什麼都先別說,先看預覽圖!預覽圖中是限制了同時最大下載數為 2 的.其實下載管理器的實現是挺簡單的,我們需要弄清楚幾點就行了服務基礎首先我們需要明確一點,下載我們應該使用
Android中Service的一個Demo例子Service組件是Android系統重要的一部分,網上看了代碼,很簡單,但要想熟練使用還是需要Coding。本文,主要貼
首先必須知道JNI是什麼東東?JNI(Java Native Interface)是java本地語言接口,也就是提供一種方法可以用JAVA調用底層語言(C/C++)。一般
11. Android的數據存儲形式在Android中的數據存儲形式主要有以下幾種:SharedPreferrencesSharedPreferrences主要用於存儲一