要学会二次打包必须先对android结构非常了解,还有生命周期,也就是说你最少会做些android开发。然后把自己的代码添加进去,有点像C++的代码注入。在二次打包的过程中需要注意的是,如果用XML布局的话有点麻烦,目前我深入研究。因为这个有有布局的ID,然后ID还要在public.xml和id.xml里面去添加(这两个文件是编译的时候自动生成的)ID的值也是不能相同的,否则会影响到其它的界面控件的控制事件,导致打包失败!并且还要把对应的xml文件也要放到目标下面的res/layout... 总之,相对来说麻烦!
下面就说一个最简单的方法,用代码布局,然后把这个字节码放到目标程序对应目录下,再修改一下AndroidManifest.xml配置文件即可实现二次打包。
看例子,我们首先创建一个工程,和之前创建工程没什么区别,只是把setContentView稍微改一下,不要用自动生成的activity_main.xml,要用代码布局!以下是一个登录的例子。package com.app.login;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener {
LinearLayout.LayoutParams textParams;// textview
LinearLayout layout;
EditText editUser;
EditText editPass;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
textParams = new LinearLayout.LayoutParams(-2, -2);// textview
layout = new LinearLayout(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(-1, -1);
layout.setOrientation(LinearLayout.VERTICAL);
layout.setGravity(Gravity.CENTER);
layout.setLayoutParams(params);
setContentView(layout);
initViews();
}
private void initViews() {
initUser();
initPass();
initSubmit();
}
private void initUser() {
// 用户名布局
LinearLayout username_layout = new LinearLayout(this);
username_layout.setGravity(Gravity.CENTER_HORIZONTAL);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(-1, -2);
username_layout.setLayoutParams(params);
// 用户名
TextView textUser = new TextView(this);
textUser.setText("用户名:");
username_layout.addView(textUser, textParams);
layout.addView(username_layout);
// 输入框
editUser = new EditText(this);
editUser.setEms(6);
editUser.setSingleLine(true);
editUser.setLayoutParams(params);
username_layout.addView(editUser, textParams);
}
private void initPass() { // 密码布局
LinearLayout userpass_layout = new LinearLayout(this);
userpass_layout.setGravity(Gravity.CENTER_HORIZONTAL);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(-1, -2);
userpass_layout.setLayoutParams(params);
// 用户名
TextView textPass = new TextView(this);
textPass.setText("密 码:");
userpass_layout.addView(textPass, textParams);
layout.addView(userpass_layout);
// 输入框
editPass = new EditText(this);
editPass.setEms(6);
editPass.setSingleLine(true);
editPass.setLayoutParams(params);
editPass.setInputType(android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD);
userpass_layout.addView(editPass, textParams);
}
private void initSubmit() {
Button ok = new Button(this);
ok.setText("提交");
ok.setOnClickListener(this);
layout.addView(ok, textParams);
}
public void onClick(View view) {
try {
Intent mIntent = new Intent();
mIntent.setClassName(this, "com.lee.xqq.SplashActivity");
startActivity(mIntent);
} catch (Exception e) {
// TODO Auto-generated catch block
Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
}
}
}运行界面:
第一步:
OK,接下来把APK文件反编译,关于这个反编译网上有教程,推荐使用“Android逆向助手”,这个集成了多个命令和工具一身,不用翻来翻去,相当方便!
反编译之后的工程目录下有Smali目录,那这是什么玩意儿呢? smali分别是指安卓系统里的Java虚拟机(Dalvik)所使用的一种.dex格式文件的汇编器。
打开对应的包(文件夹),如我工程包:com.app.login,那么这个对应目录是com/app/login/,在这个目录下面是不是看到了我们创建的MainAcitivity.smali文件呢?还有一些其它的,什么R.smali、R$attr.smali……带有$符号的是R的内部类,对我们来说是没有用的,因为本教程讲的是纯代码实现的界面。只要这一个MainAcitivity.smali即可。把其它文件全部删除,只留下这一个文件。那么第一步就完成了!
第二步:
就是植入目标APK文件,随便找一个APP,下载好了用“Android逆向助手”反编译,然后把上面得到的com/app/login/MainAcitivity.smali复制到反编译目录下的smali目录,注意,不能光复制一个文件,目录结构是必须的。代码弄好了再把AndroidManifest.xml改改,如果你只是添加activity的话,那直接和普通开发没区别,直接添加即可。如果要改入口界面的话要把反编译的AndroidManifest.xml里面的main去掉,添加自己的Activity为Main,这样程序启动会先进入到你写的界面。以下是我自己修改的。切记,只须要修改和添加,不要改其它的,不然会出错的,特别是,切记切记!
弄完了重新打包,然后签名,不签名是不能安装的!
教程写的比较快,十几分钟搞完了,如有不懂可以留言!