Android Studio Apk Packing Confusion

Posted by maxedison on Sun, 26 May 2019 22:14:45 +0200

Recently, some problems have been encountered in the package company's project. Here's a record.

Packaging APK under Android Studio

  • This article only talks about the way of AS packaging Apk, eclispe packaging can Baidu itself.

  • There are two ways to pack Apk:

    • The first way
      Use Android Studio's own tools to generate Apk. The specific step is Build > Generate Signed APK, and the interface shown in the figure will appear. If the APK is generated for the first time, a new signature file will need to be created (Figure 2).

Generate APK interface. png

New key.png
  • Here's an explanation of what the box needs to fill in

    • 1. Choose the path to save the new signature file, choose the right path and create the name of the new signature file.
    • 2. Enter the password of the signature file (the password is needed to generate Apk to import the signature file)
    • 3. Confirm password
    • 4. Alias for signature files
    • 5-6 Alias Password and Confirmation Password
    • 7. Your name or code
    • The next 8-12 are companies, organizations, cities, regions and countries (not necessarily, if it is a company project, you can fill in the company name, etc.).
  • After filling in the signature file of this project, if the project has been packaged before, you can import the signature file generated before directly and enter the password. (The password of the signature file must be remembered, and the following will explain why.) Fill in the password you just set as shown, and click Next.



    Select the signature file and enter the password.png
  • Finally, you can choose the output path to generate Apk, the name of Apk, which has two options, Signature Versions, which means packaging a signature version of a file, choosing the app packaged in V1 as jar (usually used as a third-party import project), and choosing the app packaged in v2 as APK version (that is, it can be installed directly on the phone, but online). Generally, there will be no problem in checking both. Okay, so the first way to generate Apk is over. Is it simple?



    Configuration complete packaging Apk.png
  • The second way is to package in the console using commands

First configure the gradle signature file information, as shown in the figure:


Configure signature file information. png

Then in Build Types, select the release just configured (signature configuration information), as shown in the figure.


Select release.png that has just been configured

At this point, we can go to gradle to see the signature file information we just configured, and have a reference in buildTypes, indicating that the signature file has been configured, as shown in the figure.


Signature file information in gradle.png

But if we put the password of the signature file directly in Gradle, it will be unsafe and may be decompiled by others. At this time, we can set it in Gradle, as shown in the figure.


Signature information setting read password.png
  • At this time, we can use the command gradlew assemble Release to generate our Apk in the console of AS (if we use the method of reading password, we will be asked to enter the password of the signature file after entering the command). After entering the command as shown, we can build the generated Apk in app > build > outputs > apk (the APK with debug is an unsigned APK with release in its name). It's our signature packaged APK.

Console input generates Apk command. png

Finally, possible problems

  • When we write the code test, we install the application on the mobile phone. Then when we install the packaged application on the mobile phone again, there will be a "same-name packet with signature conflict already existing", which leads to the failure of the application installation. This is the conflict of our signature file. The signature file used by the application tested and installed is the test signature file of IDE tool (default is debug, so that The signature text is in $HOME/.android/debug.keystore, and the signature file we packaged for APK is the signature file we created ourselves, so the conflict is certain, so we said above that we must save the signature file and password we generated, otherwise when you update the version, it will not be able to overwrite the installation.
  • Choose the existing signature file, if the password is wrong, you can continue to pack, but the final packaging failure will be displayed, error log display can not read the log file, if you use the console input command to generate Apk, then there is no problem.
  • build.gradle under app package, if you turn on minify Enabled true, but the rules of obfuscation file are not configured, it will also package failure. If you do not turn on obfuscation, minify Enabled false, which is also used together with the removal of useless resources. If you turn off obfuscation, you should set shrink false resources accordingly, if it is tr. UE also fails to pack; if you set minify Enabled true separately and obfuscate the rules in the file correctly, you can pack successfully.
 buildTypes {
        release {
          ......
          minifyEnabled true
          shrinkResources true
          ......
   }
}
  • Confusion allocation
    Confusion configurations are commonly used in Apks that are published online. Confusing Apks has two advantages:
    • It can prevent your project from being decompiled by others to obtain source code (how to decompile Apk is not discussed here, decompile tools generally have apktool (decompile Apk to get resource files, where smile file is. java file compiled file, if you want to crack Apk, you need to be familiar with smile grammar, interested in you can study); dex2jar will decompose the DEX file in the Apk to convert. Change to. jar file; jd-gui is a tool that looks at the. jar file generated earlier, so that you can see the decompiled Apk code. If confused, you can see that the package name and class name are replaced by characters such as a b c, so that you can not read the source code, as shown in the following figure)
    • It can reduce the volume of Apk, obfuscate the code, and the volume of packaged Apk will definitely decrease, which is also a scheme of Apk slimming.

jd-gui Views Decompiled Apk Source (Source Obfuscated). png
  • How to mix up

    • Firstly, the obfuscation configuration is made in build.gradle under app directory. The proguard-rules.pro is used to configure debug and release. We can debug the obfuscation rules before release packages the official version, as follows:

Confused configuration gradle.png
  • Secondly, to configure obfuscation rule files, to configure obfuscation file rules, first of all, we need to understand what the rules are, understand the rules, the specific details will not be elaborated here, you can see this article, portal.( http://www.jianshu.com/p/b471db6a01af)
 Parameters:

- include {filename} reads configuration parameters from a given file   
- basedirectory {directoryname} specifies the base directory as the relative file name for the future   
- injars {class_path} specifies the application jar,war,ear, and directory to be processed   
- outjars {class_path} specifies the name of the jar,war,ear, and directory to be output after processing.   
- libraryjars {classpath} specifies the library files required by the application jar,war,ear, and directory to be processed   
- dontskip nonpubliclibraryclasses specifies that non-public library classes are not ignored.   
- dontskip nonpubliclibraryclass members specify that members of library classes that do not ignore package visibility.

Reserved options

- keep {Modifier} {class_specification} protects specified class files and class members   
- Keep class members {modifier} {class_specification} protect members of a specified class, and they will protect better if such classes are protected   
- keep classes with memberships {class_specification} protects members of specified classes and classes, provided that all specified classes and class members exist.   
- keepnames {class_specification} protects the name of the specified class and its members (if they do not compress steps to delete)   
- keep class membernames {class_specification} protects the name of the member of the specified class (if they do not compress steps to delete)   
- keep classes with member names {class_specification} protects the name of the specified class and class members if all the specified class members are present (after the compression step)   
- printseeds {filename} lists the member-keep options for classes and classes, which are standard output to a given file  

compress

- dontshrink uncompressed input class file   
-printusage {filename}   
-whyareyoukeeping {class_specification}  

optimization

- dontoptimize does not optimize input class files   
- assumenosideeffects {class_specification} optimization assumes the specified method without any side effects   
- allowaccessmodification optimization allows access to and modification of modifier classes and class members  

confusion

- dontobfuscate does not confuse input class files   
-printmapping {filename}   
- Apply mapping {filename} Reuse mapping increases confusion   
- obfuscation dictionary {filename} uses keywords in a given file as the name of the method to be obfuscated   
- Application of intrusive overload in overload aggressivity confusion   
- useuniqueclass membernames identifies the name of the member of the unified obfuscation class to increase obfuscation   
- Flatten package hierarchy {package_name} repackages all renamed packages and places them in a given single package   
- repackage class {package_name} repackage all renamed class files in a given single package   
- Dontusemixed class names do not produce a variety of class names when confused   
- Keep attributes {attribute_name,...} protect given optional attributes, such as LineNumberTable, LocalVariable Table, SourceFile, Deprecated, Synthetic, Signature, and InnerClasses.  
- renamesourcefileattribute {string} sets the string constants given in the source file  
  • Finally, I posted the confusion configuration rules file of my packaged project for reference only. If you copy it directly into your project, you may make mistakes in packing. You need to configure it according to your own project. If you use third-party packages in your project, you can usually go to the official website to find the confusion configuration. At this point, the obfuscation configuration is completed, so that the packaged Apk code has been obfuscated.
#Specify the compression level of the code
-optimizationpasses 5

#Wrapped without mixing case and case
-dontusemixedcaseclassnames

#Do not ignore non-public library classes
-dontskipnonpubliclibraryclasses

 #Optimizing class files that do not optimize input
-dontoptimize

 #Pre check
-dontpreverify

 #Whether to log in case of confusion
-verbose

 # The algorithm used in confusion
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*

#Protection annotation
-keepattributes *Annotation*

# What classes should be kept unambiguous
-keep public class * extends android.app.Fragment
-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
#If you have a reference to the v4 package, you can add the following line
-keep public class * extends android.support.v4.app.Fragment


#Ignore warning
-ignorewarning

##Record generated log data,gradle build When output in the root directory of this project##
#The internal structure of all class es in the apk package
-dump proguard/class_files.txt
#Unobfuscated classes and members
-printseeds proguard/seeds.txt
#List the code deleted from the apk
-printusage proguard/unused.txt
#Mapping before and after confusion
-printmapping proguard/mapping.txt
########Record the generated log data. gradle build When output in the root directory of this project-end######

#If v4 or v7 package is referenced
-dontwarn android.support.**

####Obfuscating part of the code that protects your project and the third party that references it jar package library-end####



#Keep the native approach unambiguous
-keepclasseswithmembernames class * {
    native <methods>;
}

#Keep custom control classes unambiguous
-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

#Keep custom control classes unambiguous
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

-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*(...);
}

#Keep Parcelable unambiguous
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

#Keep Serializable unambiguous
-keepnames class * implements java.io.Serializable

#Keep Serializable unambiguous and enum classes unambiguous
-keepclassmembers class * implements java.io.Serializable {
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    !static !transient <fields>;
    !private <fields>;
    !private <methods>;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

#Keep enum classes unambiguous
-keepclassmembers enum * {
  public static **[] values();
  public static ** valueOf(java.lang.String);
}

-keepclassmembers class * {
    public void *ButtonClicked(android.view.View);
}

#Do not confuse resource classes
-keepclassmembers class **.R$* {
    public static <fields>;
}

#Avoid confusing generics if confusing error reporting is recommended to turn off
-keepattributes Signature

#Remove the code of Log class to print all levels of logs, and use it as a forbidden log when typing formal packages. Here it can be used as a function of forbidding log printing. Another implementation scheme is controlled by variables of BuildConfig.DEBUG.
-assumenosideeffects class android.util.Log {
    public static *** v(...);
    public static *** i(...);
    public static *** d(...);
    public static *** w(...);
    public static *** e(...);
}

#gson
#If you use the Gson parsing package, you can successfully confuse by adding the following lines directly, otherwise you will report an error.
-keepattributes Signature
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
# Application classes that will be serialized/deserialized over Gson
-keep class com.google.gson.** { *; }
-keep class com.google.gson.stream.** { *; }

#mob
-keep class android.net.http.SslError
-keep class android.webkit.**{*;}
-keep class cn.sharesdk.**{*;}
-keep class com.sina.**{*;}
-keep class m.framework.**{*;}
-keep class **.R$* {*;}
-keep class **.R{*;}
-dontwarn cn.sharesdk.**
-dontwarn **.R$*

#butterknife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }

-keepclasseswithmembernames class * {
    @butterknife.* <fields>;
}

-keepclasseswithmembernames class * {
    @butterknife.* <methods>;
}

# If you use tools like Gson to keep the JavaBean classes that it parses, that is, entity classes, from being confused.
-keep class com.lecloud.base.** { *; }
-keep class com.lecloud.imlib.** { *; }
-keep class com.lecloud.leblockmodelmanager.** { *; }


# Avoid confusion in allied Statistics - ---------------------------------------------------------------------------------------------------------------------------------
-dontwarn Android.support.v4.**
-dontwarn org.apache.commons.net.**
-dontwarn com.tencent.**
-keepclasseswithmembernames class * {
    native <methods>;
}
-keepclasseswithmembernames class * {
    public <init>(Android.content.Context, Android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
    public <init>(Android.content.Context, Android.util.AttributeSet, int);
}
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
-keep class * implements Android.os.Parcelable {
  public static final Android.os.Parcelable$Creator *;
}
-keepclasseswithmembers class * {
    public <init>(Android.content.Context);
}
-dontshrink
-dontoptimize
-dontwarn com.google.Android.maps.**
-dontwarn Android.webkit.WebView
-dontwarn com.umeng.**
-dontwarn com.tencent.weibo.sdk.**
-dontwarn com.facebook.**
-keep enum com.facebook.**
-keepattributes Exceptions,InnerClasses,Signature
-keepattributes *Annotation*
-keepattributes SourceFile,LineNumberTable
-keep public interface com.facebook.**
-keep public interface com.tencent.**
-keep public interface com.umeng.socialize.**
-keep public interface com.umeng.socialize.sensor.**
-keep public interface com.umeng.scrshot.**
-keep public class com.umeng.socialize.* {*;}
-keep public class javax.**
-keep public class Android.webkit.**
-keep class com.facebook.**
-keep class com.umeng.scrshot.**
-keep public class com.tencent.** {*;}
-keep class com.umeng.socialize.sensor.**
-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 im.yixin.sdk.api.YXMessage {*;}
-keep class im.yixin.sdk.api.** implements im.yixin.sdk.api.YXMessage$YXMessageData{*;}
-keep public class [your_pkg].R$*{
    public static final int *;
}

#Jpush
-dontoptimize
-dontpreverify

-dontwarn cn.jpush.**
-keep class cn.jpush.** { *; }

#retroift
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions

#ButterKnife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
    @butterknife.* <fields>;
}

-keepclasseswithmembernames class * {
    @butterknife.* <methods>;
}
#fastjson
-dontwarn com.alibaba.fastjson.**
-keep class com.alibaba.fastjson.** { *; }

#WebView processing, the project does not use webView ignore can be
-keepclassmembers class fqcn.of.javascript.interface.for.webview {
   public *;
}
-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, jav.lang.String);
}

#Melting clouds
-keepattributes Exceptions,InnerClasses

-keepattributes Signature

# RongCloud SDK
-keep class io.rong.** {*;}
-keep class * implements io.rong.imlib.model.MessageContent {*;}
-dontwarn io.rong.push.**
-dontnote com.xiaomi.**
-dontnote com.google.android.gms.gcm.**
-dontnote io.rong.**

# VoIP
-keep class io.agora.rtc.** {*;}

# Location
-keep class com.amap.api.**{*;}
-keep class com.amap.api.services.**{*;}

# Red envelopes
-keep class com.google.gson.** { *; }
-keep class com.uuhelper.Application.** {*;}
-keep class net.sourceforge.zbar.** { *; }
-keep class com.google.android.gms.** { *; }
-keep class com.alipay.** {*;}
-keep class com.jrmf360.rylib.** {*;}

-ignorewarnings

#Player Framework
-keep class tv.danmaku.ijk.media.player.** {*;}

Okay, that's all for this record. If you find something wrong, please point out to me that everyone is learning and making progress together. If you think the article is helpful to you, please give me a favorite.

Reference article: http://blog.csdn.net/u012124438/article/details/54958757

Topics: Android Java Gradle ButterKnife