有界面(Activity或其他View)的SDK项目混淆发布

1.首先,作为SDK的项目查找界面时不能按常规的套路来,之前的Activity设置界面是setContentView(R.layout.activity_main)。现在提供一个资源工具类(据说是一个天才少年写的,我直接复制给大家了),所有资源都通过该类查找。


/*
 * Copyright (C) 2015 pengjianbo(pengjianbosoft@gmail.com), Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.vzone.tmdsdk.tool;

import java.lang.reflect.Field;

import android.content.Context;

/**
 * Desction: Author:pengjianbo Date:15/10/22 下午9:01
 */
public class ResourceUtils {
    /**
     * 获取 layout 布局文件
     * 
     * @param context
     *            Context
     * @param resName
     *            layout xml 的文件名
     * @return layout
     */
    public static int getLayoutId(Context context, String resName) {
        return context.getResources().getIdentifier(resName, "layout",
                context.getPackageName());
    }

    /**
     * 获取 string 值
     * 
     * @param context
     *            Context
     * @param resName
     *            string name的名称
     * @return string
     */
    public static int getStringId(Context context, String resName) {
        return context.getResources().getIdentifier(resName, "string",
                context.getPackageName());
    }

    /**
     * 获取 drawable 布局文件 或者 图片的
     * 
     * @param context
     *            Context
     * @param resName
     *            drawable 的名称
     * @return drawable
     */
    public static int getDrawableId(Context context, String resName) {
        return context.getResources().getIdentifier(resName, "drawable",
                context.getPackageName());
    }

    /**
     * 获取 style
     * 
     * @param context
     *            Context
     * @param resName
     *            style的名称
     * @return style
     */
    public static int getStyleId(Context context, String resName) {
        return context.getResources().getIdentifier(resName, "style",
                context.getPackageName());
    }

    /**
     * 获取 styleable
     * 
     * @param context
     *            Context
     * @param resName
     *            styleable 的名称
     * @return styleable
     */
    /*public static Object getStyleableId(Context context, String resName) {
        return context.getResources().getIdentifier(resName, "styleable",
                context.getPackageName());
    }*/

    /**
     * 获取 anim
     * 
     * @param context
     *            Context
     * @param resName
     *            anim xml 文件名称
     * @return anim
     */
    public static int getAnimId(Context context, String resName) {
        return context.getResources().getIdentifier(resName, "anim",
                context.getPackageName());
    }

    /**
     * 获取 id
     * 
     * @param context
     *            Context
     * @param resName
     *            id 的名称
     * @return
     */
    public static int getId(Context context, String resName) {
        return context.getResources().getIdentifier(resName, "id",
                context.getPackageName());
    }

    /**
     * color
     * 
     * @param context
     *            Context
     * @param resName
     *            color 名称
     * @return
     */
    public static int getColorId(Context context, String resName) {
        return context.getResources().getIdentifier(resName, "color",
                context.getPackageName());
    }

    private static Object getResourceId(Context context, String name, String type) {
        String className = context.getPackageName() + ".R";
        try {
            Class<?> cls = Class.forName(className);
            for (Class<?> childClass : cls.getClasses()) {
                String simple = childClass.getSimpleName();
                if (simple.equals(type)) {
                    for (Field field : childClass.getFields()) {
                        String fieldName = field.getName();
                        if (fieldName.equals(name)) {
                            System.out.println(fieldName);
                            return field.get(null);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取styleable的ID号数组
     */
    public static int[] getStyleableArray(Context context,String name) {
        return (int[])getResourceId(context, name,"styleable");
    }

    /**
     *context.getResources().getIdentifier无法获取到styleable的数据
     */
    public static int getStyleable(Context context, String name) {
        return ((Integer)getResourceId(context, name,"styleable")).intValue();
    }
}

自定义view属性的获取:

TypedArray a = context.obtainStyledAttributes(attrs, ResourceUtils.getStyleableArray(context, "CircleImageView"), defStyle, 0);

        mBorderWidth = a.getDimensionPixelSize(ResourceUtils.getStyleable(context, "CircleImageView_civ_border_width"), DEFAULT_BORDER_WIDTH);
        mBorderColor = a.getColor(ResourceUtils.getStyleable(context, "CircleImageView_civ_border_color"), DEFAULT_BORDER_COLOR);
        mBorderOverlay = a.getBoolean(ResourceUtils.getStyleable(context, "CircleImageView_civ_border_overlay"), DEFAULT_BORDER_OVERLAY);
        mFillColor = a.getColor(ResourceUtils.getStyleable(context, "CircleImageView_civ_fill_color"), DEFAULT_FILL_COLOR);
        a.recycle();

2.确保所有资源的名字唯一,比如预设的activity_main.xml最好改一个名字,因为引用SDK的人(后面称为Client)很可能也有一个xml文件叫做activity_main.xml。
3.所有涉及到声明的东西,必须在Client的AndroidManifest.xml中声明,比如权限、Activity、Service、BroadcastReceiver等(仅针对eclipse,AndroidStudio另算)。
4.lib打包成jar时,除了src以外其他都不能选择。
5.将jar包混淆,参考http://blog.csdn.net/ithouse/article/details/51605955
6.删除你之前SDK项目中src目录下的所有源码,拷贝混淆之后的jar包到SDK项目的libs目录下。
7.将该SDK项目发布出去,让Client引用该项目即可。

Android混淆是一种通过对代码进行重命名和优化来增加应用程序安全性和性能的技术。在Android开发,可以使用自带的混淆工具来进行代码混淆。默认情况下,Android SDK提供了一些默认的混淆文件,如proguard-android.txt或proguard-android-optimize.txt。这些文件包含了一些常用的混淆命令,可以对代码进行混淆处理。如果需要对自定义的混淆进行配置,可以在proguard-rules.pro文件进行设置。\[1\] 在进行混淆时,需要注意不要混淆Activity参数是View的方法。因为在Android开发,有一种常见的用法是在XML配置android:onClick属性,当用户点击按钮时,会调用Activity的对应方法,例如buttonClick(View view)。如果这个方法被混淆,就无法找到对应的方法了。为了避免这种情况,可以使用如下混淆命令来保留Activity参数是View的方法:-keepclassmembers class * extends android.app.Activity { public void *(android.view.View); }\[2\] 此外,还可以使用一些通用的混淆命令来保留Android的一些常用类,例如Activity、Application、Service、BroadcastReceiver和ContentProvider:-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\[3\] 通过使用混淆技术,可以有效地保护Android应用程序的代码安全性,并提高应用程序的性能。 #### 引用[.reference_title] - *1* [Android:代码混淆概念整理](https://blog.csdn.net/qjyws/article/details/126488356)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Android--混淆配置(比较详细的混淆规则)](https://blog.csdn.net/weixin_42602900/article/details/127671586)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ithouse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值