0

我正在开发 Android,我使用教程中的代码来编写我的应用程序,我的应用程序是一个聊天机器人,它接受用户的输入(字符串)并给出合适的答案:例如用户输入“hi”,聊天机器人回答“hi there”

我的应用程序运行良好,但我尝试添加一个方法来处理用户在输入中再次输入最后一个 inputSentence,我只是添加了简单的 if() 来检查重复,但现在问题面临新问题。当用户和聊天机器人互相聊天,然后用户按下手机上的返回按钮,然后返回应用程序并尝试再次聊天,当用户在输入中输入内容时,当聊天机器人尝试从数据库中找到合适的答案时,程序因“强制”而崩溃停止”错误,

我刚刚在此处添加了代码并使新方法 BOLD:它有点长...

package com.color.speechbubble;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;

import android.app.ListActivity;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.hardware.Camera.Size;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.InputFilter.LengthFilter;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

/**
 * MessageActivity is a main Activity to show a ListView containing Message
 * items
 * 
 * @author Adil Soomro
 * @author Mehrdad4all
 * 
 */
public class MessageActivity extends ListActivity {
    /** Called when the activity is first created. */

    // Variables,Constants and Objects $$$$$$$$$$$$$$$$$$
    // DATABASE VARIABLES
    private String USER = "user";
    private String SHOMPET = "shompet";

    Utility utility_obj = new Utility();

    private static String newMessage = "null in sql";
    ir.mehrdadsalimi.ShompetBot.DataBaseHelper myDbHelper = new ir.mehrdadsalimi.ShompetBot.DataBaseHelper(
            this);

    ArrayList<Message> messages;
    AwesomeAdapter adapter;
    EditText text;
    static Random rand = new Random();
    static String sender;

    // to save USER chat Log and check repeatation
    ArrayList<String> userChatLogArray = new ArrayList<String>();
    // to check whether this is user's first input
    public static Boolean firstInput = true;

    // $$$$$$$$$$$$$$$$$$$
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        text = (EditText) this.findViewById(R.id.text);

        sender = utility_obj.sender[rand.nextInt(utility_obj.sender.length - 1)];
        this.setTitle("ShompetBot(" + sender + ")");
        messages = new ArrayList<Message>();

        // here we choose between two method, user starts chat or ShompetBot
        // starts it!
        // we use random method to choose,
        // it makes ShompetBot more Real!
        // we have 7 condition 4 for user starts which is nothing
        // and 4 which ShompetBot choose one of this sentences randomly
        switch (rand.nextInt(7)) {
        case 0:
            messages.add(new Message("Welcome here!", false));

            break;
        case 1:
            messages.add(new Message("user, how are you doing today??!", false));
            break;
        case 2:
            messages.add(new Message("What's up?", false));
            break;
        case 3:
            messages.add(new Message("Hey, How can i help you?", false));
            break;

        default:
            break;
        }

        // messages.add(new Message("Hello", false));
        // messages.add(new Message("Hi!", true));
        // messages.add(new Message("Wassup??", false));
        // messages.add(new
        // Message("nothing much, working on speech bubbles.",true));
        // messages.add(new Message("you say!", true));
        // messages.add(new Message("oh thats great. how are you showing them",
        // false));

        adapter = new AwesomeAdapter(this, messages);
        setListAdapter(adapter);

        // addNewMessage(new
        // Message("mmm, well, using 9 patches png to show them.", true));

    }

    public void sendMessage(View v) {
        String newMessage = text.getText().toString().trim();
        userChatLogArray.add(newMessage);
        this.newMessage = newMessage;
        if (newMessage.length() > 0) {
            text.setText("");
            addNewMessage(new Message(newMessage, true));
            new SendMessage().execute();
        }
    }

    private class SendMessage extends AsyncTask<Void, String, String> {
        @Override
        protected String doInBackground(Void... params) {
            try {
                Thread.sleep(2000); // simulate a network call
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            this.publishProgress(String.format("%s started writing", sender));
            try {
                Thread.sleep(2000); // simulate a network call
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            this.publishProgress(String.format("%s has entered text", sender));
            try {
                Thread.sleep(3000);// simulate a network call
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            // **************************************************
            try { // here
                myDbHelper.createDataBase(); // we
            } catch (IOException ioe) { // create
                throw new Error("Unable to create database"); // and
            } // open
            try { // DB
                myDbHelper.openDataBase(); //
            } catch (SQLException sqle) { //
                throw sqle; //
            } //
            SQLiteDatabase db = myDbHelper.getReadableDatabase();// make an
            // readable
            // database
            // from
            // existing
            // one
            String shompetAnswer = "";// shompet final answer
            **if (checkRepeatation(firstInput)) {
                shompetAnswer = " rep test";
            } else {**
                // here we first edit userInput to make it easier to search
                // for suitable answer in DB
                editEndOfNewMessage();

                Cursor cursor = db.rawQuery(
                        "SELECT shompet FROM exact_sentence WHERE " + USER
                                + " = '" + newMessage + "'", null);// query
                                                                    // exact_sentence
                                                                    // table
                ArrayList<String> stringArrayList = new ArrayList<String>();
                String shompetAnswersSet[] = null;
                String tempString = "";
                // check if got answer from exact_sentence table(first engine)
                if (cursor.moveToFirst()) {
                    do {
                        // add to arraylist
                        tempString = cursor.getString(cursor
                                .getColumnIndex("shompet"));
                        stringArrayList.add(tempString);

                    } while (cursor.moveToNext());
                    shompetAnswersSet = stringArrayList
                            .toArray(new String[stringArrayList.size()]);
                    shompetAnswer = shompetAnswersSet[rand
                            .nextInt(shompetAnswersSet.length)];
                    cursor.close();
                }
                // Here we will use second engine to search DB with 40% accuracy
                else {

                    cursor = db.rawQuery("SELECT shompet FROM sentence "
                            + "WHERE LENGTH(user) = ( "
                            + " SELECT MAX(LENGTH(user)) FROM sentence "
                            + "  WHERE ? LIKE '%' || " + USER + " || '%' "
                            + ") AND ? LIKE '%' || " + USER + " || '%' ",
                            new String[] { newMessage, newMessage });

                    // check if find answer from second engine
                    if (cursor.moveToFirst()) {
                        do {
                            // add to arraylist
                            tempString = cursor.getString(cursor
                                    .getColumnIndex("shompet"));
                            stringArrayList.add(tempString);

                        } while (cursor.moveToNext());
                        shompetAnswersSet = stringArrayList
                                .toArray(new String[stringArrayList.size()]);
                        shompetAnswer = shompetAnswersSet[rand
                                .nextInt(shompetAnswersSet.length)];
                    }
                    cursor.close();
                }
                // ***************************************************

            }
            // to prevent from onPause and onResume errors
            myDbHelper.close();
            return shompetAnswer;
        }

        @Override
        public void onProgressUpdate(String... v) {

            if (messages.get(messages.size() - 1).isStatusMessage)// check
                                                                    // wether we
                                                                    // have
                                                                    // already
                                                                    // added a
                                                                    // status
                                                                    // message
            {
                messages.get(messages.size() - 1).setMessage(v[0]); // update
                                                                    // the
                                                                    // status
                                                                    // for that
                adapter.notifyDataSetChanged();
                getListView().setSelection(messages.size() - 1);
            } else {
                addNewMessage(new Message(true, v[0])); // add new message, if
                                                        // there I'm fine,
                                                        // thanks, what about
                                                        // you?is no existing
                                                        // status message
            }
        }

        @Override
        protected void onPostExecute(String text) {
            if (messages.get(messages.size() - 1).isStatusMessage)// check if
                                                                    // there is
                                                                    // any
                                                                    // status
                                                                    // message,
                                                                    // now
                                                                    // remove
                                                                    // it.
            {
                messages.remove(messages.size() - 1);
            }

            addNewMessage(new Message(text, false)); // add the original message
                                                        // from server.
        }

    }

    void addNewMessage(Message m) {
        messages.add(m);
        adapter.notifyDataSetChanged();
        getListView().setSelection(messages.size() - 1);
    }

    void editEndOfNewMessage() {

        // here we edit userinput from useless sign at the end of the statement
        while (newMessage.charAt(newMessage.length() - 1) == '!'
                || newMessage.charAt(newMessage.length() - 1) == '.'
                || newMessage.charAt(newMessage.length() - 1) == '?') {
            newMessage = newMessage.substring(0, newMessage.length() - 1);
        } //
        newMessage = newMessage.trim();// delete whitespace from end of
                                        // statement
        newMessage = newMessage.toLowerCase();// clear!
    }

    **public Boolean checkRepeatation(Boolean input)// check equality of user
    // //
    // input with last user
    { // input for repeatation
        if (input) {
            firstInput = false;
            return false;
        } else {
            String userChatLog[] = userChatLogArray
                    .toArray(new String[userChatLogArray.size()]);
            if (userChatLog[userChatLog.length - 2].equals(newMessage)) {
                return true;
            }
            return false;
        }
    }**

}

和扩展 SQLiteOpenHelper 类的类:

package ir.mehrdadsalimi.ShompetBot;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment;

public class DataBaseHelper extends SQLiteOpenHelper{

    //The Android's default system path of your application database.
    private static String DB_PATH = "/data/data/com.color.speechbubble/databases/";

    private static String DB_NAME = "ShompetBot_DBTest";

    private SQLiteDatabase myDataBase; 

    private final Context myContext;

    /**
     * Constructor
     * Takes and keeps a reference of the passed context in order to access to the application assets and resources.
     * @param context
     */
    public DataBaseHelper(Context context) {

        super(context, DB_NAME, null, 1);
        this.myContext = context;
    }   

  /**
     * Creates a empty database on the system and rewrites it with your own database.
     * */
    public void createDataBase() throws IOException{

        boolean dbExist = checkDataBase();

        if(dbExist){
            //do nothing - database already exist
        }else{

            //By calling this method and empty database will be created into the default system path
               //of your application so we are gonna be able to overwrite that database with our database.
            this.getReadableDatabase();

            try {

                copyDataBase();

            } catch (IOException e) {

                throw new Error("Error copying database");

            }
        }

    }

    /**
     * Check if the database already exist to avoid re-copying the file each time you open the application.
     * @return true if it exists, false if it doesn't
     */
    private boolean checkDataBase(){

        SQLiteDatabase checkDB = null;

        try{
            String myPath = Environment.getExternalStorageDirectory() + "/" + DB_NAME;
            checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

        }catch(SQLiteException e){

            //database does't exist yet.


        }

        if(checkDB != null){

            checkDB.close();

        }

        return checkDB != null ? true : false;
    }

    /**
     * Copies your database from your local assets-folder to the just created empty database in the
     * system folder, from where it can be accessed and handled.
     * This is done by transfering bytestream.
     * */
    private void copyDataBase() throws IOException{

        //Open your local db as the input stream
        InputStream myInput = myContext.getAssets().open(DB_NAME);

        // Path to the just created empty db
        String outFileName = DB_PATH + DB_NAME;

        //Open the empty db as the output stream
        OutputStream myOutput = new FileOutputStream(outFileName);

        //transfer bytes from the inputfile to the outputfile
        byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer))>0){
            myOutput.write(buffer, 0, length);
        }

        //Close the streams
        myOutput.flush();
        myOutput.close();
        myInput.close();

    }

    public void openDataBase() throws SQLException{

        //Open the database
        String myPath = DB_PATH + DB_NAME;
        myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);

    }

    @Override
    public synchronized void close() {

            if(myDataBase != null)
                myDataBase.close();

            super.close();

    }

    @Override
    public void onCreate(SQLiteDatabase db) {

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }

        // Add your public helper methods to access and get content from the database.
       // You could return cursors by doing "return myDataBase.query(....)" so it'd be easy
       // to you to create adapters for your views.

}
4

1 回答 1

0

一天后我终于明白了:问题是因为这条线:

public static Boolean firstInput = true;

我刚刚将此行添加到 onCtreate 方法的第一个:

firstInput = true;

在程序中,我们在用户第一次输入后创建这个变量false,然后当用户按下返回按钮时它仍然是假的,程序运行到这个条件并执行什么if(),因为这行是不正确的:

if (userChatLog[userChatLog.length - 2].equals(newMessage))

长度为1,索引为-1!

于 2013-08-25T20:00:20.977 回答