程序员人生 网站导航

安卓转战React-Native之签名打包成Apk并极速多渠道打包

栏目:综合技术时间:2016-06-27 16:52:11

前言

弄安卓的开发应当知道开发好的apk都是需要上传到利用市场给用户下载的,固然有些公司的产品是不用上传到利用市场的(比如我们公司放7牛云)但是也需要放在云上面给用户下载。react-native直接run-android默许是产生1个debug的版本apk明显这是不符合开发需求的,理由很简单debug版本apk是没有进行代码混淆的这是很危险的,所以我们需要个release的版本,下面我们来详细看1下怎样样进行签名打包React Native利用并且多渠道打包。

debug和release版本apk反编译后比较

准备工具

先下载反编译工具包:dex2jar⑵.0、jd-gui、apktool

反编译

先把apk解压获得classes.dex,再取得classes-dex2jar.jar

使用jd-gui查看源代码(debug版本效果)

固然这里只是helloword做个例子,并没有写甚么代码即便混淆了也看不出甚么效果(由于第3方的包都不能混淆),但是混淆后效果还是好点:看下其他的例子(直接偷郭霖的图):(release版本效果)

Android签名文件生成

Android签名文件包括2种格式:.keystore和.jks

安卓签名文件的生成不外乎2种方式:我现在给大家讲授两种签名生成的方法:①:keytool命令方式生成 ,②:Android Studio IDE和Eclipse IDE进行生成。

  • keytool命令生成keystore文件(如果没有安装androidStudio或eclispe)

之前我也有写过用蓝贝儿多渠道打包里面介绍了使用自带的keytool命令生成签名文件,这里再来介绍1下

keytool -genkey -v -keystore losileeya.keystore -alias losileeya(别名) -keyalg RSA(算法) -keysize 2048(密钥长度) -validity 10000(有效期,天单位)

个人比较偏向于使用ide这1种方法,首先是图形界面的,而且少了命令行书写的问题,而且之前我记得在使用Eclipse开发Android的时候也1直使用这类方式,下面我们来看1下生成签名的具体步骤:

  • IDE 工具生成签名文件

    1.Android Studio IDE生成jks文件

    build—>Generate Signed apk

    接下来:

    2.Eclipse IDE生成keystore文件

Gradle配置

(1)把刚才生成的.jks文件考入到项目android/app文件夹下面

(2)直接在工程目录下得android/app/build.gradle中以下节点添加以下内容:
方法1: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 } }

方法2: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 # 是不是混淆第3方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⑴.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 <init>(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 <init>(android.content.Context, android.util.AttributeSet); } -keepclasseswithmembers class * { public <init>(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 <methods>; } # 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 <fields>; } #缺省proguard 会检查每个援用是不是正确,但是第3方库里面常常有些不会用到的类,没有正确援用。如果不配置的话,系统就会报错。 -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 <fields>; } #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

这里写图片描述
网速渣的1逼:5min
这里写图片描述

不存在react.gradle文件的项目打包

对不存在react.gradle文件那末我们就需要生成assets文件夹,并且生成index.android.bundle文件

方法1:利用curl生成
命令以下:

cd ZyReact(定位到你的工程根目录) curl -k "http//localhost:8081/index.android.bundle" >android/app/src/main/assets/index.android.bundle

如图:
这里写图片描述
这里使用的curl.exe要自己去下载,记得需要开启服务。生成成功后以下:
这里写图片描述
方法2:
首先命令切换到该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

下面我们来看1下release包的效果:
这里写图片描述

安装apk

上面的步骤我们已完成了项目的签名打包在对应的目录中生成中apk文件,下面我们直接运行以下的命令进即将apk安装到装备中。

cd android && ./gradle installRelease

看图:
这里写图片描述

美团多渠道极速打包

为何要进行多渠道打包?

不弄安卓开发的也许不知道甚么是多渠道打包,ios呢也就1般放appstore里面,但是打包安卓利用商店(1个商店也叫做1个渠道,如360,baidu,xiaomi,利用宝)众多,大大小小几百个,我们发布利用以后需要统计各个渠道的用户下载量,所以才有了多渠道打包。

怎样样统计各个渠道的下载量呢?

现在有比较成熟的第3方利用帮我们实现统计功能(比如友盟),统计的本质就是搜集用户信息传输到后台,后台生成报表,帮助我们跟踪分析并完善app。通过系统的方法已可以获得到,版本号,版本名称,系统版本,机型,地区等各种信息,惟独利用商店(渠道)的信息我们是没有办法从系统获得到的,所以我们就人为的在apk里面添加渠道信息(其实就用1个字段进行标识,如360,baidu),我们只要把这些信息打包到apk文件并将信息传输到后台,后台根据这个标识,可以统计各个渠道的下载量了,并没有多么的高大上。
说了那末多,其实多渠道打包只需要关注两件事情:

1.将渠道信息写入apk文件

2.将apk中的渠道信息传输到统计后台

常见的多渠道打包方法有哪些?

1.插件打包法
2.Android的productFlavors打包法

之前我也写过量渠道比如蓝贝壳多渠道(插件打包法)打包,但是呢速度还是比较慢,然后也写过android studio的多渠道打包(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文件夹并且下面生成了多个渠道包:
这里写图片描述

总结

时间不早了就写到这里,打包的知识又温习了1遍,写个博客各种截图也是相当的累,其实打包React-Native没有几句代码。

  • 生成自己的签名文件 (.jks或。keystore)
  • 配置gradle文件
  • 写代码混文件
  • 有必要的话生成assets文件夹,并且写入index.android.bundle
  • gradle assembleRelease履行打包命令
  • 有需求的话多渠道打包

好了,做任何1件事都不是简单,惟有自己熟习做起来才快,好好学习好好生活吧。

come on,enjoy it

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐