作者 : 万境绝尘

转载请著名出处http://blog.csdn.net/shulianghan/article/details/36438365

示例代码下载 :

-- CSDN : http://download.csdn.net/detail/han1202012/7639253;

-- GitHub : https://github.com/han1202012/TracerouteAndBusybox ;

1. 原理思路

文件权限修改无法实现 : 如果 没有 root 权限, 就不能改变二进制文件的文件权限;

-- 将busybox推送到Android系统中 : 使用 adb push 命令, 将 busybox 传入到 sd 卡中, 注意, 上传到内存中无法实现;

-- 上传到sd卡成功 : 使用 adb push 文件名 手机中的文件全路径名 命令;

octopus@octopus:~/csdn$ adb push busybox-armv7l /sdcard/octopus/busybox
3256 KB/s (1109128 bytes in 0.332s)

-- 上传到内存失败 : 使用 adb push 上传到内存中失败, 因为 adb 使用的是 system 用户, 只有 root 用户才有权限向内存中写入数据;

octopus@octopus:~/csdn$ adb push busybox-armv7l /data/busybox
failed to copy 'busybox-armv7l' to '/data/busybox': Permission denied

-- 查看并修改busybox权限失败 : system 用户没有修改 sd 卡文件模式的权限;

shell@android:/sdcard/octopus $ ll
-rw-rw-r-- root     sdcard_rw  1109128 2014-07-08 19:49 busybox
shell@android:/sdcard/octopus $ chmod 755 busybox
Unable to chmod busybox: Operation not permitted

应用程序解决方案 :

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

-- 将可执行二进制文件拷贝到安装目录中 : 将交叉编译好的 busybox 放到 工程目录下的 res/assets/ 目录下;

2. 实现策略

文件初始放置 : 将 交叉编译好的 busybox 文件放在 工程目录的 /res/assets/ 目录下;

文件拷贝 : 将该 二进制文件 拷贝到 app 的安装目录的 files 目录下, 即 /data/data/包名/files/下;

修改文件权限 : 使用命令可以直接修改该目录下的权限, 注意这个操作是可以执行的;

执行busybox : 在代码中执行 ./data/data/包名/files/busybox ;

获取执行结果 :

3. 使用到的api解析

(1) 获取 assets 目录文件的输入流

InputStream is = context.getAssets().open(source);

-- 获取AssetsManager : 调用 Context 上下文对象的 context.getAssets() 即可获取 AssetsManager对象;

-- 获取输入流 : 调用 AssetsManager 的 open(String fileName) 即可获取对应文件名的输入流;

(2) 文件流相关操作

根据输入流获取文件大小 : 调用输入流的 inputStream.available() 方法;

int size = is.available();

将文件读取到缓冲区中 : 创建一个与文件大小相同的字节数组缓冲区, 输入流将数据存放到缓冲区中;

byte[] buffer = new byte[size];
is.read(buffer);
is.close();

将文件写到内存中 : 调用上下文对象的 openFileOutput(绝对路径名, 权限), 即可创建一个文件的输出流;

FileOutputStream output = context.openFileOutput(destination, Context.MODE_PRIVATE);
output.write(buffer);
output.close();

(3) 获取文件的绝对路径

获取app绝对安装路径 : 调用 上下文对象的 getFilesDir().getAbsolutePath() 方法;

String filesPath = context.getFilesDir().getAbsolutePath();

(4) 执行二进制文件

创建 Process 对象, 并使用该 process 执行shell脚本命令 :

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) {
                processList.add(line);
            }
            br.close(); 

4. 代码示例

MainActivity 主程序代码 :

package cn.org.octopus.tracerouteandbusybox;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

/** 看不懂注释我就吃半斤狗粮 :-) */
public class MainActivity extends ActionBarActivity {

	private EditText et_cmd;
	private String app_path;
	private TextView tv_result;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.home_activity);

		/*初始化控件*/
		et_cmd = (EditText) findViewById(R.id.et_cmd);
		tv_result = (TextView) findViewById(R.id.tv_result);
		/* 获取app安装路径 */
		app_path = getApplicationContext().getFilesDir().getAbsolutePath();

	}

	/** 按钮点击事件 */
	public void onClick(View view) {
		int id = view.getId();
		switch (id) {
		case R.id.copy_busybox: /* 拷贝busybox可执行文件 */
			varifyFile(getApplicationContext(), "busybox");
			break;
		case R.id.copy_traceroute:/* 拷贝traceroute可执行文件 */
			varifyFile(getApplicationContext(), "traceroute");
			break;
		case R.id.exe_busybox:/* 将busybox命令添加到Editext中 */
			String cmd = "." + app_path + "/busybox";
			System.out.println(et_cmd);
			et_cmd.setText(cmd);
			break;
		case R.id.exe_traceroute:/* 将traceroute命令添加到Editext中 */
			cmd = "." + app_path + "/traceroute 8.8.8.8";
			et_cmd.setText(cmd);
			break;
		case R.id.exe: /* 执行Editext中的命令 */
			cmd = et_cmd.getText().toString();
			/* 执行脚本命令 */
			List<String> results = exe(cmd);
			String result = "";
			/* 将结果转换成字符串, 输出到 TextView中 */
			for(String line : results){
				result += line + "\n";
			}
			tv_result.setText(result);
			break;

		default:
			break;
		}
	}

	/** 验证文件是否存在, 如果不存在就拷贝 */
	private void varifyFile(Context context, String fileName) {

        try {
        	/* 查看文件是否存在, 如果不存在就会走异常中的代码 */
        	context.openFileInput(fileName);
        } catch (FileNotFoundException notfoundE) {
            try {
            	/* 拷贝文件到app安装目录的files目录下 */
                copyFromAssets(context, fileName, fileName);
                /* 修改文件权限脚本 */
                String script = "chmod 700 " + app_path + "/" + fileName;
                /* 执行脚本 */
                exe(script);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

	/** 将文件从assets目录中拷贝到app安装目录的files目录下 */
	private void copyFromAssets(Context context, String source,
			String destination) throws IOException {
		/* 获取assets目录下文件的输入流 */
		InputStream is = context.getAssets().open(source);
		/* 获取文件大小 */
		int size = is.available();
		/* 创建文件的缓冲区 */
		byte[] buffer = new byte[size];
		/* 将文件读取到缓冲区中 */
		is.read(buffer);
		/* 关闭输入流 */
		is.close();
		/* 打开app安装目录文件的输出流 */
		FileOutputStream output = context.openFileOutput(destination,
				Context.MODE_PRIVATE);
		/* 将文件从缓冲区中写出到内存中 */
		output.write(buffer);
		/* 关闭输出流 */
		output.close();
	}

	/** 执行 shell 脚本命令 */
	private List<String> exe(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;
	}

}

home_activity.xml 布局文件代码 :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal" >

        <Button
            android:id="@+id/copy_busybox"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onClick"
            android:text="拷贝busybox"
            android:textSize="7dp"
            android:textStyle="bold" />

        <Button
            android:id="@+id/copy_traceroute"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onClick"
            android:text="拷贝traceroute"
            android:textSize="7dp"
            android:textStyle="bold" />

        <Button
            android:id="@+id/exe_busybox"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onClick"
            android:text="执行busybox"
            android:textSize="7dp"
            android:textStyle="bold" />

        <Button
            android:id="@+id/exe_traceroute"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="onClick"
            android:text="执行traceroute"
            android:textSize="7dp"
            android:textStyle="bold" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <EditText
            android:id="@+id/et_cmd"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="4"
            android:hint="输入要执行的命令"
            android:textStyle="bold" />

        <Button
            android:id="@+id/exe"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="onClick"
            android:text="执行"
            android:textSize="10dp"
            android:textStyle="bold" />
    </LinearLayout>

    <TextView
        android:id="@+id/tv_result"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#000000"
        android:textColor="#FFF"
        android:textSize="10dp"
        android:textStyle="bold" />

</LinearLayout>

5. 执行结果

执行 busybox 程序 :

执行 traceroute 程序 :

示例代码下载 :

-- CSDN : http://download.csdn.net/detail/han1202012/7639253;

-- GitHub : https://github.com/han1202012/TracerouteAndBusybox ;

作者 : 万境绝尘

转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/36438365

【Android 应用开发】Android 上实现非root的 Traceroute -- 非Root权限下移植可执行二进制文件 脚本文件的更多相关文章

  1. Android 上实现非root的 Traceroute -- 非Root权限下移植可执行二进制文件 脚本文件

    作者 : 万境绝尘 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/36438365 示例代码下载 : -- CSDN : htt ...

  2. Android 上实现非root的 Traceroute -- 非Root权限下移植可运行二进制文件 脚本文件

    作者 : 万境绝尘 转载请著名出处 : http://blog.csdn.net/shulianghan/article/details/36438365 演示样例代码下载 : -- CSDN : h ...

  3. 用Android Studio 开发Android应用

    目前AndroidStudio已经到了1.2版本了,我用了下,觉得还蛮好的,有些自动生成的资源,它会自动帮你管理.下面开始列一下,我的开发环境搭配.在开始前,你得有个VPN,可者代理.嗯.不然你下不了 ...

  4. android studio 开发android app 真机调试

    大家都知道开发android app 的时候可以有2种调试方式, 一种是Android Virtual Device(虚拟模拟器) ,另一种就是真机调试. 这里要说的是真机调试的一些安装步骤: 1. ...

  5. 码农人生——从未学过Android如何开发Android App 案例讲解-第002期案例

    标题有点晃眼,本次分享是002期博文的实践故事,不会有任何代码.也不会教别人android 如何开发,类似博文已经有大批大批,而且还会有陆陆续续的人写,我写的文章,主要是经验之谈,希望总结出的一些方法 ...

  6. Android BLE开发——Android手机与BLE终端通信初识

    蓝牙BLE官方Demo下载地址:   http://download.csdn.net/detail/lqw770737185/8116019参考博客地址:    http://www.eoeandr ...

  7. Android多媒体开发-- android中OpenMax的实现整体框架

    1.android中用openmax来干啥? android中的AwesomePlayer就 是用openmax来做(code)编解码,其实在openmax接口设计中,他不光能用来当编解码.通过他的组 ...

  8. [Hybrid App]--Android混合开发,Android、Js的交互

    AndroidJs通信 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !imp ...

  9. Android Studio开发Android应用如何签名

    1.使用jdk自带的工具生成keystore 使用cmd命令行进入到jdk的bin目录(比如:C:\Program Files\Java\jdk1.7.0_01\bin) 运行如下命令: C:\Pro ...

随机推荐

  1. 628. Maximum Product of Three Numbers

    Given an integer array, find three numbers whose product is maximum and output the maximum product. ...

  2. Python练习之pillow

    此系列意在记录于一些有趣的程序及对其的总结. 问题来源: https://github.com/Yixiaohan/show-me-the-code https://github.com/HT524/ ...

  3. 无忧代理免费ip爬取(端口js加密)

    起因 为了训练爬虫技能(其实主要还是js技能-),翻了可能有反爬的网站挨个摧残,现在轮到这个网站了:http://www.data5u.com/free/index.shtml 解密过程 打开网站,在 ...

  4. OC基础之推荐一个旋转木马(跑马灯)效果的图片展示Demo

    这个旋转木马(跑马灯)效果的图片展示Demo,包括设定旋转方向,图片倒影,背景设置,旋转速度,开始结束,点击显示选中的图片,彩色的块展示等等功能 效果图:(源码下载:https://github.co ...

  5. 计算机网络之远程终端协议TELNET

    TELNET 是一个简单的远程终端协议.用户用 TELNET 就可在其所在地通过 TCP 连接注册(即登录)到远地的另一个主机上(使用主机名或 IP 地址). TELNET 能将用户的击键传到远地主机 ...

  6. Windows 10下Markdown不能显示预览

    Windows 10下Markdown不能显示预览 结局办法 下载awesomium的SDK,安装后重启Markdown即可 实测最新版本的SDK不行,建议安装1.6.6 下载地址:http://ww ...

  7. Dynamics CRM 安装CRM程序系统检查界面报未将对象引用设置到对象的实例的解决方法

    今天在安装CRM的时候,在系统检查阶段遇到了如下的错误,咋看之下直接是懵逼的 但不要着急,界面上有两个按钮,一个是详细信息,一个是帮助,详细信息不用看了就那一行字也看不出什么,咱们点下帮助看看,定位到 ...

  8. 详解EBS接口开发之应收INVOICE导入

    (一)应收INVOICE常用标准表简介 1.1   常用标准表 如下表中列出了与应收INVOICE导入相关的表和说明: 表名 说明 其他信息 RA_BATCH_SOURCES_ALL AR事务处理来源 ...

  9. tomcat启动批处理——startup.bat

    从文件命名上看就知道这是一个启动批处理,这个批处理的主要功能就是为了找到另一个批处理catalina.bat,并且执行catalina.bat. 一开始就用if "%OS%" == ...

  10. 非阻塞IO服务器模型

    我们来考虑一个情形,你跟千千万万个玩家是魔兽世界的超级粉丝,每周末准时组团打boss.每当周末游戏服务器就亚历山大,因为起码几十万用户同时在线.如果用我们的多线程阻塞服务器作为游戏服务器是否可行呢?先 ...