作者:万境绝尘

转载请著名出处: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 文件名 手机中的文件全路径名命令;

[plain] view plain copy
  1. octopus@octopus:~/csdn$adbpushbusybox-armv7l/sdcard/octopus/busybox
  2. 3256KB/s(1109128bytesin0.332s)
-- 上传到内存失败 : 使用 adb push 上传到内存中失败, 因为 adb 使用的是 system 用户, 只有 root 用户才有权限向内存中写入数据;

[plain] view plain copy
  1. octopus@octopus:~/csdn$adbpushbusybox-armv7l/data/busybox
  2. failedtocopy'busybox-armv7l'to'/data/busybox':Permissiondenied
-- 查看并修改busybox权限失败 : system 用户没有修改 sd 卡文件模式的权限;

[plain] view plain copy
  1. shell@android:/sdcard/octopus$ll
  2. -rw-rw-r--rootsdcard_rw11091282014-07-0819:49busybox
  3. shell@android:/sdcard/octopus$chmod755busybox
  4. Unabletochmodbusybox:Operationnotpermitted

应用程序解决方案:

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

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


2. 实现策略


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

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

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

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

获取执行结果 :


3. 使用到的api解析


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


[java] view plain copy
  1. InputStreamis=context.getAssets().open(source);
-- 获取AssetsManager : 调用 Context 上下文对象的 context.getAssets() 即可获取 AssetsManager对象;

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


(2) 文件流相关操作


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

[java] view plain copy
  1. intsize=is.available();

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

[java] view plain copy
  1. byte[]buffer=newbyte[size];
  2. is.read(buffer);
  3. is.close();

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

[java] view plain copy
  1. FileOutputStreamoutput=context.openFileOutput(destination,Context.MODE_PRIVATE);
  2. output.write(buffer);
  3. output.close();



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


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

[java] view plain copy
  1. StringfilesPath=context.getFilesDir().getAbsolutePath();


(4) 执行二进制文件


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

[java] view plain copy
  1. Runtimeruntime=Runtime.getRuntime();
  2. process=runtime.exec(cmd);

获取执行的命令行结果 :

[java] view plain copy
  1. InputStreamis=process.getInputStream();
  2. BufferedReaderbr=newBufferedReader(newInputStreamReader(is));
  3. Stringline=null;
  4. while((line=br.readLine())!=null){
  5. processList.add(line);
  6. }
  7. br.close();


4. 代码示例


MainActivity 主程序代码:

[java] view plain copy
  1. packagecn.org.octopus.tracerouteandbusybox;
  2. importjava.io.BufferedReader;
  3. importjava.io.FileNotFoundException;
  4. importjava.io.FileOutputStream;
  5. importjava.io.IOException;
  6. importjava.io.InputStream;
  7. importjava.io.InputStreamReader;
  8. importjava.util.ArrayList;
  9. importjava.util.List;
  10. importandroid.content.Context;
  11. importandroid.os.Bundle;
  12. importandroid.support.v7.app.ActionBarActivity;
  13. importandroid.view.View;
  14. importandroid.widget.EditText;
  15. importandroid.widget.TextView;
  16. /**看不懂注释我就吃半斤狗粮:-)*/
  17. publicclassMainActivityextendsActionBarActivity{
  18. privateEditTextet_cmd;
  19. privateStringapp_path;
  20. privateTextViewtv_result;
  21. @Override
  22. protectedvoidonCreate(BundlesavedInstanceState){
  23. super.onCreate(savedInstanceState);
  24. setContentView(R.layout.home_activity);
  25. /*初始化控件*/
  26. et_cmd=(EditText)findViewById(R.id.et_cmd);
  27. tv_result=(TextView)findViewById(R.id.tv_result);
  28. /*获取app安装路径*/
  29. app_path=getApplicationContext().getFilesDir().getAbsolutePath();
  30. }
  31. /**按钮点击事件*/
  32. publicvoidonClick(Viewview){
  33. intid=view.getId();
  34. switch(id){
  35. caseR.id.copy_busybox:/*拷贝busybox可执行文件*/
  36. varifyFile(getApplicationContext(),"busybox");
  37. break;
  38. caseR.id.copy_traceroute:/*拷贝traceroute可执行文件*/
  39. varifyFile(getApplicationContext(),"traceroute");
  40. break;
  41. caseR.id.exe_busybox:/*将busybox命令添加到Editext中*/
  42. Stringcmd="."+app_path+"/busybox";
  43. System.out.println(et_cmd);
  44. et_cmd.setText(cmd);
  45. break;
  46. caseR.id.exe_traceroute:/*将traceroute命令添加到Editext中*/
  47. cmd="."+app_path+"/traceroute8.8.8.8";
  48. et_cmd.setText(cmd);
  49. break;
  50. caseR.id.exe:/*执行Editext中的命令*/
  51. cmd=et_cmd.getText().toString();
  52. /*执行脚本命令*/
  53. List<String>results=exe(cmd);
  54. Stringresult="";
  55. /*将结果转换成字符串,输出到TextView中*/
  56. for(Stringline:results){
  57. result+=line+"\n";
  58. }
  59. tv_result.setText(result);
  60. break;
  61. default:
  62. break;
  63. }
  64. }
  65. /**验证文件是否存在,如果不存在就拷贝*/
  66. privatevoidvarifyFile(Contextcontext,StringfileName){
  67. try{
  68. /*查看文件是否存在,如果不存在就会走异常中的代码*/
  69. context.openFileInput(fileName);
  70. }catch(FileNotFoundExceptionnotfoundE){
  71. try{
  72. /*拷贝文件到app安装目录的files目录下*/
  73. copyFromAssets(context,fileName,fileName);
  74. /*修改文件权限脚本*/
  75. Stringscript="chmod700"+app_path+"/"+fileName;
  76. /*执行脚本*/
  77. exe(script);
  78. }catch(Exceptione){
  79. e.printStackTrace();
  80. }
  81. }
  82. }
  83. /**将文件从assets目录中拷贝到app安装目录的files目录下*/
  84. privatevoidcopyFromAssets(Contextcontext,Stringsource,
  85. Stringdestination)throwsIOException{
  86. /*获取assets目录下文件的输入流*/
  87. InputStreamis=context.getAssets().open(source);
  88. /*获取文件大小*/
  89. intsize=is.available();
  90. /*创建文件的缓冲区*/
  91. byte[]buffer=newbyte[size];
  92. /*将文件读取到缓冲区中*/
  93. is.read(buffer);
  94. /*关闭输入流*/
  95. is.close();
  96. /*打开app安装目录文件的输出流*/
  97. FileOutputStreamoutput=context.openFileOutput(destination,
  98. Context.MODE_PRIVATE);
  99. /*将文件从缓冲区中写出到内存中*/
  100. output.write(buffer);
  101. /*关闭输出流*/
  102. output.close();
  103. }
  104. /**执行shell脚本命令*/
  105. privateList<String>exe(Stringcmd){
  106. /*获取执行工具*/
  107. Processprocess=null;
  108. /*存放脚本执行结果*/
  109. List<String>list=newArrayList<String>();
  110. try{
  111. /*获取运行时环境*/
  112. Runtimeruntime=Runtime.getRuntime();
  113. /*执行脚本*/
  114. process=runtime.exec(cmd);
  115. /*获取脚本结果的输入流*/
  116. InputStreamis=process.getInputStream();
  117. BufferedReaderbr=newBufferedReader(newInputStreamReader(is));
  118. Stringline=null;
  119. /*逐行读取脚本执行结果*/
  120. while((line=br.readLine())!=null){
  121. list.add(line);
  122. }
  123. br.close();
  124. }catch(IOExceptione){
  125. e.printStackTrace();
  126. }
  127. returnlist;
  128. }
  129. }


home_activity.xml 布局文件代码:

[html] view plain copy
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical">
  6. <LinearLayout
  7. android:layout_width="match_parent"
  8. android:layout_height="wrap_content"
  9. android:gravity="center"
  10. android:orientation="horizontal">
  11. <Button
  12. android:id="@+id/copy_busybox"
  13. android:layout_width="wrap_content"
  14. android:layout_height="wrap_content"
  15. android:onClick="onClick"
  16. android:text="拷贝busybox"
  17. android:textSize="7dp"
  18. android:textStyle="bold"/>
  19. <Button
  20. android:id="@+id/copy_traceroute"
  21. android:layout_width="wrap_content"
  22. android:layout_height="wrap_content"
  23. android:onClick="onClick"
  24. android:text="拷贝traceroute"
  25. android:textSize="7dp"
  26. android:textStyle="bold"/>
  27. <Button
  28. android:id="@+id/exe_busybox"
  29. android:layout_width="wrap_content"
  30. android:layout_height="wrap_content"
  31. android:onClick="onClick"
  32. android:text="执行busybox"
  33. android:textSize="7dp"
  34. android:textStyle="bold"/>
  35. <Button
  36. android:id="@+id/exe_traceroute"
  37. android:layout_width="wrap_content"
  38. android:layout_height="wrap_content"
  39. android:onClick="onClick"
  40. android:text="执行traceroute"
  41. android:textSize="7dp"
  42. android:textStyle="bold"/>
  43. </LinearLayout>
  44. <LinearLayout
  45. android:layout_width="match_parent"
  46. android:layout_height="wrap_content"
  47. android:orientation="horizontal">
  48. <EditText
  49. android:id="@+id/et_cmd"
  50. android:layout_width="0dp"
  51. android:layout_height="wrap_content"
  52. android:layout_weight="4"
  53. android:hint="输入要执行的命令"
  54. android:textStyle="bold"/>
  55. <Button
  56. android:id="@+id/exe"
  57. android:layout_width="0dp"
  58. android:layout_height="wrap_content"
  59. android:layout_weight="1"
  60. android:onClick="onClick"
  61. android:text="执行"
  62. android:textSize="10dp"
  63. android:textStyle="bold"/>
  64. </LinearLayout>
  65. <TextView
  66. android:id="@+id/tv_result"
  67. android:layout_width="match_parent"
  68. android:layout_height="match_parent"
  69. android:background="#000000"
  70. android:textColor="#FFF"
  71. android:textSize="10dp"
  72. android:textStyle="bold"/>
  73. </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

更多相关文章

  1. XML解析
  2. Android可执行文件
  3. android 百度sdk之 百度定位
  4. 我的第一个python脚本
  5. 反编译Android部署程序
  6. android 3.3 butterknife-7.0.1。jar(com.jakewharton:butterkni
  7. 一些android错误
  8. android File保存数据
  9. adb push可执行文件制作教程

随机推荐

  1. Android类库介绍
  2. Android启动流程分析(十二) SystemServer
  3. Android深入浅出系列课程---Lesson1 AAF1
  4. Android常见布局简述
  5. Android之NDK开发
  6. Android(安卓)入门教程:安装 Android(安卓
  7. 《宅男的android开发指南》(翻译)--1
  8. Android设备获取wifi下的ipv6地址
  9. View类xml属性、方法
  10. Android体系结构