Android 致命异常:包嗅探应用程序的主要异常

Android 致命异常:包嗅探应用程序的主要异常,android,exception,main,Android,Exception,Main,我是Android编程的初学者,我正在做我的最后一个项目,我需要开发一个包嗅探应用程序。我在网上找到了一些代码,并试图将其扩展到我的项目中。但是得到了致命的异常:主要错误和以下错误 代码如下: public class Main extends Activity { // Variable declarations for handling the view items in the layout. private Button start_button; privat

我是Android编程的初学者,我正在做我的最后一个项目,我需要开发一个包嗅探应用程序。我在网上找到了一些代码,并试图将其扩展到我的项目中。但是得到了致命的异常:主要错误和以下错误

代码如下:

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 ComponentInfo{com.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;
}
}
公共类根shell{
受保护进程进程=null;
受保护的DataOutputStream os=null;
受保护的DataInputStream为空;
私有布尔设备ooted=false;
/**
*RootShell类构造函数。检查设备是否为根设备。
*/
公共根壳(){
deviceRooted=checkRootStatus();
}
/**
*RootShell类析构函数。如果外壳尚未关闭,则关闭外壳。
*/
受保护的void finalize(){
if(进程!=null)
闭壳();
}
/**
*打开根shell并等待命令。
* 
*@return 0一切正常。
*-1外壳已打开。
*-2设备没有根目录。
*-3运行su命令时发生IOException。 */ public int openShell(){ if(进程==null){ 如果(设备驱动){ //正在尝试获取根访问权限。 试一试{ process=Runtime.getRuntime().exec(“su”); }捕获(IOE异常){ 返回-3; } //获取到根shell的输出流以引入 //命令。 os=新的DataOutputStream(process.getOutputStream()); //获取根shell的输入流以显示 //结果。 is=新的DataInputStream(process.getInputStream()); 返回0; }否则 返回-2; }否则 返回-1; } /** *在根shell中运行该命令。 * *@param命令 *将在根shell中执行的命令。 *@return 0一切正常。
*-1外壳未打开。
*-2设备没有根目录。
*-4运行用户命令时发生IOException。
*-5刷新DataOutputStream时发生IOException。 */ 公共int运行命令(字符串命令){ if(进程!=null){ 如果(设备驱动){ 试一试{ os.writeBytes(命令+“\n”); }捕获(IOE异常){ 返回-4; } 试一试{ os.flush(); }捕获(IOE异常){ 返回-5; } 返回0; }否则 返回-2; }否则 返回-1; } /** *关闭已打开的外壳。 * *@return-1外壳未打开。
*-2设备没有根目录。
*-6运行exit命令时出现异常。
*-7等待进程停止时的中断异常。 */ 公共int closeShell(){ if(进程!=null){ 如果(设备驱动){ 试一试{ os.writeBytes(“退出”); }捕获(IOE1异常){ 返回-6; } 试一试{ process.waitFor(); }捕捉(中断异常e){ 返回-7; } process.destroy(); 进程=空; os=null; is=null; 返回0; }否则 返回-2; }否则 返回-1; } /** *检查Android设备是否为根设备。
*代码借用自:http://www *.stealthcopter.com/blog/2010/01/android-requesting-root-access-in *-你的应用程序/ * *@return true:设备已根目录。
*false:设备没有根目录。 */ 私有静态布尔checkRootStatus(){ 过程p; 试一试{ //预执行su以获取根权限 p=Runtime.getRuntime().exec(“su”); //尝试仅将文件写入根目录 DataOutputStream os=新的DataOutputStream(p.getOutputStream()); os.writeBytes(“echo\”我有根吗?\”>/system/sd/temporary.txt\n); //关闭航站楼 os.writeBytes(“退出”); os.flush(); 试一试{ p、 waitFor(); 如果(p.exitValue()!=255){ 返回true; }否则{ 返回false; } }捕捉(中断异常e){ 返回false; } }捕获(IOE异常){ 返回false; } } /** *@将DataInputStream返回到根shell。 */ 公共数据输入流getInputStream(){ 回报是; } /** *@将DataOutputStream返回到根shell。 */ 公共DataOutputStream getOutputStream(){ 返回操作系统; } /** *@如果外壳打开,则返回true。
*如果外壳未打开,则为false。 */ 公共布尔getProcessStatus(){ if(进程!=null) 返回true; 其他的 返回false; } }

我还发现,它给出了“08-22 19:05:19.701:I/System.out(275):e1java.io.IOException:breaked pipe”,它在“closeshell”中输入了try catch。在你的
R.id.start\u按钮和其他多个地方,

错误引用了
tcpDumpHandler.generateCommand()
,但您没有提供相应的代码。

非常感谢,我已经找到了导致错误的主要原因。在尝试获取根访问权限时,它在某一点上返回null,但我无法更正。我还有一个疑问,我们是否可以在eclipse中运行需要在Android Emulator上具有根权限的应用程序。?R指向gen包中的R.java文件,该文件与将在UI中显示的main.xml中定义的开始按钮有关。