我去其他活动时,我的应用程序不断崩溃

时间:2019-05-17 06:23:15

标签: java android android-sqlite

我正在尝试制作一个名为'moviesinfo'的应用程序,该应用程序中有一个登录页面,带有注册和忘记密码选项。当我尝试登录时,应用程序崩溃。我也不知道在注册页面上输入的数据是否存储在数据库中。

这是我的mainactivity.java

package com.example.moviesinfo;

import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    SQLiteDatabase db;
    SQLiteOpenHelper openHelper;
    private EditText user;
    private EditText password;
    private Button btn;
    private Button btn2;
    private Button forgot;
    Cursor cursor;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        forgot=findViewById(R.id.forgot);
        btn2=(Button) findViewById(R.id.signup);
        user= (EditText) findViewById(R.id.username);
        password = (EditText) findViewById(R.id.password);
        btn = (Button) findViewById(R.id.login);
        openHelper= new DatabaseHelper(this);
        db=openHelper.getReadableDatabase();

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String username1= user.getText().toString();
                String password1= password.getText().toString();

                cursor = db.rawQuery("SELECT * FROM " +DatabaseHelper.TABLENAME + " WHERE " + DatabaseHelper.COL2 + "=? AND " + DatabaseHelper.COL3+"=?", new String[]{username1,password1});

                if (cursor!=null){
                    if (cursor.getCount()>0){
                        cursor.moveToNext();
                        Intent intent = new Intent(MainActivity.this,listmenu.class);
                        startActivity(intent);
                        //Toast.makeText(getApplicationContext(),"Login Successful", Toast.LENGTH_SHORT).show();//
                    }else{
                        Toast.makeText(getApplicationContext(),"Error" , Toast.LENGTH_SHORT).show();
                    }
                }
            }
        });


        btn2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sign_up();
            }
        });

        forgot.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                forgot();
            }
        });
    }


    private void sign_up()
    {
        Intent intent= new Intent(MainActivity.this, signup.class);
        startActivity(intent);
    }

    private void forgot()
    {
        Intent intent= new Intent(MainActivity.this, forgot.class);
        startActivity(intent);
    }
}

这是signup.java

package com.example.moviesinfo;

import android.content.ContentValues;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import java.lang.String;
import java.util.ArrayList;

public class signup extends AppCompatActivity {
    SQLiteOpenHelper openHelper;
    DatabaseHelper db;
    SQLiteDatabase db1;
    public String uname = "";
    public String pwd = "";
    public ArrayList<String> cpwd = new ArrayList<String>();

    EditText e1, e2, e3;
    Button b1,b2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_signup);
        openHelper= new DatabaseHelper(this);
        e1 = (EditText) findViewById(R.id.username);
        e2 = (EditText) findViewById(R.id.password);
        e3 = (EditText) findViewById(R.id.cpwd);
        b1 = (Button) findViewById(R.id.save);
        b2 = (Button) findViewById(R.id.login2);


        b1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
            db1=openHelper.getWritableDatabase();
            String username =e1.getText().toString();
                String password =e2.getText().toString();
                String confirm_password =e3.getText().toString();
                insert_data(username,password,confirm_password);
            }
        });

        b2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(signup.this,MainActivity.class);
                startActivity(intent);
            }
        });


    }

    public void insert_data(String username, String password, String confirm_password)
    {
        ContentValues contentValues = new ContentValues();
        contentValues.put(DatabaseHelper.COL2, username);
        contentValues.put(DatabaseHelper.COL3, password);
        contentValues.put(DatabaseHelper.COL4, confirm_password);
        long id=db1.insert(DatabaseHelper.TABLENAME, null, contentValues);
    }
}

这是DatabseHelper.java

package com.example.moviesinfo;

import com.example.moviesinfo.signup;

import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DatabaseHelper extends SQLiteOpenHelper {

    public static final String DATABASE_NAME="userdetails.db";
    public static final String TABLENAME="user details";
    public static final String COL1="id";
    public static final String COL2="username";
    public static final String COL3="password";
    public static final String COL4="confirmpassword";



    public DatabaseHelper(Context context) {
        super(context, DATABASE_NAME, null,1);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("CREATE TABLE " + "TABLENAME(ID INTEGER PRIMARY KEY AUTOINCREMENT,USERNAME TEXT,PASSWORD TEXT,CONFIRMPASSWORD TEXT)");

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("DROP TABLE IF EXISTS " +TABLENAME);
        onCreate(db);
    }

}

我希望当我单击登录按钮时,它应该跳转到下一个活动,并检查数据库中的登录详细信息。

1 个答案:

答案 0 :(得分:1)

问题1

您将遇到的第一个问题是表名称用户详细信息带有空格。将提取用户作为标识符,但是SQL解析器不希望详细信息,它不是关键字或子句,因此不会出现语法错误按照以下内容可以在日志中找到:-

5-19 14:09:14.335 26779-26779/s.e.so56180693anotheractivity E/AndroidRuntime: FATAL EXCEPTION: main
    Process: s.e.so56180693anotheractivity, PID: 26779
    java.lang.RuntimeException: Unable to start activity ComponentInfo{s.e.so56180693anotheractivity/s.e.so56180693anotheractivity.MainActivity}: android.database.sqlite.SQLiteException: near "details": syntax error (code 1 SQLITE_ERROR): , while compiling: CREATE TABLE IF NOT EXISTS user details(_id INTEGER PRIMARY KEY,username TEXT,password TEXT, confirmpassword TEXT)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
        at android.os.Handler.dispatchMessage(Handler.java:106)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: android.database.sqlite.SQLiteException: near "details": syntax error (code 1 SQLITE_ERROR): , while compiling: CREATE TABLE IF NOT EXISTS user details(_id INTEGER PRIMARY KEY,username TEXT,password TEXT, confirmpassword TEXT)
        at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
        at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:903)
        at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:514)
        at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
        at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
        at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
        at android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1769)
        at android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1698)
        at s.e.so56180693anotheractivity.DatabaseHelper.onCreate(DatabaseHelper.java:33)
        at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:393)
        at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:322)
        at s.e.so56180693anotheractivity.MainActivity.onCreate(MainActivity.java:35)
        at android.app.Activity.performCreate(Activity.java:7136)

如果标识符按照:-

的形式包含在特定字符中,则标识符通常可以使用不可接受的字符(例如空格),以数字开头

如果要使用关键字作为名称,则需要引用它。在SQLite中有四种引用关键字的方法:

  
      
  • “关键字”单引号中的关键字是字符串文字。
  •   
  • “关键字”用双引号引起来的关键字是一个标识符。
  •   
  • [关键字]用方括号括起来的关键字是一个标识符。这不是   标准SQL。 MS Access和SQL使用此报价机制   服务器,并包含在SQLite中以实现兼容性。
  •   
  • 关键字用重音符号(ASCII码96)括起来的关键字是一个标识符。   这不是标准的SQL。这种引用机制由MySQL使用,并且包含在SQLite中以实现兼容性。
  •   

例如你可能有:-

public static final String TABLENAME="user details"; //<<<<<<<<<< cannot have spaces in a name unless enclosed
//!!!!NOTE!!!! ONLY 1 of the below would be allowed
public static final String TABLENAME="`user details`"; //<<<<<<<<<< e.g (with space)
public static final String TABLENAME= "[user details]";
public static final String TABLENAME = "\"user details\""; 
public static final String TABLENAME = "'user details'";
public static final String TABLENAME="user_details"; //<<<<<<<<<< changed to this for testing.
  • 阅读评论

解决问题1

public static final String TABLENAME="user details";

已更改为:-

public static final String TABLENAME="user_details";

该应用已卸载并重新运行。


问题2

下一个问题是,用于创建表的SQL不会创建根据常量TABLENAME(应用修订1后的 user_details )具有的值命名的表。该表名为TABLENAME,因为TABLENAME用引号引起来。

这会导致异常:-

2019-05-19 13:56:15.118 26443-26443/s.e.so56180693anotheractivity E/SQLiteLog: (1) no such table: user_details

解决问题2

以下是建议设置CREATE TABLE sql的方式:-

    //Uses the identifiers (names) as per the variables
    db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLENAME + "(" +
            COL1 + " INTEGER PRIMARY KEY," + // NO NEED FOR INEFFICIENT AUTOINCREMENT
            COL2 + " TEXT  UNIQUE," + //ADDED UNIQUE so that user names are not duplicated
            COL3 + " TEXT, " +
            COL4 + " TEXT" +
            ")"
    );
  • 这是用于名称的常量。
  • 重要,因为这是对数据库架构的更改,并且该数据库存在,因此您必须删除数据库,以便DatabaseHelper onCreate 方法将运行。
  • 已添加关键字UNIQUE,否则可以多次添加同一用户

问题

  

我也不知道在注册页面上输入的数据是否正在   是否存储在数据库中。

要使您知道或不知道,现在您应该知道在日志中查找,然后按如下所示修改insert_data方法将使您能够查看是否正在存储数据。

public long insert_data(String username, String password, String confirm_password) // Signature changed to return long (id)
{
    ContentValues contentValues = new ContentValues();
    contentValues.put(DatabaseHelper.COL2, username);
    contentValues.put(DatabaseHelper.COL3, password);
    contentValues.put(DatabaseHelper.COL4, confirm_password);
    long id=db1.insert(DatabaseHelper.TABLENAME, null, contentValues);
    //TODO REMOVE LOGGING BEFORE PUBLISHING THE APP
    if (id > 0) {
        Log.d("INSERTUSERDETAILSROW","The row was successfully inserted into the " + DatabaseHelper.TABLENAME + " table.");
    } else {
        Log.d("INSERTUSERDETAILSROW","Row not inserted!!!!!!!!!!");
    }
    return id; // Can be useful to have access to the id that was generated. Note method signature change 
}

示例输出:-

在日志中:-

D/INSERTUSERDETAILSROW: The row was successfully inserted into the user_details table.

问题4

如果密码和Confirm_Password值不匹配,则该行仍会添加,即Confirm_Password值无用。

解决问题4

仅在密码和Confirm_Password值匹配时才添加检查以添加数据。如果没有,则发出吐司。

    b1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            db1=openHelper.getWritableDatabase();
            String username =e1.getText().toString();
            String password =e2.getText().toString();
            String confirm_password =e3.getText().toString();
            if (password.equals(confirm_password)) {
                insert_data(username, password, confirm_password);
            } else {
                Toast.makeText(v.getContext(),"Password and Confirm Password do not match. Data not added.",Toast.LENGTH_LONG).show();
            }
        }
    });

问题5

尽管这似乎不是问题,但是当您要从某个活动返回时,不应该开始该活动,因为这将破坏初始活动并启动另一个活动。正确的方法是完成活动,然后它将返回到实际的活动开始。

解决问题5

    b2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            //Intent intent = new Intent(signup.this,MainActivity.class);
            //startActivity(intent);
            finish(); //<<<<<<<<<< Proper way to return
        }
    });

完成

就是这样。就登录和注册而言,该应用程序现在应该相对功能正常。