android 不混淆 接口

2016-09-11 23:15:00 weixin_30588907 阅读数 173

在编写Android程序之后,我们通常要代码进行混淆编码,这样才能保证市场上我们的应用不会被别人进行反编译,然后破解,所以此时需要在发布正式版本的时候,有一些类事不能混淆的,比如实现了 Serializable 接口的,否则反序列化时会出错,这种情况下,我们可以简单的通过在proguard.cfg(Eclipse)添加配置来解决:

-keepnames class * implements java.io.Serializable
-keepclassmembers class * implements java.io.Serializable {
static final long serialVersionUID;
private static final java.io.ObjectStreamField[] serialPersistentFields;
!static !transient <fields>;
private void writeObject(java.io.ObjectOutputStream);
private void readObject(java.io.ObjectInputStream);
java.lang.Object writeReplace();
java.lang.Object readResolve();
}
上面的配置表示所有实现了 Serializable 接口的类及其成员都不进行混淆。
 
再比如JS调用的Android的JavaScriptInterface代码的方法,比如个别控制层类需要反射、个别实体类需要JSON化保存在本地,这些都是要防止没有明显共同特征的类被混淆,这时候,我们怎么做呢,一个个添加到proguard.cfg里面吗?这样会导致proguard配置文件杂乱无章,同时需要团队所有的成员对其语法有所了解.
下面针对这个问题,分享一个小技巧,通过给这些类、属性、函数添加共同的标识,然后统一过滤,最后解决上面所说的问题

1. 新建表示统一标识的注解 NotProguard

package cn.trinea.android.common.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* NotProguard, Means not proguard something, like class, method, field<br/>
*/
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
public @interface NotProguard {
}
NotProguard 是个编译时注解,不会对运行时性能有任何影响。可修饰类、方法、构造函数、属性。
 
这里,可能会对注解(Annotation)有一些模糊,想了解更多关于注解相关的知识可以点击链接:Java Annotation 总结
 

2. 在 Proguard 配置文件中过滤被这个注解修饰的元素

# keep annotated by NotProguard
-keep @cn.trinea.android.common.annotation.NotProguard class * {*;}
-keep class * {
@cn.trinea.android.common.annotation.NotProguard <fields>;
}
-keepclassmembers class * {
@cn.trinea.android.common.annotation.NotProguard <methods>;
}
表示不混淆被 NotProguard 修饰的类、属性和方法。
 

3. 使用NotProguard让指定的域不进行混淆:

(1) 整个类不混淆
@NotProguard 
public class User {}
(2) 单个属性不混淆
@NotProguard 
public int id;
(3) 单个方法不混淆
@NotProguard
public boolean isValid() {
…
}
这样我们便解决了每个类都需要在 proguard 配置文件中配置的问题。
 

关于混淆

混淆一般在 Release 模式生效,主要有三个作用:
(1) 压缩、优化、删除代码;
(2) 一定程度上提高反编译后被读懂的难度;
(3) 通过删除代码功能实现的特殊作用。
比如在 Proguard 语法及常用 proguard.cfg 代码 中介绍的利用 Progurad 使得线上版本不打印 Log.d 和 Log.v 的技巧,防止调试的敏感信息被泄露。
一些应用的代码可能从来都没混淆过,虽说这些代码实际价值可能不大,本身可能也是开源代码凑起来的,再者该破解的还是能破解,但本着做事要专业的态度,还是混淆吧。
 

其他参考文章

转载于:https://www.cnblogs.com/renhui/p/5863199.html

2019-11-07 15:04:52 sinat_38184748 阅读数 271

前言

之前一直打包的sdk都是给内部项目使用的,没有提供给别的客户使用过,所以一直以来都是简单的功能打包,也不混淆,等最后的项目再写混淆方法。

最近要求提供sdk给客户但又要混淆业务逻辑,只好摸索一下,百度和谷歌都没有找到很好的教程。只能根据用过的第三方sdk的经验写一下,以下记录一下自己的想法。不能保证是优秀的代码。毕竟赶鸭子上架,有相关的经验的大佬,希望也能提点建议。

新建model

由于我直接打包aar就好了,所以就不配置jar包的设置了。

新建接口

新建文件 ITestUtil

public interface ITestUtil {

    /**
     * 打印
     * @param msg
     */
    void doLog(String msg);
}

新建业务

新建文件 TestUtil

public class TestUtil implements ITestUtil {

    @Override
    public void doLog(String msg) {
        Log.e("TestUtil", "打印:" + msg);
    }
}

混淆

基本混淆代码

直接放进你的混淆文件即可 proguard-rules.pro

#表示混淆时不使用大小写混合类名
-dontusemixedcaseclassnames
#表示不跳过library中的非public的类
-dontskipnonpubliclibraryclasses
#打印混淆的详细信息
-verbose

# Optimization is turned off by default. Dex does not like code run
# through the ProGuard optimize and preverify steps (and performs some
# of these optimizations on its own).
-dontoptimize
##表示不进行校验,这个校验作用 在java平台上的
-dontpreverify
# Note that if you want to enable optimization, you cannot just
# include optimization flags in your own project configuration file;
# instead you will need to point to the
# "proguard-android-optimize.txt" file instead of this one from your
# project.properties file.

-keepattributes *Annotation*
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService

# For native methods, see http://proguard.sourceforge.net/manual/examples.html#native
-keepclasseswithmembernames class * {
    native <methods>;
}

# keep setters in Views so that animations can still work.
# see http://proguard.sourceforge.net/manual/examples.html#beans
-keepclassmembers public class * extends android.view.View {
   void set*(***);
   *** get*();
}

# We want to keep methods in Activity that could be used in the XML attribute onClick
-keepclassmembers class * extends android.app.Activity {
   public void *(android.view.View);
}

# For enumeration classes, see http://proguard.sourceforge.net/manual/examples.html#enumerations
-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-keepclassmembers class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator CREATOR;
}

-keepclassmembers class **.R$* {
    public static <fields>;
}

# The support library contains references to newer platform versions.
# Don't warn about those in case this app is linking against an older
# platform version.  We know about them, and they are safe.
-dontwarn android.support.**

# Understand the @Keep support annotation.
-keep class android.support.annotation.Keep

-keep @android.support.annotation.Keep class * {*;}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <methods>;
}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <fields>;
}

-keepclasseswithmembers class * {
    @android.support.annotation.Keep <init>(...);
}
#忽略警告
-ignorewarnings
#保证是独立的jar,没有任何项目引用,如果不写就会认为我们所有的代码是无用的,从而把所有的代码压缩掉,导出一个空的jar
-dontshrink
#保护泛型
-keepattributes Signature

自定义相关混淆

添加自己的相关混淆配置

# 不混淆某个类(使用者可以看到全部信息)
-keep class com.rdwl.testlib.ITestUtil {*;}
# 不混淆某个类(使用者可以看到类名)
-keep class com.rdwl.testlib.TestUtil

# 不混淆某个类中以 public 开始的方法(使用者可以看到该方法)
#-keepclassmembers class com.rdwl.testlib.TestUtil {
#    public *;
#}

开启混淆

打开 model 的 build.gradle 文件

buildTypes {
        release {
            minifyEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

混淆正式打包

点击右侧边栏的 Gradle,在窗口中找到你的 model,选择 Tasks -> build -> build,如果你打开 Gradle 窗口显示 Nothing to show,你可以看下我的这篇文章:Android studio右侧Gradle窗口显示 nothing to show

等待打包完成。你就能在model的build文件夹找到打包好的aar
在这里插入图片描述

完事

2018-01-02 15:31:28 qq_33750826 阅读数 3141

有一天我想保持一个SDK的某个类的内部接口和所属的该类不被混淆,于是我在混淆文件添加如下:

-keep class com.kw.yz24g.remote22.SensorCtrlTasker{ *; }
-keep public interface
com.kw.yz24g.remote22.SensorCtrlTasker$SensorCtrlListener{ *; }

发现怎么都还是会被混淆,后面查询资料发现

-keep public interface
com.kw.yz24g.remote22.SensorCtrlTasker$SensorCtrlListener{ *; }

只需要使用这一条就可以将该类和该类中的内部接口保持原型

2016-10-27 16:39:44 jianjiaqqq001 阅读数 4817

在Android工程中混淆时,并不是所有的类都去混淆, 一些指定的类,我们要过滤掉不让其混淆。

在AndroidStudio中

混淆时 在 build.gradle 文件里面进行配置  

buildTypes {
    debug {
        // 显示Log
        buildConfigField "boolean", "LOG_DEBUG", "true"
        versionNameSuffix "-debug"
        //混淆
        minifyEnabled false
        //签名
        signingConfig signingConfigs.debug
    }

    release {
        //代码混淆开关,一定要注意现在已经使用minifyEnabled代替runProguard了
        minifyEnabled true
        //Zipalign优化
        zipAlignEnabled true
        // 移除无用的resource文件
        shrinkResources true
        // proguard-rules.pro 是当前使用的混淆文件(Eclipse中的proguard.cfg)
        //前一部分代表系统默认的android程序的混淆文件,该文件已经包含了基本的混淆声明,后一个文件是自己的定义混淆文件
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}
 //代码混淆开关,一定要注意现在已经使用minifyEnabled代替runProguard了
        minifyEnabled true 

并不是所有的类都去混淆, 一些指定的类,我们要过滤掉不让其混淆。

首先 通常第三方开源库 是不必混淆的 也没意义。

譬如网络请求框架 okhttp.

我们在  app/proguard-rules.pro文件中配置

# 不混淆okhttp3

-keep class okhttp3.** { *; }
-keep interface okhttp3.** {*;}
-dontwarn okio.**


------------------------------------------------------------------------------------------------------------------------------------------------------------------

现在我们想指定某些类不让其混淆。  有两种方法,

一种 是让不能混淆的类 继承于同一个空类 。

一种 是让不能混淆的类 实现一个空接口。

 由于类是单继承,所以当不能混淆的类已经有了父类就不适用了。 

所以采用第二种 实现自己定义的空接口, 那么实现此接口的类都可以,而且不受这种单继承限制,任何类可以实现,任何接口可以继承。 当然也是继承类和实现接口的区别中的一条重要特性


/**
 * Created by 张丹江 on 2016/10/24.
 * 实现此接口的类,都不会被混淆
 */
public interface DontObfuscateInterface {
}

在proguard-rules.pro 文件里面这样配置 

-keep public interface com.danjiang.fastjsondemo.DontObfuscateInterface{public *;}
-keep class * implements com.danjiang.fastjsondemo.DontObfuscateInterface {
<methods>;
<fields>;
}

那么实现此接口的类都不会混淆了。

但是 还有一种情况 在fastjson解析时,有些类正常 有些类依然不正常。

 FATAL EXCEPTION: main
                                                   Process: com.danjiang.fastjsondemo, PID: 21688
                                                   com.alibaba.fastjson.JSONException: default constructor not found. class com.danjiang.fastjsondemo.DataBean$a
                                                       at com.alibaba.fastjson.util.JavaBeanInfo.build(SourceFile:213)
                                                       at com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer.<init>(SourceFile:40)
                                                       at com.alibaba.fastjson.parser.ParserConfig.createJavaBeanDeserializer(SourceFile:582)
                                                       at com.alibaba.fastjson.parser.ParserConfig.getDeserializer(SourceFile:457)
                                                       at com.alibaba.fastjson.parser.deserializer.DefaultFieldDeserializer.getFieldValueDeserilizer(SourceFile:35)

说是默认构造没有找到,但是去给加了 空构造参数依然不能通过。 网上各种查询得出,是内部类被混淆的原因。

网上给出答案 ,

-keepattributesExceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod

 是InnerClasses 这样 就可以 然后测试 此语句无效。 其中异常给出

com.danjiang.fastjsondemo.DataBean$a 为$符号后的a 就是这个类被混淆了 然后查询内部类混淆规则 

$ 代表内部类

* 代表通配符


有 这样的答案 指定报名和类名。 写死是可以的通过的
-keepnames class 包名.类名$* {
    public <fields>;
    public <methods>;
}

然而这样违背了我们自定义的混淆接口的初衷, 这样就要对每一个具体的类的内部类在配置文件配置。 有100个含有内部类的类我们就得配置100次,有1万个就1万次,违背了我们的初衷。


然而 发现


令一种方法,就是让每一个内部类都去实现这样的 接口, 看看以往的工程,和现在的工程中都是这样做的。 临时各种实验都不成功暂且将每个内部类都实现这样的接口。 即使复杂的JavaBean 有多个内部类也要仔细的一个个去添加。。

也是没有办法,相比上一种也是简便许多 当然 当内部类数量 特别多时 都要去实现以下。

总感觉有可以解决的办法  开始分析进行各种尝试。 只让外部类实现,内部类不去实现 像这样


# 保持哪些类的子类 不被混淆
-keep public class * extends android.app.Activity
#保持 Parcelable 不被混淆 以及里面的子接口  看到这里类的内部类却无法如此 除非指明报名 
-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}
而我们想要的是 
-keep (class * implements com.danjiang.fastjsondemo.DontObfuscateInterface)$*
或者这样
-keep class * implements com.danjiang.fastjsondemo.DontObfuscateInterface {
<methods>;
<fields>;
}$*

或者这样

-keep class$* * implements com.danjiang.fastjsondemo.DontObfuscateInterface
或者

-keep class$* * implements com.danjiang.fastjsondemo.DontObfuscateInterface$*

理想的认为这样代表 实现此接口的类的内部类,然并卵 语法不过。各种数小时的实验 未果

-keep (class * implements com.danjiang.fastjsondemo.DontObfuscateInterface)$*
最后想到
-keep class com.danjiang.fastjsondemo.*$* {
<methods>;
<fields>;
}
我的工程包名下面的所有类的内部类都不去混淆, 那么只需让不能混淆的 外部类实现
DontObfuscateInterface接口就可以了 
这样可以保证了不用处处配置 也不用内部类处处实现。 

当然也有个缺点就是 所有的内部类不在被混淆。 
也翻阅国外的回答,目前没有发现更强大的语法 直接支持 
-keep (class * implements com.danjiang.fastjsondemo.DontObfuscateInterface)$* 这样的效果 。 或者此类生成个变脸类 取其内部类。 
当然最后一种是目前最省事的一种写法,也有缺点内部类不在混淆。
如有高手发现其他更好的可以留言,欢迎指正不足。 详细混淆规则没有一一列举 仅仅是对 实现某个接口的类的内部类的混淆探索
邮箱 。zhangdanjiang_java@163.com

2017-02-24 16:03:34 qq_18938459 阅读数 1203
在混淆代码的时候,不混淆类内部接口:

-keep interface com.test.TestSdk$Callback {
    public ;
}

调用接口方法:

导入jar包
import com.test.TestSdk;
import com.test.TestSdk$Callback;

public class MainActivity extends Activity implements  TestSdk$Callback {

}

这样既可实现不混淆接口供第三方调用。