您的位置:首页 > 其它

安卓手机无法root的情况下使用busybox

2017-06-02 18:17 543 查看

安卓手机无法root的情况下,如何使用busybox

一、什么是BusyBox?

BusyBox 是标准 Linux 工具的一个单个可执行实现。BusyBox 包含了一些简单的工具,例如 cat 和echo,还包含了一些更大、更复杂的工具,例如 grep、find、mount 以及 telnet。有些人将 BusyBox 称为 Linux 工具里的瑞士军刀。简单的说BusyBox就好像是个大工具箱,它集成压缩了 Linux 的许多工具和命令。

二、为什么要使用Busybox?

手残党想要掌上玩转Linux命令行。

迫于需要。有时候通过Linux命令来操纵数据会比编译型语言简单很多。

Android本身自带ToolBox,和BusyBox类似,不过命令少得可怜,且很多命令也精简只有基础功能了。网络上已经有各种安卓一键安装busybox的集成工具了,但都有前提,需要root权限才能安装。

我的手机也是无法root的,正巧拿来当实验了。

三、怎么做?

Busybox编译完后其实就只是一个二进制文件。这个文件可以选择下载:https://busybox.net/downloads/binaries/,

也可以选择下载源码编译:https://busybox.net/downloads/

这里我选择下载源码编译吧。

2.编译busybox(我这里就选择1.20版本):

# 获取交叉编译工具链
# 这里引用别人的博客:http://download.csdn.net/download/mybelief321/5563837 可以下载
# 如何配置?引用别人的博客:http://blog.csdn.net/u010661782/article/details/49020613




# 获取busybox源码
wget https://busybox.net/downloads/busybox-1.20.0.tar.bz2 # 解压
tar xf busybox-1.20.0.tar.bz2 -C /usr/local
# 创建软链接(可以不创,直接进。我习惯这么做。)
ln -s /usr/local/busybox-1.20.0 /usr/local/busybox
# 进入文件夹
cd /usr/local/busybox




# 配置.config文件
makemenuconfig
# 以下为Menu中的选项修改
## 不使用动态链接库,才能保证每个命令都能使用
#Busybox Settings --> Build Options --> Build Busybox as a static binary (no shared libs)  -  Enable this option by pressing \"Y\"
## 配置交叉编译工具,这里使用的是刚才配置的友善之臂交叉编译工具链。
#Busybox Settings --> Build Options --> Cross compiler prefix  -  Set this option equal to \"arm-none-linux-gnueabi-\"
## 这个菜单可能会没有。没有就不配置吧。
#Busybox Settings --> Installation Options --> Don\'t use /usr  -  Enable this option by pressing \"Y\"










make




#将编译好的busybox(当前目录下)可执行文件拷贝出来
sz busybox






3.手机权限问题需要考虑。

直接拷贝到sdcard里不会有执行权限,而且访问不到;

命令行被调用时处于根目录,非root没有写权限,只有少部分读权限。权限太低,不可能创建在root里;

Android 操作系统会为每个应用程序设置一个用户, 这个用户对其安装目录(/data/data/包名/)下的文件有完整的权限;

assets 文件夹是存放不进行编译加工的原生文件,即该文件夹里面的文件不会像 xml, java 文件被预编译;目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制。

创建测试项目(注释很清楚,我就不废话了)

新建项目

添加assets文件夹,并将busybox可执行文件复制进去



修改xml,定义命令输入框,命令执行按钮,命令清空按钮,文本地址选择按钮。

<!-- 命令输入框-->
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:hint="Command"
android:ems="10"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:id="@+id/editCmd"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />

<!-- 返回结果展示的列表-->
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/listRes"
android:layout_below="@+id/btn_run"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<!-- 执行命令的按钮-->
<Button
android:text="Run"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_run"
android:layout_below="@+id/editCmd"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
<!-- 添加文件的按钮-->
<Button
android:text="file"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/editCmd"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:id="@+id/btn_files" />
<!-- 清空命令的按钮-->
<Button
android:text="clear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/btn_clear"
android:layout_below="@+id/editCmd"
android:layout_centerHorizontal="true" />


定义使用AssetsManager对象获取Assets文件夹下的文件并复制到 /data/data/包名/files/下(APP安装目录下/files/)的函数:

/**
* 将文件从assets目录中拷贝到app安装目录的files目录下
* @param context  应用程序的context
* @param source 源文件名(Assets下的文件名)
* @param destination 目标保存文件名(files下的文件名)
* */
private void copyFromAssets(Context context, String source,
String destination) throws IOException {
/**
* 获取assets目录下文件的输入流
*
* 1、获取AssetsManager : 调用 Context 上下文对象的 context.getAssets() 即可获取 AssetsManager对象;
* 2、获取输入流 : 调用 AssetsManager 的 open(String fileName) 即可获取对应文件名的输入流;
*/
InputStream is = context.getAssets().open(source);
// 获取文件大小
int size = is.available();
// 创建文件的缓冲区
byte[] buffer = new byte[size];
// 将文件读取到缓冲区中
is.read(buffer);
// 关闭输入流
is.close();
/*
*  打开app安装目录文件的输出流
*  Context.MODE_PRIVATE  设置该文件只能被本应用使用,为私有数据
*/
FileOutputStream output = context.openFileOutput(destination,
Context.MODE_PRIVATE);
// 将文件从缓冲区中写出到内存中
output.write(buffer);
//关闭输出流
output.close();
}


使用JAVA代码通过Process对象执行shell命令:

/**
*  执行 shell 脚本命令
*  @param cmd  被执行的命令行
*  @return 返回结果列表
*  */
private List<String> exec(String cmd) {
// 获取执行工具
Process process = null;
// 存放脚本执行结果
List<String> list = new ArrayList<String>();
try {
// 获取运行时环境
Runtime runtime = Runtime.getRuntime();
//执行脚本
process = runtime.exec(cmd);
//获取脚本结果的输入流
InputStream is = process.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
// 逐行读取脚本执行结果
while ((line = br.readLine()) != null) {
list.add(line);
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
return list;
}


OnCreate注册点击事件

//文件URI返回代码
private int FILE_PATH_RETURN_CODE = 1;
//保存app安装路径
private String app_path;
//数组适配器(绑定执行结果输出的数据)
private ArrayAdapter<String> arrayAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//获取app安装路径
app_path = getApplicationContext().getFilesDir().getAbsolutePath();
//获取组件
//命令输入框
final EditText textCmd = (EditText)findViewById(R.id.editCmd);
//命令执行按钮
Button btn_run = (Button)findViewById(R.id.btn_run);
//命令执行按钮
Button btn_clear = (Button)findViewById(R.id.btn_clear);
//命令执行按钮
Button btn_file = (Button)findViewById(R.id.btn_files);
//命令结果展示框
final ListView listRes = (ListView) findViewById(R.id.listRes);
//命令执行按钮点击事件
btn_run.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//查看busybox是否存在
try {
// 查看文件是否存在, 如果不存在就进入catch
getApplicationContext().openFileInput("busybox");
} catch (FileNotFoundException notfoundE) {
try {
/**
*  拷贝文件到app安装目录的files目录下
*  从assets文件夹中  拷贝到  /data/user/0/PACKAGE_NAME/files/
* */
copyFromAssets(getApplicationContext(), "busybox", "busybox");
/*
*修改文件权限脚本
* chmod  UGO(000-777)  FILENAME
*      U:所有者
*      G:所属组
*      O:其他
*      0-7:000-111,rwx读写执行
*/
String script = "chmod 700 " + app_path + "/busybox" ;
// 执行脚本
exec(script);
} catch (Exception e) {
e.printStackTrace();
}
}
//构造执行命令
String cmdPath = "." + app_path + "/busybox ";
//     System.out.println(cmdPath);
String cmd = cmdPath +textCmd.getText().toString();
//执行并获取结果
List<String> results = exec(cmd);
String[] res = new String[results.size()];
results.toArray(res);
//结果绑定在数组适配器上显示
arrayAdapter = new ArrayAdapter<String>(MainActivity.this,
android.R.layout.simple_list_item_1,res);
listRes.setAdapter(arrayAdapter);

}
});

// 清空命令按钮点击事件
btn_clear.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
textCmd.setText("");
}
});

//文件地址选择按钮点击事件
btn_file.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//通过intent调用系统文件浏览器选择并返回文件数据
Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("*/*");//设置文件类型
//为添加Action执行环境添加一个可打开的分类
intent.addCategory(Intent.CATEGORY_OPENABLE);
//调用Activity,并获取返回的数据
startActivityForResult(intent,FILE_PATH_RETURN_CODE);
}
});
}


此时需要接收文件浏览器返回的数据,要重载onActivityResult函数:

/**
*获取被调用Activity所返回的结果
* @param requestCode requestCode用于与startActivityForResult中的requestCode中值进行比较判断,是以便确认返回的数据是从哪个Activity返回的。
* @param resultCode resultCode是由子Activity通过其setResult()方法返回。适用于多个activity都返回数据时,来标识到底是哪一个activity返回的值。
* @param data 一个Intent对象,带有返回的数据。可以通过data.getXxxExtra( );方法来获取指定数据类型的数据
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode== Activity.RESULT_OK){
//如果是这个Activity定义的intent返回代码
if(requestCode==FILE_PATH_RETURN_CODE){
String uri = data.getDataString();
//必须用decode,解析中文路径
//去掉file://  7个字符
uri = Uri.decode(uri);
uri = uri.substring(7);
//  System.out.println(uri);
final EditText textCmd = (EditText)findViewById(R.id.editCmd);

textCmd.setText(textCmd.getText().toString() + " "+uri);

}
}
}


最后,命令会涉及文件读写权限,AndroidManifest.xml中添加sd卡读写权限:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


5.测试结果:









author

Name:Luis

Email:@Luis

QQ:1396954967

CSDN:fjnuLuis

github:fjnuLuis

作者:林雍

原文链接:安卓手机无法root的情况下使用busybox
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: