Proguard - 防止某些类的混淆 - 发布apk - 思考

时间:2017-12-30 06:57:56

标签: android reflection proguard comparator

我有一个写的类GenericComparator,根据方法名称在我的应用程序中根据方法名称进行排序 - 例如getPriority

import android.util.Log;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.Date;


public final class GenericComparator implements Comparator, Serializable {
    private static final long serialVersionUID = -2293914106471884607L;
    private static final int LESSER = -1;
    private static final int EQUAL = 0;
    private static final int GREATER = 1;
    private static final String METHOD_GET_PREFIX = "get";
    private static final String DATATYPE_STRING = "java.lang.String";
    private static final String DATATYPE_DATE = "java.util.Date";
    private static final String DATATYPE_INTEGER = "java.lang.Integer";
    private static final String DATATYPE_LONG = "java.lang.Long";
    private static final String DATATYPE_FLOAT = "java.lang.Float";
    private static final String DATATYPE_DOUBLE = "java.lang.Double";
    public static final String PRIORITY_COMPARATOR = "priority";
    public static final String DISPLAY_ORDER_COMPARATOR = "displayOrder";


    private enum CompareMode {EQUAL, LESS_THAN, GREATER_THAN, DEFAULT}

    // generic comparator attributes
    private String targetMethod;
    private boolean sortAscending;


    public GenericComparator(boolean sortAscending) {
        super();
        this.targetMethod = null;
        this.sortAscending = sortAscending;
    }


    public GenericComparator(String sortField) {
        super();
        this.targetMethod = prepareTargetMethod(sortField);
        this.sortAscending = true;
    }


    public GenericComparator(String sortField, boolean sortAscending) {
        super();
        this.targetMethod = prepareTargetMethod(sortField);
        this.sortAscending = sortAscending;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int compare(Object o1, Object o2) {
        int response = LESSER;
        try {
            Object v1 = (null == this.targetMethod) ? o1 : getValue(o1);
            Object v2 = (null == this.targetMethod) ? o2 : getValue(o2);
            CompareMode cm = findCompareMode(v1, v2);

            if (!cm.equals(CompareMode.DEFAULT)) {
                return compareAlternate(cm);
            }

            final String returnType = (null == this.targetMethod)
                    ? o1.getClass().getName() : getMethod(o1).getReturnType().getName();
            response = compareActual(v1, v2, returnType);
            Logger.error("NoSuch", "" + o1.getClass().getName());
        } catch (NoSuchMethodException nsme) {
            Logger.error("NoSuchMethodException occurred while comparing", nsme.getMessage());
        } catch (IllegalAccessException iae) {
            Logger.error("IllegalAccessException occurred while comparing", iae.getMessage());
        } catch (InvocationTargetException ite) {
            Logger.error("InvocationTargetException occurred while comparing", ite.getMessage());
        }
        return response;
    }


    private int compareAlternate(CompareMode cm) {
        int compareState = LESSER;
        switch (cm) {
            case LESS_THAN:
                compareState = LESSER * determinePosition();
                break;
            case GREATER_THAN:
                compareState = GREATER * determinePosition();
                break;
            case EQUAL:
                compareState = EQUAL * determinePosition();
                break;
        }
        return compareState;
    }


    private int compareActual(Object v1, Object v2, String returnType) {
        int acutal = LESSER;
        if (returnType.equals(DATATYPE_INTEGER)) {
            acutal = (((Integer) v1).compareTo((Integer) v2) * determinePosition());
        } else if (returnType.equals(DATATYPE_LONG)) {
            acutal = (((Long) v1).compareTo((Long) v2) * determinePosition());
        } else if (returnType.equals(DATATYPE_STRING)) {
            acutal = (((String) v1).compareTo((String) v2) * determinePosition());
        } else if (returnType.equals(DATATYPE_DATE)) {
            acutal = (((Date) v1).compareTo((Date) v2) * determinePosition());
        } else if (returnType.equals(DATATYPE_FLOAT)) {
            acutal = (((Float) v1).compareTo((Float) v2) * determinePosition());
        } else if (returnType.equals(DATATYPE_DOUBLE)) {
            acutal = (((Double) v1).compareTo((Double) v2) * determinePosition());
        }
        return acutal;
    }

    /**
     * preparing target name of getter method for given sort field
     *
     * @param name a {@link String}
     * @return methodName a {@link String}
     */
    private final static String prepareTargetMethod(String name) {
        StringBuffer fieldName = new StringBuffer(METHOD_GET_PREFIX);
        fieldName.append(name.substring(0, 1).toUpperCase());
        fieldName.append(name.substring(1));
        return fieldName.toString();
    }

    /**
     * fetching method from <code>Class</code> object through reflect
     *
     * @param obj - a {@link Object} - input object
     * @return method - a {@link Method}
     * @throws NoSuchMethodException
     */
    private final Method getMethod(Object obj) throws NoSuchMethodException {
        return obj.getClass().getMethod(targetMethod, null);
    }

    /**
     * dynamically invoking given method with given object through reflect
     *
     * @param method - a {@link Method}
     * @param obj    - a {@link Object}
     * @return object - a {@link Object} - return of given method
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    private final static Object invoke(Method method, Object obj) throws InvocationTargetException, IllegalAccessException {
        return method.invoke(obj, null);
    }

    /**
     * fetching a value from given object
     *
     * @param obj - a {@link Object}
     * @return object - a {@link Object} - return of given method
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     * @throws NoSuchMethodException
     */
    private Object getValue(Object obj) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        return invoke(getMethod(obj), obj);
    }


    private CompareMode findCompareMode(Object o1, Object o2) {
        CompareMode cm = CompareMode.LESS_THAN;

        if (null != o1 & null != o2) {
            cm = CompareMode.DEFAULT;
        } else if (null == o1 & null != o2) {
            cm = CompareMode.LESS_THAN;
        } else if (null != o1 & null == o2) {
            cm = CompareMode.GREATER_THAN;
        } else if (null == o1 & null == o2) {
            cm = CompareMode.EQUAL;
        }

        return cm;
    }

    /**
     * Determining positing for sorting
     *
     * @return -1 to change the sort order if appropriate.
     */
    private int determinePosition() {
        return sortAscending ? GREATER : LESSER;
    }
}

现在,要进行排序,我使用以下类:

Collections.sort(widgets, new GenericComparator("priority");

其中priority是我班级的排序顺序字段:

public class Widget实现Serializable {

private String apiId;

public String getImageLink() {
    return imageLink;
}

public void setImageLink(String imageLink) {
    this.imageLink = imageLink;
}

private String imageLink;

private String title;

private Integer priority;

private String description;

private String key;


public String getCta() {
    return cta;
}

public void setCta(String cta) {
    this.cta = cta;
}

private String cta;

public String getApiId() {
    return apiId;
}

public void setApiId(String apiId) {
    this.apiId = apiId;
}

public String getTitle() {
    return title;
}

public void setTitle(String title) {
    this.title = title;
}

public Integer getPriority() {
    return priority;
}

public void setPriority(Integer priority) {
    this.priority = priority;
}

public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}

public String getKey() {
    return key;
}

public void setKey(String key) {
    this.key = key;
}

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

private int id;

public MetaData metaData = new MetaData();

public MetaData getMetaData() {
    return metaData;
}

public void setMetaData(String metaData) {
    Gson gson = new Gson();
    this.metaData = gson.fromJson(metaData, MetaData.class);
}

public boolean isOnline() {
    return isOnline;
}

public void setOnline(boolean online) {
    isOnline = online;
}

private boolean isOnline;

}

但是当我运行我的apk的发布版本时,它给了我NoSuchMethodFoundException getPriority。它在调试版本中运行正常。

任何人都可以建议。这也是我的proguard配置:

-keep public class com.mypackage.GenericComparator { *; }
-keepclassmembers class com.mypackage.GenericComparator { *; }
-keep public class com.mypackage.datamodels.Widget{ *;}
-keepclassmembers class com.mypackage.datamodels.Widget{ *; }
-keep public class * extends com.mypackage.GenericComparator

-keepclassmembers class * extends com.mypackage.GenericComparator{
 public <init>(java.lang.String);
}

1 个答案:

答案 0 :(得分:0)

你能试试吗,包名可以是GenericComparator和Widget所在的包。您可以根据需要优化以下内容

-keepclassmembers class lib4.com.stackoverflow.** {
    *** set*(***);
    *** get*();
}