|
Use gradle packaged apk has become the main trend, I also experienced this process needs, and we will continue with gradle new support, one by one to improve. Here, we put these things related records, make a summary.
1. Replace the placeholder AndroidManifest
I want one of the $ {app_label} Replace @ string / app_name
android {
defaultConfig {
manifestPlaceholders = [app_label: "@ string / app_name"]
}
}
If you want to replace the debug version:
android {
buildTypes {
debug {
manifestPlaceholders = [app_label: "@ string / app_name_debug"]
}
release {
}
}
}
More demand is to replace the channel number:
android {
productFlavors {
// Replace dev dev product model apk's AndroidManifest the channel
"Dev" {
manifestPlaceholders = [channel: "dev"]
}
}
}
2. The independent configuration signature information
For signature-related information, write directly gradle course not, especially some open source projects can be added to gradle.properties:
RELEASE_KEY_PASSWORD = xxxx
RELEASE_KEY_ALIAS = xxx
RELEASE_STORE_PASSWORD = xxx
RELEASE_STORE_FILE = .. /. Keystore / xxx.jks
Then referenced in build.gradle accordingly:
android {
signingConfigs {
release {
storeFile file (RELEASE_STORE_FILE)
storePassword RELEASE_STORE_PASSWORD
keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD
}
}
}
If you do not want to submit to the repository can be added to local.properties then read build.gradle in.
3. The multi-channel package
The key to multi-channel package that define different product flavor, the channel and the channel number AndroiManifest replace the corresponding flavor identification:
android {
productFlavors {
dev {
manifestPlaceholders = [channel: "dev"]
}
official {
manifestPlaceholders = [channel: "official"]
}
// ... ...
wandoujia {
manifestPlaceholders = [channel: "wandoujia"]
}
xiaomi {
manifestPlaceholders = [channel: "xiaomi"]
}
"360" {
manifestPlaceholders = [channel: "360"]
}
}
Note that in mind, here's the name if it is the beginning of the flavor numbers must be enclosed in quotes.
Build it, we will be able to generate a series of Build Variant:
devDebug
devRelease
officialDebug
officialRelease
wandoujiaDebug
wandoujiaRelease
xiaomiDebug
xiaomiRelease
360Debug
360Release
Wherein the debug, release is gradle default comes with two build type, the following section will continue to be described.
Select one, will be able to compile the apk corresponding to the channel.
4 Custom Build Type
As mentioned earlier, there are two default build type debug and release, the following differences:
// BuildConfig feature release version generated information
public final class BuildConfig {
public static final boolean DEBUG = false;
public static final String BUILD_TYPE = "release";
}
BuildConfig characteristics // debug information generated version
public final class BuildConfig {
public static final boolean DEBUG = true;
public static final String BUILD_TYPE = "debug";
}
There is a need to add a build type, interposed between debug and release, and release version is the same, but you want to keep debug state (if done rom development, then, is similar user debug version), we called the preview version it.
It is actually very simple:
android {
signingConfigs {
debug {
storeFile file (RELEASE_STORE_FILE)
storePassword RELEASE_STORE_PASSWORD
keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD
}
preview {
storeFile file (RELEASE_STORE_FILE)
storePassword RELEASE_STORE_PASSWORD
keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD
}
release {
storeFile file (RELEASE_STORE_FILE)
storePassword RELEASE_STORE_PASSWORD
keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD
}
}
buildTypes {
debug {
manifestPlaceholders = [app_label: "@ string / app_name_debug"]
}
release {
manifestPlaceholders = [app_label: "@ string / app_name"]
}
preview {
manifestPlaceholders = [app_label: "@ string / app_name_preview"]
}
}
}
In addition, build type there is a benefit, if you want to generate a one-time All preview versions, you can execute assemblePreview, debug and releae version empathy.
5. build type of customization parameters
Above us in a different build type to replace $ {app_label} for the different strings, so install on the phone you can clearly distinguish the different build type versions.
In addition, you may also be able to configure some parameters, I have here a few columns I used at work:
android {
debug {
manifestPlaceholders = [app_label: "@ string / app_name_debug"]
applicationIdSuffix ".debug"
minifyEnabled false
signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile ( 'proguard-android.txt'), 'proguard-rules.pro'
}
release {
manifestPlaceholders = [app_label: "@ string / app_name"]
minifyEnabled true
shrinkResources true
signingConfig signingConfigs.release
proguardFiles getDefaultProguardFile ( 'proguard-android.txt'), 'proguard-rules.pro'
}
preview {
manifestPlaceholders = [app_label: "@ string / app_name_preview"]
applicationIdSuffix ".preview"
debuggable true // Reserved debug information
minifyEnabled true
shrinkResources true
signingConfig signingConfigs.preview
proguardFiles getDefaultProguardFile ( 'proguard-android.txt'), 'proguard-rules.pro'
}
}
}
These are used too much, a little explanation:
// MinifyEnabled obfuscated
// ShrinkResources removing unwanted resources
// SigningConfig signature
// ProguardFiles confusing configuration
// ApplicationIdSuffix increase the suffix APP ID
// Debuggable whether to keep the debugging information
// ... ...
6. Multi-project global configuration
With the roll out of the product channels, often set of code needed to support multiple product forms, which need to abstract the main code to a Library, and then based on the Library extended several App Module.
I believe everyone will have this module is build.gradle Code:
android {
compileSdkVersion 22
buildToolsVersion "23.0.1"
defaultConfig {
minSdkVersion 10
targetSdkVersion 22
versionCode 34
versionName "v2.6.1"
}
}
When upgrading sdk, build tool, target sdk, etc., several module to be changed very troublesome. Most importantly, it is easy to forget that ultimately lead to differences between the app module is not uniform, nor controllable.
Powerful gradle plugin support global variables set in 1.1.0, one solution to this problem.
First in the root directory of the project ext build.gradle defined global variables:
ext {
compileSdkVersion = 22
buildToolsVersion = "23.0.1"
minSdkVersion = 10
targetSdkVersion = 22
versionCode = 34
versionName = "v2.6.1"
}
Then in the module's build.gradle referenced as follows:
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
applicationId "com.xxx.xxx"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode rootProject.ext.versionCode
versionName rootProject.ext.versionName
}
}
Then each modification project can achieve the global level build.gradle unified configuration.
7. Custom APK name derived
When the name of the default apk android studio generated for app-debug.apk or app-release.apk, when there are multiple channels when the need to compile a package of 50 channels, in trouble, do not know who is who.
This time, you need to customize the name for the export of APK, the different channels made out of APK file name should be different.
android {
// Rename the apk with the version name
applicationVariants.all {variant ->
variant.outputs.each {output ->
output.outputFile = new File (
output.outputFile.parent,
"Ganchai - $ {variant.buildType.name} - $ {variant.versionName} - $ {variant.productFlavors [0] .name} .apk" .toLowerCase ())
}
}
}
When apk too, if we can apk press debug, release, preview points about class the better (in fact, for me, often made version of the people, a provision will often edited versions of forty to fifty people, debug and release version can not see the whole mix, it must be classified), simply:
android {
// Rename the apk with the version name
// Add output file sub folder by build type
applicationVariants.all {variant ->
variant.outputs.each {output ->
output.outputFile = new File (
output.outputFile.parent + "/${variant.buildType.name}",
"Ganchai - $ {variant.buildType.name} - $ {variant.versionName} - $ {variant.productFlavors [0] .name} .apk" .toLowerCase ())
}
}
}
Now generates a format similar to this package ganchai-dev-preview-v2.4.0.0.apk up, preview packages naturally in the preview folder, clear.
8. confusion Tips
Confusion let decompiled code readability becomes poor, but also significantly reduce the size of the APK package.
1). The first trick
I believe many of my friends to feel confused trouble, and even that is very chaotic. Adding confusion because the rules need to check the official documentation, and even some official documents not described. When you quote too many libraries, the rule will add confusion nightmare.
Here's a tip, do not check the official documentation, instead of individual libraries consider adding rules.
First, in addition to the default configuration of confusion (android-sdk / tools / proguard / proguard-android.txt), your code will definitely have to configure their own:
## Proguard-rules.pro module located under
#####################################
The main program can not be obfuscated code ######### #########
#####################################
-dontwarn xxx.model. **
-keep class xxx.model ** {*;}.
##, Etc., on your own code clear
#####################################
########### Does not optimize Generics and reflection ##########
#####################################
-keepattributes Signature
Next is troublesome third-party libraries, in general, if the aurora is pushing it, it's packages are cn.jpush, add the following code:
-dontwarn cn.jpush. **
-keep class cn.jpush ** {*;}.
Other third library, too, add one by one, tired! In fact, you can use third-party anti-compiler tool (eg jadx: https: //github.com/skylot/jadx), open apk, one can see a reference to the package name all third-party libraries, all do not want to confuse or not determination can not be confused, and are added directly to what is wrong:
#####################################
######### Third-party library or jar package ###########
#####################################
-dontwarn cn.jpush. **
-keep class cn.jpush ** {*;}.
-dontwarn com.squareup. **
-keep class com.squareup ** {*;}.
-dontwarn com.octo. **
-keep class com.octo ** {*;}.
-dontwarn de. **
-keep class de ** {*;}.
-dontwarn javax. **
-keep class javax ** {*;}.
-dontwarn org. **
-keep class org ** {*;}.
-dontwarn u.aly. **
-keep class u.aly ** {*;}.
-dontwarn uk. **
-keep class uk ** {*;}.
-dontwarn com.baidu. **
-keep class com.baidu ** {*;}.
-dontwarn com.facebook. **
-keep class com.facebook ** {*;}.
-dontwarn com.google. **
-keep class com.google ** {*;}.
## ... ...
2) The second technique
After the general release version confusion, such as Friends of the Union statistical system crashes if there is an exception, it will be recorded as follows:
java.lang.NullPointerException: java.lang.NullPointerException
at com.xxx.TabMessageFragment $ 7.run (Unknown Source)
Unknown Source This is very terrible, errors can not be ruled out targeting a specific line, greatly reducing the debugging efficiency.
Of course, the Friends of the Union Mapping supports uploading files to help locate the position of the mapping file:
project> module
> Build> outputs> {flavor name}> {build type}> mapping.txt
If more than one version, mapping.txt regenerate every time, but also to upload, or after all the trouble.
In fact, adding proguard-rules.pro the following code:
-keepattributes SourceFile, LineNumberTable
Of course apk package will be a little bit large (I am here 6M bag, big 200k of it), but no longer mapping.txt can locate the line, in order to escape this, I personally feel that this price is the value, and value!
9. Dynamic set some additional information
If you want to compile the current time, the compiler of the machine, the latest version adds to commit apk, which in turn does not write the information in the code, powerful gradle gave me the possibility to create self-confidence:
android {
defaultConfig {
resValue "string", "build_time", buildTime ()
resValue "string", "build_host", hostName ()
resValue "string", "build_revision", revision ()
}
}
def buildTime () {
return new Date () format. ( "yyyy-MM-dd HH: mm: ss")
}
def hostName () {
return System.getProperty ( "user.name") + "@" + InetAddress.localHost.hostName
}
def revision () {
def code = new ByteArrayOutputStream ()
exec {
commandLine 'git', 'rev-parse', '--short', 'HEAD'
standardOutput = code
}
return code.toString ()
}
The code to achieve a dynamic adds three string resource: build_time, build_host, build_revision, and elsewhere may like or as a quoted string used as follows:
// Call Activity in
getString (R.string.build_time) // output 2015-11-07 17:01
getString (R.string.build_host) // output jay @ deepin, this is the user name and the name of my PC computer
getString (R.string.build_revision) // output 3dd5823, this is the last commit sha value of
This place, how to return results from the command line to read, very interesting.
In fact, when I learn from this code VLC source chance to see, inspired, not exclusive, special excerpt here.
vlc source code and compile address: https: //wiki.videolan.org/AndroidCompile, are interested can last a View.
10. give yourself a "back door": seven point
To facilitate debugging, we tend to stay in the debug version of a show that we want to see the interface (remember a previous version of iOS on the microblogging leaked a debugging interface), how to enter into a single interface, we can follow the way android developer options , seven points only shows that we achieved a:
private int clickCount = 0;
private long clickTime = 0;
sevenClickView.setOnClickListener (new View.OnClickListener () {
@Override
public void onClick (View view) {
if (clickTime == 0) {
clickTime = System.currentTimeMillis ();
}
if (System.currentTimeMillis () - clickTime> 500) {
clickCount = 0;
} Else {
clickCount ++;
}
clickTime = System.currentTimeMillis ();
if (clickCount> 6) {
// 2.7 condition is reached, jump to the debug interface
}
}
});
release version will definitely not be exposed to this interface, we can not make use am at the command line from the transfer, how to prevent it, can be exported in the release version of the debug interface is set to false.
11. Build Automation
How to package jenkins android and ios, and upload it to the platform dandelion, this can refer to my other article devoted to: "Building Android and iOS apps using Jenkins automation", but not finished the article, in fact, the company has been using, and always finish the day in a good mood, and not repeat them here.
12. Summary
android groovy package because of the strong language, become powerful at the same time must also become complicated, today put me through these doorways look out for track, do a little summary, I will add subsequent updates. |
|
|
|