-1

私は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を実行すると、ログに次のエラーが表示されます。私は提案された多くの解決策を試しましたが、それでも解決策を得ることができませんでした。

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を返しています。さらに3つのクラスにループバックします。

 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:壊れたパイプ」を表示していることもわかりました。「closeshell」でtrycatchに入ります。

4

1 に答える 1

0

RあなたR.id.start_buttonと他の複数の場所には何がありますか?
エラーは参照してtcpDumpHandler.generateCommand()いますが、コードを提供していません。

于 2012-08-22T08:10:10.667 に答える