文件:列出生成的APK文件中所有类、方法和字段的映射关系;
3
proguard-rules.pro:包含混淆规则的文件;
4
proguard-android.txt:包含基本的混淆规则。
在项目中使用Gson等库时,需要对混淆文件进行处理,以确保这些库能够正常工作。具体操作如下:
1)在项目的build.gradle文件中添加Gson依赖:
```groovy
dependencies {
implementation 'com.google.code.gson:gson:2.8.9'
}
```
2)在项目的app模块下的build.gradle文件中启用ProGuard,并配置混淆规则:
```groovy
android {
...
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
```
3)在项目的proguard-rules.pro文件中添加Gson混淆规则:
```pro
# Gson混淆规则
-keep class com.google.gson.** { *; }
-dontwarn com.google.gson.**
```
完成以上步骤后,重新打包应用并发布到测试手机上,上传功能应该可以正常使用了。
混淆后的代码与原始Java源码之间的映射关系可以通过以下几个文件来实现:
1. mapping.txt:该文件列出了混淆前的Java源码与混淆后的类、方法和属性名字之间的映射关系。通过阅读这个文件,有心人可以利用这些映射关系将混淆后的代码反推导出原来项目中的代码。因此,这个文件需要保护好,以防止未经授权的访问。需要注意的是,ProGuard无法对字符串进行混淆,所以在某些情况下,反编译后的代码可能会包含一些关键字,如http/https等,这些关键字可能泄露关键信息,如竞品使用了哪些API接口、提交数据到哪个网址等。因此,在实际项目中,我们不能完全依赖ProGuard进行混淆,而是需要自主处理混淆文件,掌握混淆规则,以避免程序运行出错。
2. seeds.txt:此文件列出了被混淆的类和成员。在使用ProGuard进行混淆时,可以通过设置seeds文件来指定哪些类和成员不进行混淆。这样,在混淆后,我们可以轻松地找到这些未被混淆的类和成员。
3. usage.txt:此文件列出了从APK文件中剥离的代码。通过对usage文件的分析,我们可以了解在混淆过程中哪些代码被保留下来,以及它们的位置和作用。这有助于我们在混淆后的项目中找到潜在的问题,并进行相应的修复。
总体来说,我们在编写混淆规则时主要考虑以下四类情况:
1)通用混淆配置:每个项目都会使用到的配置。这段配置几乎是固定的,主要用于指定基本的混淆选项,如忽略注释、保留包名等。
2)针对特定类或成员的混淆配置:针对某些特定的类或成员进行特殊处理的配置。例如,我们可以为某个特定的类设置一个别名,或者为某个特定的方法设置一个不同的名称,以便在混淆后的代码中更容易识别。
3)针对特定字符串的混淆配置:针对某些特定的字符串(如关键字、数字等)进行特殊处理的配置。例如,我们可以将某个关键字替换为一个不易识别的字符序列,以防止其被轻易获取。
4)针对特定路径或资源的混淆配置:针对某些特定的文件路径或资源名称进行特殊处理的配置。例如,我们可以将某个文件路径替换为一个不易识别的字符序列,以防止其被轻易获取。
以下是重构后的代码:
```java
// 代码混淆压缩比,在0~7之间
-optimizationpasses 5
// 混合时不使用大小写混合,混合后的类名为小写
-dontusemixedcaseclassnames
// 指定不去忽略非公共库的类
-dontskipnonpubliclibraryclasses
// 不做预校验,preverify是proguard的四个步骤之一,Android不需要preverify,去掉这一步能够加快混淆速度。
-dontpreverify
-verbose
// Google推荐算法
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
// 避免混淆Annotation、内部类、泛型、匿名类
-keepattributes *Annotation*,InnerClasses,Signature,EnclosingMethod
// 重命名抛出异常时的文件名称
-renamesourcefileattribute SourceFile
// 抛出异常时保留代码行号
-keepattributes SourceFile,LineNumberTable
// 处理support包
-dontnote android.support.**
-dontwarn android.support.**
// 保留四大组件,自定义的Application等这些类不被混淆
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Appliction
-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.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
// 保留本地native方法不被混淆
-keepclasseswithmembernames class * { native <methods>; }
// 保留枚举类不被混淆
-keepclassmembers enum * { public static **[] values(); public static ** valueOf(java.lang.String); }
// 保留Parcelable序列化类不被混淆
-keep class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; }
// 第三方jar包不被混淆
-keep class com.github.test.** {*;}
// 保留自定义的Test类和类成员不被混淆
-keep class com.lily.Test {*;}
// 保留自定义的xlog文件夹下面的类、类成员和方法不被混淆
-keep class com.test.xlog.** {
// assume no side effects:删除android.util.Log输出的日志
-assumenosideeffects class android.util.Log { public static *** v(...); public static *** d(...); public static *** i(...); public static *** w(...); public static *** e(...); }
// 保留Keep注解的类名和方法
-keep,allowobfuscation @interface android.support.annotation.Keep
-keep @android.support.annotation.Keep class *
-keepclassmembers class * { @android.support
您好!根据您的问题,我可以为您提供一些有用的信息。在Android开发中,混淆是一项非常重要的安全措施,可以帮助保护应用程序免受反编译和恶意代码的攻击。以下是一些常用的混淆库和框架的混淆配置:
- Gson
- Butterknife
- SlidingMenu
- ImageLoader
- Okhttputils
- Glide
- Picasso
- okhttp
- Okio
- EventBus
- Dagger
- RxJava
- Retrofit2
- GreenDao
- Fresco
- Crashlytics
- Fastjson
- LitePal
请注意,这些库或者框架的混淆文件不是所见即所得,不可以直接复制过去使用,而要看清楚文档的说明再进行操作,把一些路径名包名换成对应项目的。
此外,如果您使用了第三方SDK,阅读最新的第三方提供的文档即可拿到混淆文件,按照文档操作即可。
最后,自定义混淆规则可以保证一些类、类方法、类名不被混淆。比如说自定义view在xml中使用的,自定义view是带有完整路径名的,如果此时没有处理混淆文件,那么一个个路径名变成了a.b.c,那么项目就无法运行了。以下是常用的自定义的混淆规则:optimizationpasses、dontoptimize、dontusemixedcaseclassnames、dontskipnonpubliclibraryclasses、dontpreverify、dontwarn、verbose、optimizations、keep、keepnames、keepclassmembers、keepclassmembernames、keepclasseswithmembers、keepclasseswithmembernames等。
以下是混淆文件通用模板:
```proguard
# 保持类和类中的成员,防止被混淆,但当成员没有被引用时会被移除。前提是指明的类中的成员必须存在。如果不存在,还是会被混淆。
-keepclassmembers class com.example.Test {
public
public void test(java.lang.String);
}
# 不混淆某个类的所有子类
-keep public class com.example.Test extends android.app.Activity { *; }
# 不混淆某个包的所有类
-keepclassmembers class com.example.** { *; }
# 不混淆某个接口的实现
-keep class * implements com.example.TestInterface { *; }
# 不混淆某个类的构造方法
-keepclassmembers class com.example.Test {
private void
}
# 不混淆某个类的特定的方法
-keepclassmembers class com.example.Test {
private void test(java.lang.String) {}
}
# 不混淆某个类的内部类
-keep class com.example.Test$* { *; }
```
```java
-指定代码的压缩级别 0-7(指定代码进行迭代优化的次数,在Android里面默认是5,这条指令也只有在可以优化时起作用) :-optimizationpasses 5
-混淆时不会产生形形色色的类名(混淆时不使用大小写混合类名) :-dontusemixedcaseclassnames
-指定不去忽略非公共的库类(不跳过library中的非public的类) :-dontskipnonpubliclibraryclasses
-指定不去忽略包可见的库类的成员 :-dontskipnonpubliclibraryclassmembers
-不进行优化,建议使用此选项, :-dontoptimize
-不进行预校验,Android不需要,可加快混淆速度。 :-dontpreverify
-屏蔽警告 :-ignorewarnings
-指定混淆是采用的算法,后面的参数是一个过滤器
# 这个过滤器是谷歌推荐的算法,一般不做更改
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/* :-optimizations optimizations/default.xml
# 保护代码中的Annotation不被混淆 :-keepattributes *Annotation*
# 避免混淆泛型, 这对JSON实体映射非常重要 :-keepattributes Signature
# 抛出异常时保留代码行号 :-keepattributes SourceFile,LineNumberTable
# 当有优化和使用-repackageclasses时适用
# 不能用这个指令处理库中的代码,因为有的类和类成员并没有设计成public ,而在api中可能变成public
:allowaccessmodification
# 当有优化和使用-repackageclasses时适用。
:repackageclasses ''
# 混淆时记录日志(打印混淆的详细信息)
:verbose
# ------------------------------
# 默认保留下列类,不进行混淆
#继承activity、application、service、广播接收器、contentprovider....不进行混淆
:keep public class * extends android.app.Activity { ... }
:keep public class * extends android.app.Application { ... }
:keep public class * extends android.support.multidex.MultiDexApplication { ... }
: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.AgentHelperBackend { ... }
:keep public class * extends android.preference.Preference { ... }
:keep public class * extends android.view.View { ... }
:keep class android.support.** { *;}
## 保留support下的所有类及其内部类
:keep public class com.google.vending.licensing.ILicensingService { ... }
:keep public class com.android.vending.licensing.ILicensingService {} //表示不混淆上面声明的类这两个类我们基本用不到,是接入Google原生的一些服务时使用的。
# ---------------------------------------------------------
# 继续保持继承的类
:keep public class * extends android.support.v4.** { ... }
:keep public class * extends android.support.v7.** { ... }
:keep public class * extends android.support.annotation.** { ... }
# 不混淆任何包含native方法的类的类名以及native方法名,这个和我们刚才验证的结果是一致的。
:keepclasseswithmembernames class * {
native <methods>
}
# 这个主要是在layout中写的onclick方法android:onclick="onClick",不进行混淆。
:keepclassmembers class * {
void onClick();
}
# 不要混淆Activity中参数是View的方法,因为有这样一种用法,在Android配置中又配置了android:onClick=”buttonClick”属性,当用户点击该按钮时就会调用Activity中的buttonClick(View view)方法。如果这个方法被混淆的话找不到了。
:dontwarn **class *
{
onTouchEvent(android.os.MotionEvent event);
onNewIntent(android.content.Intent intent);
onKeyDown(int keyCode, KeyEvent event);
}
# 对于枚举中的values()和valueOf()方法不要混淆,枚举我用的很少,就不这个评论了。
-keepenumclass enum ** {
public static $Values[] values();
public static $ValueOf(java.lang.String name) throws java.lang.IllegalArgumentException;
}
# 不要混淆任何一个View中的setXxx()和getXxx()方法。因为属性动画需要有相应的setter和getter方法实现的,混淆了无法工作。
# ---------------------------------------------------------
# 不要混淆Parcelable实现类中的CREATOR字段。毫无疑问,CREATOR字段是绝对不能改变的,包括大小写都不能变,否则整个Parcelable工作机制都会失败。
-keep class ** implements android.os.Parcelable {
private static final long serialVersionUID = \\8L;
private static final java.io.ObjectStreamField[] writeFields = {
new java.io.ObjectStreamField(com\\$google\vending\\licensing\\ILicensingService$Creator$$BYTE$$$CLASS$, "CREATOR", com\\$google\\vending\\licensing\\ILicensingService$Creator$.class)};
private static final java.io.ObjectStreamField[] readFields = {
new java.io.ObjectStreamField(com\\$google\\vending\\licensing\\ILicensingService$Creator$$BYTE$$$CLASS$, "CREATOR", com\\$google\\vending\\licensing\ILicensingService$Creator$.class)};
}
private
return (T) new com\\$google\\vending\\licensing\\ILicensingService$Creator(in);
}
private
return new com\\$google\\vending\\licensing\\ILicancingService$Creator[size];
}
private void writeToParcel(android.os.Parcel dest_parcel, int flags) {
dest_parcel << value;
}
private void readFromParcel(android.os.Parcel source_parcel) {
value = (ILicenseCheckResponseType) source_parcel >> value;
}
narrow implementation to library build target always
occursion method only
narrow this method to library build target always
occursion method only
narrow this method to library build target always
occursion method only
narrow this method to library build target always
occursion method only
narrow this method to library build target always
occursion method only
narrow this method to library build target always
occursion method only
narrow this method to library build target always
occursion method only
narrow this method to library build target always
occursion method only
narrow this method to library build target always
occursion method only
narrow this method to library build target always
occursion method only
narrow this method to library build target always
occursion method only
narrow this method to library build target always
occursion method only
narrow this method to library build target always
occursion method only
narrow this method to library build target always
occursion method only
narrow this method to library build target always\o
四、其他注意事项
1 JNI方法不可混淆,因为它们需要与native方法保持一致。可以通过以下代码实现:
```java
-keepclasseswithmembernames class * { # 保持native方法不被混淆
native <methods>;
}
```
2. 不要混淆使用反射的类,否则反射可能出现问题。
3. AndroidManifest中的类不进行混淆。因此,四大组件(Activity、Service、BroadcastReceiver、ContentProvider)及其子类和Framework层下的所有类默认不会被混淆。自定义的View也默认不会被混淆。所以,像网上很多贴的排除自定义View或四大组件被混淆的规则在Android Studio中是无需添加的。
4. 当与服务端交互时,如果使用GSON、fastjson等框架解析服务端数据,所编写的JSON对象类不应被混淆,否则无法将JSON解析成对应的对象。
在Android开发中,Gson是一个常用的JSON解析库。要使用Gson库,首先需要将其编译为aar文件。可以使用以下命令进行编译:
```shell
gson compile 'com.google.code.gson:gson:2.8.1' -keepattributes Signature -keepattributes *Annotation* -keep class sun.misc.Unsafe { *; } -keep class com.photo.collage.photo.grid.bean.frame.FrameBean { *; } -keep class com.photo.collage.photo.grid.bean.frame.LineMarginBean { *; } -keep class com.photo.collage.photo.grid.bean.frame.MarginBean { *; } -keep class com.photo.collage.photo.grid.bean.frame.MyFrameBean { *; } -keep class com.photo.collage.photo.grid.bean.frame.ShapeMarginBean { *; } -keep class com.photo.collage.photo.grid.bean.frame.StickerMarginBean { *; } -keep class com.photo.collage.photo.grid.bean.frame.StorymarginBean { *; } -keep class com.photo.collage.photo.grid.bean.frame.TextMarginBean { *; }
```
在Android项目中使用第三方开源库或引用其他第三方SDK包时,如果有特别要求,也需要在混淆文件中加入对应的混淆规则。例如,对于WebView的JS调用,需要保证写的接口方法不混淆,以避免出现Android.os.BadParcelableException异常。
此外,在使用Android的Parcelable时,需要注意Parcelable的子类和Creator静态成员变量不混淆。否则,可能会导致Android系统抛出BadParcelableException异常。
请根据提供的代码片段完成内容重构,并保持段落结构如下:
1. 请保持实现了`android.os.Parcelable`接口的类不被混淆。在这些类中,需要添加一个名为`CREATOR`的静态常量,其类型为`android.os.Parcelable$Creator`。例如:
```java
-keep class * implements android.os.Parcelable {
## 保持Parcelable不被混淆
public static final android.os.Parcelable$Creator CREATOR;
}
```
2. 当使用枚举类型时,需要注意避免以下两个方法被反射调用,因为枚举类的特殊性,这两个方法会被反射调用。为了防止混淆,可以将这两个方法声明为静态常量。例如:
```java
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
```