I try to write an app with a sqlite database. The Problem is, that my app in the emulator always “Unfortunately stopped”.
我尝试用sqlite数据库编写应用程序。问题是,我在模拟器中的应用总是“不幸停止”。
The stack trace says that this was happening because of a RuntimeException. This RuntimeException is caused by a SQLiteException.
堆栈跟踪说由于RuntimeException而发生这种情况。此RuntimeException是由SQLiteException引起的。
The full stack trace is:
完整的堆栈跟踪是:
--------- beginning of crash
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.passwordsavver.wahlfachprojekt, PID: 3336
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.passwordsavver.wahlfachprojekt/com.passwordsavver.wahlfachprojekt.MainScreen}: android.database.sqlite.SQLiteException: no such column: favourites (code 1): , while compiling: SELECT DISTINCT _id, websitename, username, password, notes, favourites FROM mainTable
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Caused by: android.database.sqlite.SQLiteException: no such column: favourites (code 1): , while compiling: SELECT DISTINCT _id, websitename, username, password, notes, favourites FROM mainTable
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1316)
at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1163)
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1034)
at com.passwordsavver.wahlfachprojekt.DBAdapter.getAllRows(DBAdapter.java:142)
at com.passwordsavver.wahlfachprojekt.MainScreen.populateButtons(MainScreen.java:52)
at com.passwordsavver.wahlfachprojekt.MainScreen.onCreate(MainScreen.java:33)
at android.app.Activity.performCreate(Activity.java:5990)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
at android.app.ActivityThread.access$800(ActivityThread.java:151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5254)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
Application terminated.
My Problem is, after looking multiples times over my code, I don’t know where exactly the Exception in my class occurs.
我的问题是,在查看我的代码的倍数之后,我不知道我的类中出现了什么异常。
My DBHealper Class looks like this:
我的DBHealper类看起来像这样:
package com.passwordsavver.wahlfachprojekt;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DBAdapter {
private static final String TAG = "DBAdapter";
// DB Fields
public static final String KEY_ROWID = "_id";
public static final int COL_ROWID = 0;
public static final String KEY_WEBSITENAME = "websitename";
public static final String KEY_USERNAME = "username";
public static final String KEY_PASSWORD = "password";
public static final String KEY_NOTES = "notes";
public static final String KEY_FAV = "favourites";
public static final int COL_WEBSITENAME = 1;
public static final int COL_USERNAME = 2;
public static final int COL_PASSWORD = 3;
public static final int COL_NOTES = 4;
public static final int COL_FAV = 5;
public static final String[] ALL_KEYS = new String[] {KEY_ROWID, KEY_WEBSITENAME, KEY_USERNAME, KEY_PASSWORD, KEY_NOTES, KEY_FAV};
public static final String DATABASE_NAME = "MyDb";
public static final String DATABASE_TABLE = "mainTable";
public static final int DATABASE_VERSION = 5;
private static final String DATABASE_CREATE_SQL =
"create table " + DATABASE_TABLE
+ " (" + KEY_ROWID + " integer primary key autoincrement, "
+ KEY_WEBSITENAME + " string not null, "
+ KEY_USERNAME + " string not null, "
+ KEY_PASSWORD + " string not null, "
+ KEY_NOTES + " string, "
+ KEY_FAV + "string"
+ ");";
// Context of application who uses us.
private final Context context;
private DatabaseHelper myDBHelper;
private SQLiteDatabase db;
public DBAdapter(Context ctx) {
this.context = ctx;
myDBHelper = new DatabaseHelper(context);
}
// Open the database connection.
public DBAdapter open() {
db = myDBHelper.getWritableDatabase();
return this;
}
// Close the database connection.
public void close() {
myDBHelper.close();
}
// Add a new set of values to the database.
public long insertRow(String websitename, String username, String password, String notes, String fav) {
// Create row's data:
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_WEBSITENAME, websitename);
initialValues.put(KEY_USERNAME, username);
initialValues.put(KEY_PASSWORD, password);
initialValues.put(KEY_NOTES, notes);
initialValues.put(KEY_FAV, fav);
// Insert it into the database.
return db.insert(DATABASE_TABLE, null, initialValues);
}
// Delete a row from the database, by rowId (primary key)
public boolean deleteRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
return db.delete(DATABASE_TABLE, where, null) != 0;
}
public void deleteAll() {
Cursor c = getAllRows();
long rowId = c.getColumnIndexOrThrow(KEY_ROWID);
if (c.moveToFirst()) {
do {
deleteRow(c.getLong((int) rowId));
} while (c.moveToNext());
}
c.close();
}
// Return all data in the database.
public Cursor getAllRows() {
String where = null;
Cursor c = db.query(true, DATABASE_TABLE, ALL_KEYS,
where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
// Get a specific row (by rowId)
public Cursor getRow(long rowId) {
String where = KEY_ROWID + "=" + rowId;
Cursor c = db.query(true, DATABASE_TABLE, ALL_KEYS,
where, null, null, null, null, null);
if (c != null) {
c.moveToFirst();
}
return c;
}
// Change an existing row to be equal to new data.
public boolean updateRow(long rowId, String websitename, String username, String password, String notes, String fav) {
String where = KEY_ROWID + "=" + rowId;
// Create row's data:
ContentValues newValues = new ContentValues();
newValues.put(KEY_WEBSITENAME, websitename);
newValues.put(KEY_USERNAME, username);
newValues.put(KEY_PASSWORD, password);
newValues.put(KEY_NOTES, notes);
newValues.put(KEY_FAV, fav);
// Insert it into the database.
return db.update(DATABASE_TABLE, newValues, where, null) != 0;
}
private static class DatabaseHelper extends SQLiteOpenHelper
{
DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase _db) {
_db.execSQL(DATABASE_CREATE_SQL);
}
@Override
public void onUpgrade(SQLiteDatabase _db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading application's database from version " + oldVersion
+ " to " + newVersion + ", which will destroy all old data!");
// Destroy old database:
_db.execSQL("DROP TABLE IF EXISTS " + DATABASE_TABLE);
// Recreate new database:
onCreate(_db);
}
}
}
The Class in where the exception occurs looks like this:
发生异常的类如下所示:
package com.passwordsavver.wahlfachprojekt;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Base64;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.database.Cursor;
import android.widget.TextView;
import java.security.MessageDigest;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class MainScreen extends AppCompatActivity {
DBAdapter myDb;
String passwordAES;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main_screen);
Intent intent = getIntent();
passwordAES = intent.getStringExtra("Password");
openDB();
populateButtons();
}
@Override
protected void onDestroy() {
super.onDestroy();
closeDB();
}
private void openDB() {
myDb = new DBAdapter(this);
myDb.open();
}
private void closeDB() {
myDb.close();
}
private void populateButtons() {
Cursor cursor = myDb.getAllRows();
int itemNumber = 0;
int i = 0;
if (cursor.moveToFirst()) {
do {
itemNumber++;
} while (cursor.moveToNext());
}
int ids[] = new int[itemNumber];
String aesWebsitenames[] = new String[itemNumber];
String websitenames[] = new String[itemNumber];
String aesFav[] = new String[itemNumber];
String fav[] = new String[itemNumber];
if (cursor.moveToFirst()) {
do {
ids[i] = cursor.getInt(DBAdapter.COL_ROWID);
aesWebsitenames[i] = cursor.getString(DBAdapter.COL_WEBSITENAME);
aesFav[i] = cursor.getString(DBAdapter.COL_FAV);
try
{
websitenames[i] = decrypt(passwordAES, aesWebsitenames[i]);
fav[i] = decrypt(passwordAES, aesFav[i]);
}
catch(Exception e)
{
}
i++;
} while (cursor.moveToNext());
}
i = 0;
int numCols = 1;
int numRows = itemNumber;
TableLayout table = (TableLayout)findViewById(R.id.tableForButtons);
// Favourites
int countFavourites = 0;
for(int row = 0; row < numRows; row++)
{
TableRow tableRow = new TableRow(this);
table.addView(tableRow);
if(fav[i] == "1") {
Button button = new Button(this);
button.setText(websitenames[i]);
// Make text not clip on small buttons
button.setPadding(0, 0, 0, 0);
tableRow.addView(button);
final int FINAL_ID = ids[i];
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), ViewScreen.class);
intent.putExtra("id", FINAL_ID);
intent.putExtra("Password", passwordAES);
startActivity(intent);
}
});
}
countFavourites++;
i++;
}
if(countFavourites == 0)
{
TextView txtNoFavourites = (TextView) findViewById(R.id.txtMainScreenNoFavourites);
txtNoFavourites.setVisibility(View.VISIBLE);
}
i = 0;
// Not Favourites
for(int row = 0; row < numRows; row++)
{
TableRow tableRow = new TableRow(this);
table.addView(tableRow);
for(int col = 0; col < numCols; col++)
{
if(fav[i] == "0") {
Button button = new Button(this);
button.setText(websitenames[i]);
// Make text not clip on small buttons
button.setPadding(0, 0, 0, 0);
tableRow.addView(button);
final int FINAL_ID = ids[i];
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(v.getContext(), ViewScreen.class);
intent.putExtra("id", FINAL_ID);
intent.putExtra("Password", passwordAES);
startActivity(intent);
}
});
}
}
i++;
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
Intent intent;
switch (id)
{
case R.id.action_offlinemode:
intent = new Intent(this, OptionScreen.class);
intent.putExtra("Password", passwordAES);
startActivity(intent);
break;
case R.id.action_allPasswords:
intent = new Intent(this, MainScreen.class);
intent.putExtra("Password", passwordAES);
startActivity(intent);
break;
case R.id.action_favorites:
break;
case R.id.action_addPassword:
intent = new Intent(this, AddScreen2.class);
intent.putExtra("Password", passwordAES);
startActivity(intent);
break;
case R.id.action_deleteAllPasswords:
myDb.deleteAll();
break;
case R.id.action_option:
intent = new Intent(this, OptionScreen.class);
intent.putExtra("Password", passwordAES);
startActivity(intent);
break;
case R.id.action_logout:
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
private String decrypt (String password, String data) throws Exception
{
SecretKeySpec key = generateKey(password);
Cipher c = Cipher.getInstance("AES");
c.init(Cipher.DECRYPT_MODE, key);
byte[] decodedValue = Base64.decode(data, Base64.DEFAULT);
byte[] decValue = c.doFinal(decodedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}
private SecretKeySpec generateKey(String password) throws Exception
{
final MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] bytes = password.getBytes("UTF-8");
digest.update(bytes, 0, bytes.length);
byte[] key = digest.digest();
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
return secretKeySpec;
}
}
Please can anybody show over my code and tell me where my error is?
请任何人都可以显示我的代码并告诉我我的错误在哪里?
4 个解决方案
#1
1
Change a line of your DATABASE_CREATE_SQL
string,
更改DATABASE_CREATE_SQL字符串的一行,
put a space + KEY_FAV + "string"
before string make it,
在字符串之前放一个空格+ KEY_FAV +“string”,
+ KEY_FAV + " string"
change public static final int DATABASE_VERSION = 5;
value and try again.
更改public static final int DATABASE_VERSION = 5;价值再试一次。
#2
1
private static final String DATABASE_CREATE_SQL =
"create table " + DATABASE_TABLE
+ " (" + KEY_ROWID + " integer primary key autoincrement, "
+ KEY_WEBSITENAME + " string not null, "
+ KEY_USERNAME + " string not null, "
+ KEY_PASSWORD + " string not null, "
+ KEY_NOTES + " string, "
+ KEY_FAV + "string"
+ ");";
rewrite as
private static final String DATABASE_CREATE_SQL =
"create table " + DATABASE_TABLE
+ " (" + KEY_ROWID + " integer primary key autoincrement, "
+ KEY_WEBSITENAME + " string not null, "
+ KEY_USERNAME + " string not null, "
+ KEY_PASSWORD + " string not null, "
+ KEY_NOTES + " string, "
+ KEY_FAV + " string "
+ ");";
as it seems only the space issue with KEY_FAV and String.
因为它似乎只是KEY_FAV和String的空间问题。
The only change required
唯一需要的改变
+ KEY_FAV + "string"
as
+ KEY_FAV + " string "
#3
1
+ KEY_FAV + "string"
This line treating string all together. Add a space before.
这条线一起处理字符串。之前添加一个空格。
It would be " string"
这将是“字符串”
#4
0
The exception is clearly saying that
例外显然是这样说的
Caused by: android.database.sqlite.SQLiteException: no such column: favourites (code 1): , while compiling: SELECT DISTINCT _id, websitename, username, password, notes, favourites FROM mainTable
引起:android.database.sqlite.SQLiteException:没有这样的列:收藏夹(代码1):,同时编译:SELECT DISTINCT _id,websitename,用户名,密码,备注,收藏夹FROM mainTable
So there is missing a space in front of + KEY_FAV + " string"
. That is why it is throwing an exception.
所以在+ KEY_FAV +“string”前面缺少一个空格。这就是它抛出异常的原因。
#1
1
Change a line of your DATABASE_CREATE_SQL
string,
更改DATABASE_CREATE_SQL字符串的一行,
put a space + KEY_FAV + "string"
before string make it,
在字符串之前放一个空格+ KEY_FAV +“string”,
+ KEY_FAV + " string"
change public static final int DATABASE_VERSION = 5;
value and try again.
更改public static final int DATABASE_VERSION = 5;价值再试一次。
#2
1
private static final String DATABASE_CREATE_SQL =
"create table " + DATABASE_TABLE
+ " (" + KEY_ROWID + " integer primary key autoincrement, "
+ KEY_WEBSITENAME + " string not null, "
+ KEY_USERNAME + " string not null, "
+ KEY_PASSWORD + " string not null, "
+ KEY_NOTES + " string, "
+ KEY_FAV + "string"
+ ");";
rewrite as
private static final String DATABASE_CREATE_SQL =
"create table " + DATABASE_TABLE
+ " (" + KEY_ROWID + " integer primary key autoincrement, "
+ KEY_WEBSITENAME + " string not null, "
+ KEY_USERNAME + " string not null, "
+ KEY_PASSWORD + " string not null, "
+ KEY_NOTES + " string, "
+ KEY_FAV + " string "
+ ");";
as it seems only the space issue with KEY_FAV and String.
因为它似乎只是KEY_FAV和String的空间问题。
The only change required
唯一需要的改变
+ KEY_FAV + "string"
as
+ KEY_FAV + " string "
#3
1
+ KEY_FAV + "string"
This line treating string all together. Add a space before.
这条线一起处理字符串。之前添加一个空格。
It would be " string"
这将是“字符串”
#4
0
The exception is clearly saying that
例外显然是这样说的
Caused by: android.database.sqlite.SQLiteException: no such column: favourites (code 1): , while compiling: SELECT DISTINCT _id, websitename, username, password, notes, favourites FROM mainTable
引起:android.database.sqlite.SQLiteException:没有这样的列:收藏夹(代码1):,同时编译:SELECT DISTINCT _id,websitename,用户名,密码,备注,收藏夹FROM mainTable
So there is missing a space in front of + KEY_FAV + " string"
. That is why it is throwing an exception.
所以在+ KEY_FAV +“string”前面缺少一个空格。这就是它抛出异常的原因。