致命异常:主要用于数据包嗅探应用程序
Posted
技术标签:
【中文标题】致命异常:主要用于数据包嗅探应用程序【英文标题】:Fatal Exception:main for packet sniffing application 【发布时间】:2012-08-17 01:19:49 【问题描述】:我是 android 编程的初学者,我正在做我的期末项目,我需要开发一个数据包嗅探应用程序。我在互联网上找到了一些代码,并试图将其扩展到我的项目中。但得到 FATAL EXCEPTION: main 和 following 错误。
代码如下:
public class Main extends Activity
// Variable declarations for handling the view items in the layout.
private Button start_button;
private Button stop_button;
private Button read_button;
private EditText parameters;
// Variable declarations for handling the TCPdump process.
private TCPdump tcpdump = null;
private TCPdumpHandler tcpDumpHandler = null;
private SharedPreferences settings = null;
// Variable declarations for handling the options and reader activities.
private Intent optionsIntent = null;
private Intent readerIntent = null;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Associating the items in the view to the variables.
start_button = (Button) findViewById(R.id.start_button);
stop_button = (Button) findViewById(R.id.stop_button);
read_button = (Button) findViewById(R.id.read_button);
parameters = (EditText) findViewById(R.id.params_text);
// Accessing the app's preferences.
settings = getSharedPreferences(GlobalConstants.prefsName, 0);
// Extracting the TCPdump binary to the app folder.
if (RootTools.installBinary(Main.this, R.raw.tcpdump, "tcpdump") == false)
new AlertDialog.Builder(Main.this)
.setTitle(R.string.extraction_error)
.setMessage(R.string.extraction_error_msg)
.setNeutralButton(R.string.ok, null).show();
// Creating a new TCPdump object.
tcpdump = new TCPdump();
// Creating a TCPdump handler for the TCPdump object created after.
tcpDumpHandler = new TCPdumpHandler(tcpdump, this, this, true);
// Obtaining the command from the options that were saved last time
// Shark was running.
tcpDumpHandler.generateCommand();
start_button.setOnClickListener(new OnClickListener()
// Setting the action to perform when the start button is pressed.
public void onClick(View v)
startTCPdump();
);
stop_button.setOnClickListener(new OnClickListener()
// Setting the action to perform when the stop button is pressed.
public void onClick(View v)
stopTCPdump();
);
read_button.setOnClickListener(new OnClickListener()
// Setting the action to perform when the open in reader button is
// pressed.
public void onClick(View v)
launchReader();
);
BroadcastReceiver connectionReceiver = new BroadcastReceiver()
@Override
public void onReceive(Context context, Intent intent)
// Setting the action to be performed when the network status
// changes.
if ((tcpDumpHandler.checkNetworkStatus() == false)
&& (tcpdump.getProcessStatus()))
stopTCPdump();
new AlertDialog.Builder(Main.this)
.setTitle(
getString(R.string.network_connection_down))
.setMessage(
getString(R.string.network_connection_down_msg))
.setNeutralButton(getString(R.string.ok), null)
.show();
;
// Registering the BroadcastReceiver and associating it with the
// connectivity change event.
registerReceiver(connectionReceiver, new IntentFilter(
"android.net.conn.CONNECTIVITY_CHANGE"));
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
// Setting the action to perform when returning to this activity from
// another activity which had been called.
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && requestCode == 1)
if (tcpdump.getProcessStatus())
new AlertDialog.Builder(Main.this)
.setTitle(getString(R.string.settings_changed))
.setMessage(getString(R.string.settings_changed_msg))
.setNeutralButton(getString(R.string.ok), null).show();
tcpDumpHandler.generateCommand();
@Override
public void onDestroy()
// Setting the action to perform when the Android O.S. kills this
// activity.
if (tcpdump.getProcessStatus())
stopTCPdump();
public boolean onCreateOptionsMenu(Menu menu)
// This code makes the activity to show a menu when the device's menu
// key is pressed.
menu.add(0, 0, 0, getString(R.string.options_text));
menu.add(0, 1, 0, getString(R.string.about_text));
return true;
public boolean onOptionsItemSelected(MenuItem item)
// Setting the action to perform when an option from the menu is
// selected.
switch (item.getItemId())
case 0:
optionsIntent = new Intent(Main.this, Options.class);
startActivityForResult(optionsIntent, 1);
return true;
case 1:
new AlertDialog.Builder(Main.this).setTitle(R.string.about_text)
.setMessage(getString(R.string.about_shark))
.setNeutralButton(getString(R.string.ok), null).show();
return true;
return false;
/**
* Calls TCPdumpHandler to try start the packet capture.
*/
private void startTCPdump()
if (tcpDumpHandler.checkNetworkStatus())
switch (tcpDumpHandler.start(parameters.getText().toString()))
case 0:
Toast.makeText(Main.this, getString(R.string.tcpdump_started),
Toast.LENGTH_SHORT).show();
break;
case -1:
Toast.makeText(Main.this,
getString(R.string.tcpdump_already_started),
Toast.LENGTH_SHORT).show();
break;
case -2:
new AlertDialog.Builder(Main.this)
.setTitle(getString(R.string.device_not_rooted_error))
.setMessage(
getString(R.string.device_not_rooted_error_msg))
.setNeutralButton(getString(R.string.ok), null).show();
break;
case -4:
new AlertDialog.Builder(Main.this).setTitle("Error")
.setMessage(getString(R.string.command_error))
.setNeutralButton(getString(R.string.ok), null).show();
break;
case -5:
new AlertDialog.Builder(Main.this).setTitle("Error")
.setMessage(getString(R.string.outputstream_error))
.setNeutralButton(getString(R.string.ok), null).show();
break;
default:
new AlertDialog.Builder(Main.this).setTitle("Error")
.setMessage(getString(R.string.unknown_error))
.setNeutralButton(getString(R.string.ok), null).show();
else
new AlertDialog.Builder(Main.this)
.setTitle(getString(R.string.network_connection_error))
.setMessage(
getString(R.string.network_connection_error_msg))
.setPositiveButton(getString(R.string.yes),
new DialogInterface.OnClickListener()
public void onClick(DialogInterface dialog,
int which)
startActivity(new Intent(
Settings.ACTION_WIRELESS_SETTINGS));
).setNegativeButton(getString(R.string.no), null)
.show();
/**
* Calls TCPdumpHandler to try to stop the packet capture.
*/
private void stopTCPdump()
switch (tcpDumpHandler.stop())
case 0:
Toast.makeText(Main.this, getString(R.string.tcpdump_stoped),
Toast.LENGTH_SHORT).show();
break;
case -1:
Toast.makeText(Main.this,
getString(R.string.tcpdump_already_stoped),
Toast.LENGTH_SHORT).show();
break;
case -2:
new AlertDialog.Builder(Main.this)
.setTitle(getString(R.string.device_not_rooted_error))
.setMessage(getString(R.string.device_not_rooted_error_msg))
.setNeutralButton(getString(R.string.ok), null).show();
break;
case -4:
new AlertDialog.Builder(Main.this).setTitle("Error")
.setMessage(getString(R.string.command_error))
.setNeutralButton(getString(R.string.ok), null).show();
break;
case -5:
new AlertDialog.Builder(Main.this).setTitle("Error")
.setMessage(getString(R.string.outputstream_error))
.setNeutralButton(getString(R.string.ok), null).show();
break;
case -6:
new AlertDialog.Builder(Main.this).setTitle("Error")
.setMessage(getString(R.string.close_shell_error))
.setNeutralButton(getString(R.string.ok), null).show();
break;
case -7:
new AlertDialog.Builder(Main.this).setTitle("Error")
.setMessage(getString(R.string.process_finish_error))
.setNeutralButton(getString(R.string.ok), null).show();
default:
new AlertDialog.Builder(Main.this).setTitle("Error")
.setMessage(getString(R.string.unknown_error))
.setNeutralButton(getString(R.string.ok), null).show();
/**
* Tries to launch the reader activity.
*/
private void launchReader()
readerIntent = new Intent(Main.this, Reader.class);
if (FileManager.checkFile(GlobalConstants.dirName,
settings.getString("fileText", "shark_capture.pcap")))
if (tcpdump.getProcessStatus() == false)
startActivity(readerIntent);
else
new AlertDialog.Builder(Main.this)
.setTitle(getString(R.string.capture_in_progress_error))
.setMessage(
getString(R.string.capture_in_progress_error_msg))
.setPositiveButton(getString(R.string.yes),
new DialogInterface.OnClickListener()
public void onClick(DialogInterface arg0,
int arg1)
stopTCPdump();
startActivity(readerIntent);
)
.setNegativeButton(getString(R.string.no), null).show();
else
new AlertDialog.Builder(Main.this)
.setTitle(getString(R.string.file_error))
.setMessage(getString(R.string.file_error_msg))
.setNeutralButton(getString(R.string.ok), null).show();
当我运行这个 Eclipse 时,我在日志中收到一个错误 cat 以下错误。我尝试了很多建议的解决方案,即使那样我也无法获得解决方案。
08-21 15:38:01.483: D/AndroidRuntime(499): Shutting down VM
08-21 15:38:01.483: W/dalvikvm(499): threadid=1: thread exiting with uncaught exception (group=0x4001d800)
08-21 15:38:01.504: E/AndroidRuntime(499): FATAL EXCEPTION: main
08-21 15:38:01.504: E/AndroidRuntime(499): java.lang.RuntimeException: Unable to start activity ComponentInfocom.shark/com.shark.Main: java.lang.NullPointerException
08-21 15:38:01.504: E/AndroidRuntime(499): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
08-21 15:38:01.504: E/AndroidRuntime(499): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
08-21 15:38:01.504: E/AndroidRuntime(499): at android.app.ActivityThread.access$2300(ActivityThread.java:125)
08-21 15:38:01.504: E/AndroidRuntime(499): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
08-21 15:38:01.504: E/AndroidRuntime(499): at android.os.Handler.dispatchMessage(Handler.java:99)
08-21 15:38:01.504: E/AndroidRuntime(499): at android.os.Looper.loop(Looper.java:123)
08-21 15:38:01.504: E/AndroidRuntime(499): at android.app.ActivityThread.main(ActivityThread.java:4627)
08-21 15:38:01.504: E/AndroidRuntime(499): at java.lang.reflect.Method.invokeNative(Native Method)
08-21 15:38:01.504: E/AndroidRuntime(499): at java.lang.reflect.Method.invoke(Method.java:521)
08-21 15:38:01.504: E/AndroidRuntime(499): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
08-21 15:38:01.504: E/AndroidRuntime(499): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
08-21 15:38:01.504: E/AndroidRuntime(499): at dalvik.system.NativeStart.main(Native Method)
08-21 15:38:01.504: E/AndroidRuntime(499): Caused by: java.lang.NullPointerException
08-21 15:38:01.504: E/AndroidRuntime(499): at com.shark.TCPdumpHandler.generateCommand(TCPdumpHandler.java:322)
08-21 15:38:01.504: E/AndroidRuntime(499): at com.shark.Main.onCreate(Main.java:93)
08-21 15:38:01.504: E/AndroidRuntime(499): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
08-21 15:38:01.504: E/AndroidRuntime(499): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
08-21 15:38:01.504: E/AndroidRuntime(499): ... 11 more
我找到了错误发生的确切位置。据此,“closeShell”在以下代码中返回 null。进一步循环回三个类。
public class RootShell
protected Process process = null;
protected DataOutputStream os = null;
protected DataInputStream is = null;
private boolean deviceRooted = false;
/**
* RootShell class constructor. Checks if the device is rooted.
*/
public RootShell()
deviceRooted = checkRootStatus();
/**
* RootShell class destructor. Closes the shell if its not already closed.
*/
protected void finalize()
if (process != null)
closeShell();
/**
* Opens a root shell and waits for commands.
*
* @return 0 Everything went OK.<br>
* -1 The shell has already been opened.<br>
* -2 The device isn't rooted.<br>
* -3 IOException when running the su command.
*/
public int openShell()
if (process == null)
if (deviceRooted)
// Trying to get root access.
try
process = Runtime.getRuntime().exec("su");
catch (IOException e)
return -3;
// Getting an output stream to the root shell for introducing
// commands.
os = new DataOutputStream(process.getOutputStream());
// Getting an input stream to the root shell for displaying
// results.
is = new DataInputStream(process.getInputStream());
return 0;
else
return -2;
else
return -1;
/**
* Runs the command in the root shell.
*
* @param command
* The command which will be executed in the root shell.
* @return 0 Everything went OK.<br>
* -1 The shell wasn't opened.<br>
* -2 The device isn't rooted.<br>
* -4 IOException when running the user command.<br>
* -5 IOException when flushing the DataOutputStream.
*/
public int runCommand(String command)
if (process != null)
if (deviceRooted)
try
os.writeBytes(command + "\n");
catch (IOException e)
return -4;
try
os.flush();
catch (IOException e)
return -5;
return 0;
else
return -2;
else
return -1;
/**
* Closes a shell which is already open.
*
* @return -1 The shell wasn't opened.<br>
* -2 The device isn't rooted.<br>
* -6 IOException when running the exit command.<br>
* -7 InterruptedException when waiting for the process to stop.
*/
public int closeShell()
if (process != null)
if (deviceRooted)
try
os.writeBytes("exit\n");
catch (IOException e1)
return -6;
try
process.waitFor();
catch (InterruptedException e)
return -7;
process.destroy();
process = null;
os = null;
is = null;
return 0;
else
return -2;
else
return -1;
/**
* Checks if an Android device is rooted or not.<br>
* Code borrowed from: http://www
* .stealthcopter.com/blog/2010/01/android-requesting-root-access-in
* -your-app/
*
* @return true: The device is rooted.<br>
* false: The device isn't rooted.
*/
private static boolean checkRootStatus()
Process p;
try
// Preform su to get root privileges
p = Runtime.getRuntime().exec("su");
// Attempt to write a file to a root-only
DataOutputStream os = new DataOutputStream(p.getOutputStream());
os.writeBytes("echo \"Do I have root?\" >/system/sd/temporary.txt\n");
// Close the terminal
os.writeBytes("exit\n");
os.flush();
try
p.waitFor();
if (p.exitValue() != 255)
return true;
else
return false;
catch (InterruptedException e)
return false;
catch (IOException e)
return false;
/**
* @return A DataInputStream to the root shell.
*/
public DataInputStream getInputStream()
return is;
/**
* @return A DataOutputStream to the root shell.
*/
public DataOutputStream getOutputStream()
return os;
/**
* @return true if the shell is opened.<br>
* false if the shell isn't opened.
*/
public boolean getProcessStatus()
if (process != null)
return true;
else
return false;
我还发现,它给出“08-22 19:05:19.701: I/System.out(275): e1java.io.IOException: Broken pipe”,它在“closeshell”中输入 try catch。
【问题讨论】:
【参考方案1】:您的R.id.start_button
和其他多个地方的R
是什么?
错误是指tcpDumpHandler.generateCommand()
,但您没有提供它的代码。
【讨论】:
非常感谢,我找到了错误的主要原因。尝试获取 root 访问权限时,它在某一时刻返回 null,但我无法更正它。 我还有一个疑问,我们能否在 Eclipse 中在 Android Emulator 上运行需要 root 权限的应用程序?? R 指向 gen 包中的 R.java 文件,该文件与 main.xml 中定义的开始按钮相关,将在 UI 中显示。以上是关于致命异常:主要用于数据包嗅探应用程序的主要内容,如果未能解决你的问题,请参考以下文章