Android應用很多時候都會涉及到網絡,在請求網絡出錯時,我們可以通過抓包來分析網絡請求,返回的數據等,通常我們是用tcpdump這個工具來抓包,再通過wireshark工具來分析生成的文件,關於tcpdump的使,可以從網上查一下,有很多介紹,比如:http://www.cnblogs.com/likwo/archive/2012/09/06/2673944.html。關於如何用wireshark來分析文件,本文不作介紹。
使用adb的命令來操作,還是比較麻煩,所以我寫了一個應用,把這些命令封裝了起來。實現的最根本的原理是通過Runtime.exec來執行linux命令。
運行截圖
、
實現代碼
CommandsHelper.java<喎?/kf/ware/vc/" target="_blank" class="keylink">vc3Ryb25nPgo8cHJlIGNsYXNzPQ=="brush:java;">/**
*
* @author lihong06
* @since 2014-3-3
*/
public class CommandsHelper {
private static final String NAME = "tcpdump";
private static final String TAG = "CommandsHelper";
public static final String DEST_FILE = Environment.getExternalStorageDirectory() + "/capture.pcap";
public static boolean startCapture(Context context) {
InputStream is = null;
OutputStream os = null;
boolean retVal = false;
try {
AssetManager am = context.getAssets();
is = am.open(NAME);
File sdcardFile = Environment.getExternalStorageDirectory();
File dstFile = new File(sdcardFile, NAME);
os = new FileOutputStream(dstFile);
copyStream(is, os);
String[] commands = new String[7];
commands[0] = "adb shell";
commands[1] = "su";
commands[2] = "cp -rf " + dstFile.toString() + " /data/local/tcpdump";
commands[3] = "rm -r " + dstFile.toString();
commands[4] = "chmod 777 /data/local/tcpdump";
commands[5] = "cd /data/local";
commands[6] = "tcpdump -p -vv -s 0 -w " + DEST_FILE;
execCmd(commands);
} catch (IOException e) {
e.printStackTrace();
Log.i(TAG, " error: " + e.getMessage());
} finally {
closeSafely(is);
closeSafely(os);
}
return retVal;
}
public static void stopCapture(Context context) {
// 找出所有的帶有tcpdump的進程
String[] commands = new String[2];
commands[0] = "adb shell";
commands[1] = "ps|grep tcpdump|grep root|awk '{print $2}'";
Process process = execCmd(commands);
String result = parseInputStream(process.getInputStream());
if (!TextUtils.isEmpty(result)) {
String[] pids = result.split("\n");
if (null != pids) {
String[] killCmds = new String[pids.length];
for (int i = 0; i < pids.length; ++i) {
killCmds[i] = "kill -9 " + pids[i];
}
execCmd(killCmds);
}
}
}
public static Process execCmd(String command) {
return execCmd(new String[] { command }, true);
}
public static Process execCmd(String[] commands) {
return execCmd(commands, true);
}
public static Process execCmd(String[] commands, boolean waitFor) {
Process suProcess = null;
try {
suProcess = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(suProcess.getOutputStream());
for (String cmd : commands) {
if (!TextUtils.isEmpty(cmd)) {
os.writeBytes(cmd + "\n");
}
}
os.flush();
os.writeBytes("exit\n");
os.flush();
} catch (IOException e) {
e.printStackTrace();
}
if (waitFor) {
boolean retval = false;
try {
int suProcessRetval = suProcess.waitFor();
if (255 != suProcessRetval) {
retval = true;
} else {
retval = false;
}
} catch (Exception ex) {
Log.w("Error ejecutando el comando Root", ex);
}
}
return suProcess;
}
private static void copyStream(InputStream is, OutputStream os) {
final int BUFFER_SIZE = 1024;
try {
byte[] bytes = new byte[BUFFER_SIZE];
for (;;) {
int count = is.read(bytes, 0, BUFFER_SIZE);
if (count == -1) {
break;
}
os.write(bytes, 0, count);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void closeSafely(Closeable is) {
try {
if (null != is) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static String parseInputStream(InputStream is) {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = null;
StringBuilder sb = new StringBuilder();
try {
while ( (line = br.readLine()) != null) {
sb.append(line).append("\n");
}
} catch (IOException e) {
e.printStackTrace();
}
return sb.toString();
}
}
MainActivity.java
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textView = (TextView) findViewById(R.id.textView1);
String oldText = textView.getText().toString();
textView.setText(oldText + "\n\n" + "目標文件: " + CommandsHelper.DEST_FILE);
findViewById(R.id.start_capture).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
v.setEnabled(false);
new Thread(new Runnable() {
@Override
public void run() {
final boolean retVal = CommandsHelper.startCapture(MainActivity.this);
runOnUiThread(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "startCapture result = " + retVal, Toast.LENGTH_SHORT).show();
}
});
}
}).start();
}
});
findViewById(R.id.stop_capture).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
CommandsHelper.stopCapture(MainActivity.this);
findViewById(R.id.start_capture).setEnabled(true);
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
說明
1、手機必須要Root,沒有root的我沒有測試過,另外,我也只測試了我一台手機,沒有覆蓋到所有的手機。
2、大家如果發現問題,請告知於我,謝謝。