Android,程序反编译后的打包发布

本文探讨了在Android应用程序打包过程中遇到的反射问题。作者分享了自己的经验,如何利用Java的反射机制解决懒加载问题,并在反编译后成功进行打包发布。

android对于打包中遇到的反射的问题

(大虾请飘过........快哭了

1:本人生活比较懒,今天将懒也发挥到了程序上

哎,开发android一会了,今天发现好多代码都是一样的,比如举例为:刚开始一个数据库,增加一个table1,就要为该表写最简单的增删改查的操作,增加一个table2的时候又要写这些东西,哎这种代码,看的哥蛋疼,于是决定赖一下下;呵呵

2:对java的反射机制和注释有一定的基础

该文章设计到的基本类,DBUtils,以及table1,table2,数据库对象表模型的基类DBTable;
首先DBUtils如下:
public class DBUtils {

	private static DBUtils			instance;
	static final String				FAILED	= "{\"result\":\"-1\"}";
	static final String				SUCESS	= "{\"result\":\"0\"}";
	private static QDWDBSuper		mQDWDB;
	private static SQLiteDatabase	database;

	public static void initDatabase(SQLiteDatabase db) {
		DBUtils.database = db;
	}

	/**
	 * 创建数据库
	 * 
	 * @param userID
	 * @return
	 */
	public boolean createDB(int userID) {
		return mQDWDB.createDB(userID);
	}

	/**
	 * 判断数据库是否存在
	 * 
	 * @param userID
	 * @return
	 */
	public boolean dbExists(int userID) {
		return mQDWDB.dbExists(userID);
	}

	/**
	 * 刪除数据库
	 * 
	 * @param type
	 * @param userID
	 * @return
	 */
	public boolean deleteDB(int userID) {
		boolean result = mQDWDB.deleteDB(userID);
		mQDWDB = null;
		return result;
	}

	/**
	 * 调用dbuser之前确保用户已经登陆,否则该单例返回错误
	 */
	public static DBUtils getInstance(QDWDBSuper dbSuper) {
		if (mQDWDB == null || mQDWDB != dbSuper) {
			synchronized (DBUtils.class) {
				if (mQDWDB != dbSuper) {
					mQDWDB = dbSuper;
					instance = new DBUtils();
				}
			}
		}
		return instance;
	}

	public DBUtils() {
		database = mQDWDB.getDBWriteBase();
	}

	private boolean isNull() {
		return database == null ? false : true;
	}

	/**
	 * 建表,必须带主键
	 * 
	 * @param clazz
	 * @return
	 */
	public String create(Class<? extends DBTable> clazz) {

		if (!isNull()) {
			return FAILED;
		}

		Table table = clazz.getAnnotation(Table.class);
		if (table == null) {
			return FAILED;
		}
		ContentValues values = new ContentValues();
		String key = "";
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {
			Paramter column = field.getAnnotation(Paramter.class);
			if (column == null || TextUtils.isEmpty(column.column_name())) {
				continue;
			}
			if (column.is_primary_key()) {

				if (TextUtils.isEmpty(key)) {
					key = column.column_name();
				}
				else {
					key = key + "," + column.column_name();
				}

			}
			values.put(column.column_name(), column.column_type().getValue());
		}
		String maryKey = "";
		if (!TextUtils.isEmpty(key)) {
			maryKey = "primary key (" + key + ")";
		}
		try {
			StringBuffer sql = new StringBuffer("create table if not exists ");
			sql.append(table.table_name());
			sql.append("(");
			Set<Entry<String, Object>> set = values.valueSet();
			for (Entry<String, Object> entry : set) {
				sql.append(entry.getKey());
				sql.append(' ');
				sql.append(entry.getValue());
				sql.append(',');
			}
			sql.append(maryKey);

			String teString = sql.toString() + ");";
			database.execSQL(teString);
		}
		catch (Exception e) {
			e.printStackTrace();
			return FAILED;
		}
		finally {
		}

		return SUCESS;
	}

	/**
	 * 插入表
	 * 
	 * @param clazz
	 * @param dbTableSuper
	 * @return
	 */
	public String insert(Class<? extends DBTable> clazz, DBTable dbTableSuper) {

		if (!isNull()) {
			return FAILED;
		}
		try {
			Table table = clazz.getAnnotation(Table.class);
			if (table == null) {
				return FAILED;
			}

			Field[] fields = clazz.getDeclaredFields();
			if (fields.length <= 0) {
				return FAILED;
			}
			ContentValues values = new ContentValues();
			for (Field field : fields) {

				Paramter paramter = field.getAnnotation(Paramter.class);
				if (paramter == null || TextUtils.isEmpty(paramter.column_name())) {
					continue;
				}
				if (paramter.column_type() == DBColumnType.FLOAT) {
					values.put(paramter.column_name(), (Double) field.get(dbTableSuper));
				}
				else if (paramter.column_type() == DBColumnType.INTTEGER) {
					values.put(paramter.column_name(), (Integer) field.get(dbTableSuper));
				}
				else if (paramter.column_type() == DBColumnType.LONG) {
					values.put(paramter.column_name(), (Long) field.get(dbTableSuper));
				}
				else if (paramter.column_type() == DBColumnType.TEXT) {
					values.put(paramter.column_name(), (String) field.get(dbTableSuper));
				}
			}

			return database.insert(table.table_name(), null, values) > 0 ? SUCESS : FAILED;
		}
		catch (Exception e) {
			QDWLog.log(LOGINFO.E, "zj", "exception--->: " + e.getMessage());
			return FAILED;
		}
	}

	/**
	 * 更新表数据
	 * 
	 * @param clazz
	 * @param key
	 * @param value
	 * @param oldValue
	 * @return
	 */
	public String update(Class<? extends DBTable> clazz, String putkey, String putValue, String keyWhere, String keyCondition) {
		if (!isNull()) {
			return FAILED;
		}
		Table table = clazz.getAnnotation(Table.class);
		if (table == null) {
			return FAILED;
		}
		ContentValues values = new ContentValues();
		values.put(putkey, putValue);
		String where = keyWhere + " = '" + keyCondition + "'";
		return database.update(table.table_name(), values, where, null) > 0 ? SUCESS : FAILED;
	}

	/**
	 * 删除表数据
	 * 
	 * @param clazz
	 * @param key
	 * @param value
	 * @return
	 */
	public String delete(Class<? extends DBTable> clazz, String key, String value) {
		if (!isNull()) {
			return FAILED;
		}
		Table table = clazz.getAnnotation(Table.class);
		if (table == null) {
			return FAILED;
		}
		String where = key + " = '" + value + "'";
		return database.delete(table.table_name(), TextUtils.isEmpty(key) ? null : where, null) > 0 ? SUCESS : FAILED;
	}

	/**
	 * 查询表数据
	 * 
	 * @param key
	 * @param value
	 * @param limit
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T> QDWList<T> select(String key, String value, String limit, Class<? extends DBTable> clazz) {
		if (!isNull()) {
			return null;
		}
		Table table = clazz.getAnnotation(Table.class);
		if (table == null) {
			return null;
		}
		QDWList<T> result = new QDWList<T>();
		String where = key + " ='" + value + "'";

		if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value)) {
			where = null;
		}
		Cursor cursor = database.query(table.table_name(), null, where, null, null, null, null, limit);
		try {
			while (cursor.moveToNext()) {
				JSONObject child = new JSONObject();
				Field[] fields = clazz.getDeclaredFields();

				for (Field field : fields) {
					Object jsonValue = "";

					Paramter paramter = field.getAnnotation(Paramter.class);
					if (paramter == null || TextUtils.isEmpty(paramter.column_name())) {
						continue;
					}

					if (paramter.column_type() == DBColumnType.INTTEGER) {
						jsonValue = cursor.getInt(cursor.getColumnIndex(paramter.column_name()));
					}
					else if (paramter.column_type() == DBColumnType.TEXT) {
						jsonValue = cursor.getString(cursor.getColumnIndex(paramter.column_name()));
					}
					else if (paramter.column_type() == DBColumnType.LONG) {
						jsonValue = cursor.getLong(cursor.getColumnIndex(paramter.column_name()));
					}
					else if (paramter.column_type() == DBColumnType.FLOAT) {
						jsonValue = cursor.getFloat(cursor.getColumnIndex(paramter.column_name()));
					}
					if (!TextUtils.isEmpty(paramter.column_name())) {
						child.put(paramter.column_name(), String.valueOf(jsonValue));
					}
				}
				Constructor<?> constructor = clazz.getConstructor(new Class[] { String.class });
				result.add((T) constructor.newInstance(child.toString()));
			}
			return result;
		}
		catch (Exception e) {
			QDWLog.log(LOGINFO.E, "zj", "dbutils ---------select--------exception>: " + e.getMessage());
			return null;
		}
	}

}

其中一个table1的模型:
@Table(table_name = "tb_table1")
public class table1 extends DBTable {
	private static final long	serialVersionUID	= 1L;

	public int getID() {
		return id;
	}

	public void setID(int id) {
		this.id= id;
	}
<span style="white-space:pre">	</span>public String getName() {
<span style="white-space:pre">		</span>return name;
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>public void setName(String mSUserName) {
<span style="white-space:pre">		</span>this.<span style="font-family: Arial, Helvetica, sans-serif;">name</span><span style="font-family: Arial, Helvetica, sans-serif;"> = name;</span>
<span style="white-space:pre">	</span>}
	@Paramter(column_name = "id", column_type = DBColumnType.INTTEGER, is_primary_key = true)
	public int		id;		// 用戶ID

	@Paramter(column_name = "name", column_type = DBColumnType.TEXT, is_primary_key = false)
	public String	mSPhone;	<span style="font-family: Arial, Helvetica, sans-serif;">	// 用戶手机号</span>
<span style="font-family: Arial, Helvetica, sans-serif;">}</span>

就让table2模型和table1相同吧,字段就随意大伙改了,
然后你只需要这样
DBUtils.getInstance().create(table1.class); //创建table1
<pre name="code" class="java">DBUtils.getInstance().create(table2.class); //创建table2

查询的时候只需要这样
<pre name="code" class="java">DBUtils.getInstance().select("","",1,table1.class);//相当于sql语句   select * from <span style="font-family: Arial, Helvetica, sans-serif;">tb_table1 limit 1</span>
<span style="font-family:Arial, Helvetica, sans-serif;">其他的插入,更新,删除也差不多了</span>



3:真正的问题来了

当打包发布的时候,如果混淆代码,则以上的代码全部废了,我去,让我重新写一次像以前一样,每个数据库表的模型写一遍增删改查吗?杀了我吧.......
终于在网上找到各位大虾的言论和经验后经过以下的改动,如下:
-keepclasseswithmembers class com.test.model.not.compile.table1 {     
    public <init>(java.lang.String);  
}
-keepclasseswithmembers class com.test.model.not.compile.table2{     
    public <init>(java.lang.String);  
}
-keepclasseswithmembernames class com.test.utils.db.**{*;}

然后接着打包,跑起来,打开数据库看,闯将表成功了,于是开始插入啊,删除啊,各种操作,哈哈hold住了,然后决定看一下是否真心是混淆打包的,于是将打包出来的apk包重新反编译后查看,
如下图:

哈哈,收工....还说赖,今天都写了两篇,太不像我了.....
还是一样,代码质量很差,没有任何想法,只是希望给各位在一线开发的码友一个简单的想法和处理问题的方法,希望各位大虾不要吐槽

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值