我正在尝试制作具有登录功能的应用。用户输入用户名和密码,使用包含可接受的用户名和密码列表的数据库进行检查。如果登录成功,则将用户转移到其他活动。如果登录尝试失败,最终将会有代码减少attempt_counter并在尝试进行太多尝试时锁定登录按钮。在我为用户名实现代码之前,我决定测试它并查看是否正确检查了密码。当我点击我的按钮登录时,应用程序崩溃并说'#34;不幸的是,DrHelper已经停止了。"请帮助我理解为什么会这样。我是一名业余程序员,很乐意接受任何建设性的批评。
这是我的Login.java:
package com.example.drhelper;
/*
This class is started on application launch. It has an EditText for user name,
an EditText for password, a TextView that is used to show the word attempts on screen,
a counter that decreases every time there is a failed login attempt, and a login button.
*/
import android.support.v7.app.ActionBarActivity;
import java.io.IOException;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
//Declarations
@SuppressWarnings("deprecation")
public class Login extends ActionBarActivity {
private static EditText username;
private static EditText password;
private static TextView attempts;
private static Button login_button;
//This can be changed to increase or decrease amount of login attempts.
int attempt_counter = 5;
private DataBaseHelper mDbHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//This sets my layout to my activity_login.xml on create.
setContentView(R.layout.activity_login);
//This calls my main method so that it is running then the user starts the app.
LoginButton();
}
public void LoginButton () {
username = (EditText)findViewById(R.id.editText_Username_Field);
password = (EditText)findViewById(R.id.editText_Password_Field);
attempts = (TextView)findViewById(R.id.textView_Attempts_Count);
login_button = (Button)findViewById(R.id.Button_Login);
final String u = username.getText().toString();
final String p = password.getText().toString();
attempts.setText(Integer.toString(attempt_counter));
/*
* This is the handler for my button. When it is clicked I want the username
* and password to be checked with the id and password on the login database
* table.
*/
login_button.setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
/*This is where I want to do the actual check to see if the database
* information matches the information that was entered into the EditText.
*/
Cursor AllIDs = mDbHelper.getID();
AllIDs.moveToFirst();
while (!AllIDs.isAfterLast()) {
String id = AllIDs.getString(1);
if (id == u) {
Toast.makeText(Login.this, "Username and password are correct!",
Toast.LENGTH_SHORT).show();
//This redirects the user to the Search activity.
Intent intent = new Intent("com.example.drhelper.Search");
startActivity(intent);
} else {
if (AllIDs.isLast() && id != username.toString()) {
Toast.makeText(Login.this, "Username and password are incorrect.",
Toast.LENGTH_SHORT).show();
}
}
}
}
});
}}
这是我的AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.drhelper"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="23" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Base.Theme.AppCompat" >
<activity
android:name=".Login"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".Search"
android:label="@string/title_activity_search" >
<intent-filter>
<action android:name="com.example.drhelper.Search" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<activity
android:name=".Results"
android:label="@string/title_activity_results" >
</activity>
</application>
</manifest>
这是我的DataBaseHelper:
package com.example.drhelper;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
public class DataBaseHelper extends SQLiteOpenHelper {
//The Android's default system path of your application database.
private static String DB_PATH = "/data/data/com.example.drhelper/databases/";
private static String DB_NAME = "DrHelperDB";
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 = DB_PATH + 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) {
}
public Cursor getID() {
Cursor cursor = getReadableDatabase().rawQuery("SELECT _id FROM login", null);
return cursor;
}
public Cursor getPassword() {
Cursor cursor = getReadableDatabase().rawQuery("SELECT password FROM login", null);
return cursor;
}
}
这是我从启动应用程序到发生崩溃时的LogCat:
11-12 23:05:19.687: W/System(2119): ClassLoader referenced unknown path: /data/app/com.example.drhelper-1/lib/arm
11-12 23:05:19.785: D/OpenGLRenderer(2119): Use EGL_SWAP_BEHAVIOR_PRESERVED: true
11-12 23:05:19.862: I/Adreno-EGL(2119): <qeglDrvAPI_eglInitialize:379>: QUALCOMM Build: 09/02/15, 76f806e, Ibddc658e36
11-12 23:05:19.865: I/OpenGLRenderer(2119): Initialized EGL, version 1.4
11-12 23:05:28.063: D/AndroidRuntime(2119): Shutting down VM
11-12 23:05:28.065: E/AndroidRuntime(2119): FATAL EXCEPTION: main
11-12 23:05:28.065: E/AndroidRuntime(2119): Process: com.example.drhelper, PID: 2119
11-12 23:05:28.065: E/AndroidRuntime(2119): java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.Cursor com.example.drhelper.DataBaseHelper.getID()' on a null object reference
11-12 23:05:28.065: E/AndroidRuntime(2119): at com.example.drhelper.Login$1.onClick(Login.java:74)
11-12 23:05:28.065: E/AndroidRuntime(2119): at android.view.View.performClick(View.java:5198)
11-12 23:05:28.065: E/AndroidRuntime(2119): at android.view.View$PerformClick.run(View.java:21147)
11-12 23:05:28.065: E/AndroidRuntime(2119): at android.os.Handler.handleCallback(Handler.java:739)
11-12 23:05:28.065: E/AndroidRuntime(2119): at android.os.Handler.dispatchMessage(Handler.java:95)
11-12 23:05:28.065: E/AndroidRuntime(2119): at android.os.Looper.loop(Looper.java:148)
11-12 23:05:28.065: E/AndroidRuntime(2119): at android.app.ActivityThread.main(ActivityThread.java:5417)
11-12 23:05:28.065: E/AndroidRuntime(2119): at java.lang.reflect.Method.invoke(Native Method)
11-12 23:05:28.065: E/AndroidRuntime(2119): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
11-12 23:05:28.065: E/AndroidRuntime(2119): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
答案 0 :(得分:0)
mDbHelper
为null,您应该在调用其方法之前对其进行初始化:
mDbHelper = new DataBaseHelper(this);//this would go in onCreate()
Cursor AllIDs = mDbHelper.getID();