編輯:關於Android編程
文件權限修改無法實現 : 如果 沒有 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/ 目錄下;
文件初始放置 : 將 交叉編譯好的 busybox 文件放在 工程目錄的 /res/assets/ 目錄下;
文件拷貝 : 將該 二進制文件 拷貝到 app 的安裝目錄的 files 目錄下, 即 /data/data/包名/files/下;
修改文件權限 : 使用命令可以直接修改該目錄下的權限, 注意這個操作是可以執行的;
執行busybox : 在代碼中執行 ./data/data/包名/files/busybox ;
獲取執行結果 :
InputStream is = context.getAssets().open(source);-- 獲取AssetsManager : 調用 Context 上下文對象的 context.getAssets() 即可獲取 AssetsManager對象;
-- 獲取輸入流 : 調用 AssetsManager 的 open(String fileName) 即可獲取對應文件名的輸入流;
根據輸入流獲取文件大小 : 調用輸入流的 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();
獲取app絕對安裝路徑 : 調用 上下文對象的 getFilesDir().getAbsolutePath() 方法;
String filesPath = context.getFilesDir().getAbsolutePath();
創建 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();
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(); /* 執行腳本命令 */ Listresults = exe(cmd); String result = ; /* 將結果轉換成字符串, 輸出到 TextView中 */ for(String line : results){ result += line + ; } 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 exe(String cmd) { /* 獲取執行工具 */ Process process = null; /* 存放腳本執行結果 */ List list = new ArrayList (); 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 布局文件代碼 :
執行 busybox 程序 :
執行 traceroute 程序 :
示例代碼下載 :
-- CSDN : http://download.csdn.net/detail/han1202012/7639253;
-- GitHub : https://github.com/han1202012/TracerouteAndBusybox ;
作者 : 萬境絕塵
轉載請著名出處 : http://blog.csdn.net/shulianghan/article/details/36438365
提煉為常量是從臨時變量快速提煉出靜態常量,這也是我們常用的重構手段.操作步驟:? 菜單欄: Refactor —> Extract —>
新建一個布局文件 my_dialog.xml 以下是strings.xml文件: demo091801 Sett
(一).前言:今天我們的項目繼續更新,今天我們主要講解消息總線EventBus的基本使用方法,後面一篇我們會從源碼的角度稍微分析一下實現過程。Fa
之前學習了Pulltorefresh,pinnedheaderexpanablelistview 但是結合起來還是有點麻煩的。尤其是像QQ這種。他不是單純的第一個當做分組