我无法打开SQLite数据库。它向我显示错误(代码14)无法打开数据库。我已经尝试了解决前面提到的问题的解决方案,但它没有帮助。我已经尝试检查DB文件是否存在,我还添加了读取和写入的权限但是,它仍然给了我这些错误。我只是想知道我做错了什么。请告诉我。
DBHelper.java
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
public class DBHelper extends SQLiteOpenHelper {
String DB_PATH;
private final static String DB_NAME = "db_order";
public final static int DB_VERSION = 1;
public static SQLiteDatabase db;
private final Context context;
private final String TABLE_NAME = "tbl_order";
private final String ID = "id";
private final String MENU_NAME = "Menu_name";
private final String QUANTITY = "Quantity";
private final String TOTAL_PRICE = "Total_price";
public DBHelper(Context context) {
super(context, DB_NAME, null, DB_VERSION);
this.context = context;
DB_PATH = Constant.DBPath;
}
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
SQLiteDatabase db_Read = null;
if (dbExist) {
//do nothing - database already exist
} else {
db_Read = this.getReadableDatabase();
db_Read.close();
try {
copyDataBase();
} catch (IOException e) {
throw new Error("Error copying database");
}
}
}
private boolean checkDataBase() {
File dbFile = new File(DB_PATH + DB_NAME);
return dbFile.exists();
}
private void copyDataBase() throws IOException {
InputStream myInput = context.getAssets().open(DB_NAME);
String outFileName = DB_PATH + DB_NAME;
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
public void openDataBase() throws SQLException {
SQLiteDatabase db = null;
try {
String myPath = DB_PATH + DB_NAME;
File file = new File(myPath);
if (file.exists() && !file.isDirectory()) {
db = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE);
}
if (db != null) {
db.close();
}
}catch (SQLException e)
{
//
}
if(db!= null)
{
db.close();
}
}
@Override
public void close() {
db.close();
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
}
/** this code is used to get all data from database */
public ArrayList<ArrayList<Object>> getAllData(){
ArrayList<ArrayList<Object>> dataArrays = new ArrayList<ArrayList<Object>>();
Cursor cursor = null;
try{
cursor = db.query(
TABLE_NAME,
new String[]{ID, MENU_NAME, QUANTITY, TOTAL_PRICE},
null,null, null, null, null);
cursor.moveToFirst();
if (!cursor.isAfterLast()){
do{
ArrayList<Object> dataList = new ArrayList<Object>();
dataList.add(cursor.getLong(0));
dataList.add(cursor.getString(1));
dataList.add(cursor.getString(2));
dataList.add(cursor.getString(3));
dataArrays.add(dataList);
}
while (cursor.moveToNext());
}
cursor.close();
}catch (SQLException e){
Log.e("DB Error", e.toString());
e.printStackTrace();
}
return dataArrays;
}
/** this code is used to get all data from database */
public boolean isDataExist(long id){
boolean exist = false;
Cursor cursor = null;
try{
cursor = db.query(
TABLE_NAME,
new String[]{ID},
ID +"="+id,
null, null, null, null);
if(cursor.getCount() > 0){
exist = true;
}
cursor.close();
}catch (SQLException e){
Log.e("DB Error", e.toString());
e.printStackTrace();
}
return exist;
}
/** this code is used to get all data from database */
public boolean isPreviousDataExist(){
boolean exist = false;
Cursor cursor;
try{
cursor = db.query(
TABLE_NAME,
new String[]{ID},
null,null, null, null, null);
if(cursor.getCount() > 0){
exist = true;
}
cursor.close();
}catch (SQLException e){
Log.e("DB Error", e.toString());
e.printStackTrace();
}
return exist;
}
public void addData(long id, String menu_name, int quantity, double total_price){
// this is a key value pair holder used by android's SQLite functions
ContentValues values = new ContentValues();
values.put(ID, id);
values.put(MENU_NAME, menu_name);
values.put(QUANTITY, quantity);
values.put(TOTAL_PRICE, total_price);
// ask the database object to insert the new data
try{db.insert(TABLE_NAME, null, values);}
catch(Exception e)
{
Log.e("DB ERROR", e.toString());
e.printStackTrace();
}
}
public void deleteData(long id){
// ask the database manager to delete the row of given id
try {db.delete(TABLE_NAME, ID + "=" + id, null);}
catch (Exception e)
{
Log.e("DB ERROR", e.toString());
e.printStackTrace();
}
}
public void deleteAllData(){
// ask the database manager to delete the row of given id
try {db.delete(TABLE_NAME, null, null);}
catch (Exception e)
{
Log.e("DB ERROR", e.toString());
e.printStackTrace();
}
}
public void updateData(long id, int quantity, double total_price){
// this is a key value pair holder used by android's SQLite functions
ContentValues values = new ContentValues();
values.put(QUANTITY, quantity);
values.put(TOTAL_PRICE, total_price);
// ask the database object to update the database row of given rowID
try {db.update(TABLE_NAME, values, ID + "=" + id, null);}
catch (Exception e)
{
Log.e("DB Error", e.toString());
e.printStackTrace();
}
}
}
MainActivity.java
package com.solodroid.frizzy;
import java.io.IOException;
import java.util.ArrayList;
import com.parse.Parse;
import com.parse.ParseAnalytics;
import com.parse.ParseInstallation;
import com.parse.PushService;
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.database.SQLException;
import android.graphics.drawable.ColorDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
@SuppressLint("NewApi")
public class MainActivity extends FragmentActivity {
private DrawerLayout mDrawerLayout;
private ListView mDrawerList;
private ActionBarDrawerToggle mDrawerToggle;
// nav drawer title
private CharSequence mDrawerTitle;
// used to store app title
private CharSequence mTitle;
// slide menu items
private String[] navMenuTitles;
private TypedArray navMenuIcons;
private ArrayList<NavDrawerItem> navDrawerItems;
private AdapterNavDrawerList adapter;
// declare dbhelper and adapter object
static DBHelper dbhelper;
AdapterMainMenu mma;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.nav_drawer_main);
// Parse push notification
Parse.initialize(this, getString(R.string.parse_application_id), getString(R.string.parse_client_key));
ParseAnalytics.trackAppOpened(getIntent());
PushService.setDefaultPushCallback(this, MainActivity.class);
ParseInstallation.getCurrentInstallation().saveInBackground();
mTitle = mDrawerTitle = getTitle();
// load slide menu items
navMenuTitles = getResources().getStringArray(R.array.nav_drawer_items);
// nav drawer icons from resources
navMenuIcons = getResources().obtainTypedArray(R.array.nav_drawer_icons);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mDrawerList = (ListView) findViewById(R.id.list_slidermenu);
mDrawerLayout.setDrawerShadow(R.drawable.navigation_drawer_shadow, GravityCompat.START);
navDrawerItems = new ArrayList<NavDrawerItem>();
// adding nav drawer items to array
navDrawerItems.add(new NavDrawerItem(navMenuTitles[0], navMenuIcons.getResourceId(0, -1)));
navDrawerItems.add(new NavDrawerItem(navMenuTitles[1], navMenuIcons.getResourceId(1, -1)));
navDrawerItems.add(new NavDrawerItem(navMenuTitles[2], navMenuIcons.getResourceId(2, -1)));
navDrawerItems.add(new NavDrawerItem(navMenuTitles[3], navMenuIcons.getResourceId(3, -1)));
navDrawerItems.add(new NavDrawerItem(navMenuTitles[4], navMenuIcons.getResourceId(4, -1)));
navDrawerItems.add(new NavDrawerItem(navMenuTitles[5], navMenuIcons.getResourceId(5, -1)));
navDrawerItems.add(new NavDrawerItem(navMenuTitles[6], navMenuIcons.getResourceId(6, -1)));
navDrawerItems.add(new NavDrawerItem(navMenuTitles[7], navMenuIcons.getResourceId(7, -1)));
navDrawerItems.add(new NavDrawerItem(navMenuTitles[8], navMenuIcons.getResourceId(8, -1)));
navDrawerItems.add(new NavDrawerItem(navMenuTitles[9], navMenuIcons.getResourceId(9, -1)));
// Recycle the typed array
navMenuIcons.recycle();
mDrawerList.setOnItemClickListener(new SlideMenuClickListener());
// setting the nav drawer list adapter
adapter = new AdapterNavDrawerList(getApplicationContext(), navDrawerItems);
mDrawerList.setAdapter(adapter);
// enabling action bar app icon and behaving it as toggle button
//getActionBar().setDisplayHomeAsUpEnabled(true);
//getActionBar().setHomeButtonEnabled(true);
ActionBar bar = getActionBar();
//bar.setBackgroundDrawable(new ColorDrawable(getResources().getColor(R.color.header)));
// get screen device width and height
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
// checking internet connection
if (!Constant.isNetworkAvailable(MainActivity.this)) {
Toast.makeText(MainActivity.this, getString(R.string.no_internet), Toast.LENGTH_SHORT).show();
}
mma = new AdapterMainMenu(this);
dbhelper = new DBHelper(this);
// create database
try {
dbhelper.createDataBase();
} catch (IOException ioe) {
throw new Error("Unable to create database");
}
// then, the database will be open to use
try {
dbhelper.getWritableDatabase();
dbhelper.openDataBase();
} catch (SQLException sqle) {
throw sqle;
}
// if user has already ordered food previously then show confirm dialog
if (dbhelper.isPreviousDataExist()) {
showAlertDialog();
}
mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer, // nav
// menu
// toggle
// icon
R.string.app_name, // nav drawer open - description for
// accessibility
R.string.app_name // nav drawer close - description for
// accessibility
) {
public void onDrawerClosed(View view) {
getActionBar().setTitle(mTitle);
// calling onPrepareOptionsMenu() to show action bar icons
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(mDrawerTitle);
// calling onPrepareOptionsMenu() to hide action bar icons
invalidateOptionsMenu();
}
};
mDrawerLayout.setDrawerListener(mDrawerToggle);
if (savedInstanceState == null) {
// on first time display view for first nav item
displayView(0);
}
}
// show confirm dialog to ask user to delete previous order or not
void showAlertDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.confirm);
builder.setMessage(getString(R.string.db_exist_alert));
builder.setCancelable(false);
builder.setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
// delete order data when yes button clicked
dbhelper.deleteAllData();
dbhelper.close();
}
});
builder.setNegativeButton(getString(R.string.no), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
// close dialog when no button clicked
dbhelper.close();
dialog.cancel();
}
});
AlertDialog alert = builder.create();
alert.show();
}
@Override
public void onBackPressed() {
// TODO Auto-generated method stub
dbhelper.deleteAllData();
dbhelper.close();
finish();
overridePendingTransition(R.anim.open_main, R.anim.close_next);
}
/**
* Slide menu item click listener
*/
private class SlideMenuClickListener implements ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// display view for selected nav drawer item
displayView(position);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// toggle nav drawer on selecting action bar app icon/title
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
// Handle action bar actions click
switch (item.getItemId()) {
case R.id.rate_app:
try {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + getPackageName())));
} catch (android.content.ActivityNotFoundException anfe) {
startActivity(new Intent(Intent.ACTION_VIEW,
Uri.parse("http://play.google.com/store/apps/details?id=" + getPackageName())));
}
return true;
case R.id.more_app:
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.more_apps))));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/*
* * Called when invalidateOptionsMenu() is triggered
*/
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
// if nav drawer is opened, hide the action items
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
menu.findItem(R.id.ic_menu).setVisible(!drawerOpen);
return super.onPrepareOptionsMenu(menu);
}
/**
* Diplaying fragment view for selected nav drawer list item
*/
private void displayView(int position) {
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 0:
fragment = new ActivityHome();
break;
case 1:
startActivity(new Intent(getApplicationContext(), ActivityCategoryList.class));
overridePendingTransition(R.anim.open_next, R.anim.close_next);
break;
case 2:
startActivity(new Intent(getApplicationContext(), ActivityCart.class));
overridePendingTransition(R.anim.open_next, R.anim.close_next);
break;
case 3:
startActivity(new Intent(getApplicationContext(), ActivityCheckout.class));
overridePendingTransition(R.anim.open_next, R.anim.close_next);
break;
case 4:
startActivity(new Intent(getApplicationContext(), ActivityProfile.class));
overridePendingTransition(R.anim.open_next, R.anim.close_next);
break;
case 5:
startActivity(new Intent(getApplicationContext(), ActivityInformation.class));
overridePendingTransition(R.anim.open_next, R.anim.close_next);
break;
case 6:
startActivity(new Intent(getApplicationContext(), ActivityAbout.class));
overridePendingTransition(R.anim.open_next, R.anim.close_next);
break;
case 7:
Intent sendInt = new Intent(Intent.ACTION_SEND);
sendInt.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.app_name));
sendInt.putExtra(Intent.EXTRA_TEXT, "E-Commerce Android App\n\"" + getString(R.string.app_name)
+ "\" \nhttps://play.google.com/store/apps/details?id=" + getPackageName());
sendInt.setType("text/plain");
startActivity(Intent.createChooser(sendInt, "Share"));
break;
case 8:
startActivity(new Intent(getApplicationContext(), ActivityContactUs.class));
overridePendingTransition(R.anim.open_next, R.anim.close_next);
break;
case 9:
dbhelper.deleteAllData();
dbhelper.close();
MainActivity.this.finish();
overridePendingTransition(R.anim.open_next, R.anim.close_next);
break;
default:
break;
}
if (fragment != null) {
android.app.FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.frame_container, fragment).commit();
// update selected item and title, then close the drawer
mDrawerList.setItemChecked(position, true);
mDrawerList.setSelection(position);
setTitle(navMenuTitles[position]);
mDrawerLayout.closeDrawer(mDrawerList);
} else {
// error in creating fragment
Log.e("MainActivity", "Error in creating fragment");
}
}
@Override
public void setTitle(CharSequence title) {
mTitle = title;
getActionBar().setTitle(mTitle);
}
/**
* When using the ActionBarDrawerToggle, you must call it during
* onPostCreate() and onConfigurationChanged()...
*/
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Pass any configuration change to the drawer toggls
mDrawerToggle.onConfigurationChanged(newConfig);
}
}
logcat的:
09-19 01:59:06.747 17250-17250/com.solodroid.frizzy E/SQLiteLog: (14) cannot open file at line 32456 of [bda77dda96]
09-19 01:59:06.747 17250-17250/com.solodroid.frizzy E/SQLiteLog: (14) os_unix.c:32456: (13) open(/data/data/com.solodroid.ecommerce/databases/db_order) -
09-19 01:59:06.748 17250-17250/com.solodroid.frizzy E/SQLiteDatabase: Failed to open database '/data/data/com.solodroid.ecommerce/databases/db_order'.
android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
at android.database.sqlite.SQLiteConnection.nativeOpen(Native Method)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:209)
at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:193)
at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:463)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:185)
at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:177)
at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:808)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:793)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:696)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:671)
at com.solodroid.frizzy.DBHelper.openDataBase(DBHelper.java:101)
at com.solodroid.frizzy.MainActivity.onCreate(MainActivity.java:138)
at android.app.Activity.performCreate(Activity.java:6662)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
09-19 01:59:06.748 17250-17250/com.solodroid.frizzy D/AndroidRuntime: Shutting down VM
09-19 01:59:06.748 17250-17250/com.solodroid.frizzy E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.solodroid.frizzy, PID: 17250
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.solodroid.frizzy/com.solodroid.frizzy.MainActivity}:
java.lang.NullPointerException: Attempt to invoke virtual method 'android.database.Cursor android.database.sqlite.SQLiteDatabase.query(java.lang.String, java.lang.String[],
java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.ma
in(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)
Caused by: java.lang.NullPointerException:
Attempt to invoke virtual method 'android.database.Cursor android.database.sqlite.SQLiteDatabase.query(java.lang.String, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String, java.lang.String, java.lang.String)'
on a null object reference
at com.solodroid.frizzy.DBHelper.isPreviousDataExist(DBHelper.java:205)
at com.solodroid.frizzy.MainActivity.onCreate(MainActivity.java:144)
at android.app.Activity.performCreate(Activity.java:6662)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2599)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2707)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1460) at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6077)
at java.lang.reflect.Method.invoke(Native Method)
答案 0 :(得分:2)
您永远不会打开db
方法中引用的DBHelper.isPreviousDataExist()
。它引用了全局的静态db
:
<强> DBHelper.java 强>
public static SQLiteDatabase db
您可以将其设置为实例变量并在构造函数中初始化(首选)或完全取消它并在SQLiteDatabase
方法中创建本地DBHelper.isPreviousDataExist()
,就像您在其他方法。
最后,您的代码存在各种问题,但public static
成员是一个很大的代码味道。 See this为什么。
答案 1 :(得分:0)
我不确定,但也许您的数据库需要 "*.db"
结尾。
private final static String DB_NAME = "db_order.db";
之后卸载旧应用并再次运行。