我的应用程序正在崩溃我正在尝试读取预构建的数据库并从那里加载列但是目前,它在启动时崩溃并认为它与我的DHhandler有关,以及它如何设置GetJobList但我很新一般的Android和编程所以我不完全确定
DBhandler在
下面package com.example.joelg.clapp;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
/**
* Created by joelg on 22/10/2017.
*/
public class IntDataBaseHelper extends SQLiteOpenHelper{
private static String DB_PATH ="C:\\Users\\joelg\\AndroidStudioProjects\\CLAPP\\app\\build\\intermediates\\assets";
private static String DB_NAME = "JobList";
private static String DB_COLUMN = " JobNM";
private static String DB_TABLE = "Job";
private static String DB_JOB_IS_DONE = "JobComplete";
private SQLiteDatabase JobListDatabase;
private final Context jobContext;
/**
* constructor t
*/
public IntDataBaseHelper (Context context) {
super (context, DB_NAME,null, 1);
this.jobContext = context;
}
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
if(dbExist){
//do nothing database already exists
}else{
// calling this method will create an empty database
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e){
throw new Error("Error copying database");
}
}
}
// check if database exists to avoid recopying it
private boolean checkDataBase (){
SQLiteDatabase checkDB = null;
try{
String JobListPath = DB_PATH + DB_NAME;
checkDB = SQLiteDatabase.openDatabase(JobListPath, null,
SQLiteDatabase.OPEN_READONLY);
}catch(SQLiteException e){
// database doesnt exist yet
}
if(checkDB !=null){
checkDB.close();
}
return checkDB !=null ? true : false;
}
// copies db from local assets file, were it can be accessed and handled
private void copyDataBase() throws IOException {
// open local database as the input stream
InputStream JobInput = jobContext.getAssets().open(DB_NAME);
// path to the just created empty database
String OutFileName = DB_PATH + DB_NAME;
// open the empty db as the output stra,
OutputStream myOutPut = new FileOutputStream(OutFileName);
// transfer bytes from the input file to the output file
byte[] buffer = new byte[1024];
int length;
while ((length = JobInput.read(buffer))>0){
myOutPut.write(buffer,0,length);
}
myOutPut.flush();
myOutPut.close();
JobInput.close();
}
public void openDataBase() throws SQLiteException {
// open the database
String JobListPath = DB_PATH+DB_NAME;
JobListDatabase =
SQLiteDatabase.openDatabase(JobListPath,null,SQLiteDatabase.OPEN_READONLY);
}
// Getting Job Count
public ArrayList<String> getJobList() {
ArrayList<String> JobList = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(DB_TABLE,new String[]
{DB_COLUMN},null,null,null,null,null);
while(cursor.moveToNext()){
int index = cursor.getColumnIndex(DB_COLUMN);
JobList.add(cursor.getString(index));
}
cursor.close();
db.close();
return JobList;
}
@Override
public synchronized void close(){
if(JobListDatabase !=null){
JobListDatabase.close();
super.close();
}
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
这是logcat输出
10-24 03:07:05.081 11072-11072/com.example.joelg.clapp E/SQLiteLog: (1) no such table: job
10-24 03:07:05.084 11072-11072/com.example.joelg.clapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.joelg.clapp, PID: 11072
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.joelg.clapp/com.example.joelg.clapp.MainActivity}: android.database.sqlite.SQLiteException: no such table: job (code 1): , while compiling: SELECT jobNM FROM job
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: android.database.sqlite.SQLiteException: no such table: job (code 1): , while compiling: SELECT jobNM FROM job
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:1318)
at android.database.sqlite.SQLiteDatabase.queryWithFactory(SQLiteDatabase.java:1165)
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1036)
at android.database.sqlite.SQLiteDatabase.query(SQLiteDatabase.java:1204)
at
com.example.joelg.clapp.IntDataBaseHelper.getJobList(IntDataBaseHelper.java:128)
at
com.example.joelg.clapp.MainActivity.onCreate(MainActivity.java:46)
at
android.app.Activity.performCreate(Activity.java:6975)
at
android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at
android.app.ActivityThread.-wrap11(Unknown Source:0)
at
android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at
android.os.Handler.dispatchMessage(Handler.java:105)
at
android.os.Looper.loop(Looper.java:164)
at
android.app.ActivityThread.main(ActivityThread.java:6541)
at
java.lang.reflect.Method.invoke(Native Method)
at
com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
这是作业db文件的位置
[ 10-24 05:22:39.920
1508:
2079 D/ ]
SurfaceInterface::setAsyncMode: set async mode 1
10-24 05:22:39.925 1611-1631/? E/ResourcesManager: failed to add asset path
/data/app/com.example.joelg.clapp-0JSJFIAy0bMCNOuIEgUs3g==/base.apk
10-24 05:22:39.925 1611-1631/? E/ResourcesManager: failed to add asset path
/data/app/com.example.joelg.clapp-0JSJFIAy0bMCNOuIEgUs3g==/base.apk
10-24 05:22:39.925 1611-1631/? E/ResourcesManager: failed to add asset path
/data/app/com.example.joelg.clapp-0JSJFIAy0bMCNOuIEgUs3g==/base.apk
10-24 05:22:39.938 1611-1631/? E/ResourcesManager: failed to add asset path
/data/app/com.example.joelg.clapp-0JSJFIAy0bMCNOuIEgUs3g==/base.apk
10-24 05:22:40.523 1611-1628/? E/ResourcesManager: failed to add asset path
/data/app/com.example.joelg.clapp-0JSJFIAy0bMCNOuIEgUs3g==/base.apk
10-24 05:22:40.523 1611-1628/? E/ResourcesManager: failed to add asset path
/data/app/com.example.joelg.clapp-0JSJFIAy0bMCNOuIEgUs3g==/base.apk
10-24 05:22:42.973 1508-1598/? E/TaskPersister: File error accessing recents
directory (directory doesn't exist?).
10-24 05:22:53.636 1508-1598/? E/TaskPersister: File error accessing recents
directory (directory doesn't exist?).
10-24 05:22:54.924 1508-1521/? E/memtrack: Couldn't load memtrack module
10-24 05:23:26.999 1508-1521/? E/memtrack: Couldn't load memtrack module
10-24 05:23:27.010 1508-1521/? E/memtrack: Couldn't load memtrack module
10-24 05:23:39.285 1508-1525/? E/BatteryStatsService: modem info is invalid:
`ModemActivityInfo{ mTimestamp=0 mSleepTimeMs=0 mIdleTimeMs=0 mTxTimeMs[]=
[0, 0, 0, 0, 0] mRxTimeMs=0 mEnergyUsed=0}`
10-24 05:23:43.109 1508-1521/? E/memtrack: Couldn't load memtrack module
10-24 05:24:00.005 1508-1521/? E/memtrack: Couldn't load memtrack module
最新的logcat输出
10-24 12:01:30.319 2669-2669/? E/SQLiteLog: (14) cannot open file at line 35648 of [036ebf729e]
10-24 12:01:30.319 2669-2669/? E/SQLiteLog: (14) os_unix.c:35648: (2) open(/data/user/0/com.example.joelg.clapp/databases/JobList) -
10-24 12:01:30.320 2669-2669/? E/SQLiteDatabase: Failed to open database '/data/user/0/com.example.joelg.clapp/databases/JobList'.
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.example.joelg.clapp.CopyDBFromAssets.checkDataBase(CopyDBFromAssets.java:94)
at com.example.joelg.clapp.CopyDBFromAssets.createDataBase(CopyDBFromAssets.java:25)
at com.example.joelg.clapp.MainActivity.onCreate(MainActivity.java:25)
at android.app.Activity.performCreate(Activity.java:6975)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
10-24 12:01:30.322 2669-2669/? E/CHECKASSET: Asset JobListcould not be found. Assets that exists are:- CleanIngListTemplate.db.sqbpro JobList.db JobList.db.sqbpro JobList.sqbpro images webkit
10-24 12:01:30.322 2669-2669/? E/CREATEDB: Error getting asset JobList
10-24 12:01:30.325 2669-2669/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.joelg.clapp, PID: 2669
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.joelg.clapp/com.example.joelg.clapp.MainActivity}: java.lang.RuntimeException: No Usable Database exists or was copied from the assets.
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.RuntimeException: No Usable Database exists or was copied from the assets.
at com.example.joelg.clapp.MainActivity.onCreate(MainActivity.java:34)
at android.app.Activity.performCreate(Activity.java:6975)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
答案 0 :(得分:1)
根据评论回答问题。
1)复制到assets文件夹中的文件与数据库具有完全相同的名称至关重要。因此,如果要将数据库称为 JobList ,那么它必须是assets文件夹中的文件名。
2)在我接触代码之前,先解释一下混乱。如果事情不完全正确的话,这是双重打击。无论数据库是什么情况都是如此。首先,如果数据库不存在,this.getReadableDatabase();
的{{1}}方法中的单行createDatabase
将会运行。但是,即使你没有运行(例如注释掉),因为你已经创建了IntDataBaseHelper
类的实例,那么任何打开数据库的尝试也会尝试创建它。在IntDataBaseHelper
方法中没有代码的情况下,结果将是一个空数据库,实际上没有表*(表sqlite_master和android_metadata将存在,但它们是系统类型表)**
因此我决定将数据库的创建/副本从DBHelper中分离出来,并希望使代码发出更具描述性的消息。
所以我建议您使用的代码。
首先有一个我称之为 onCreate
的新课程。这基本上是来自CopyDBFromAssets
的代码,但是以更长的方式编写。有一种新的方法IntDatabaseHelper
,根据它的名称应该是不言而喻的重新使用它。
调用MainActivity有点不同。而不是获得checkAssetExists
的实例。代码最初调用新IntDatabaseHelper
类中的createDatabase
方法,该方法返回一个布尔值。
如果 true ,则会创建CopyDBFromAssets
的实例并且一切都应该没问题。
1)创建一个新类 CopyDBFromAssets.java ,然后复制以下代码: -
IntDatabaseHelper
这是一个精简版本,需要注意的一点是,DB_NAME,DB_COLUMN和DB_TABLE已更改为public class CopyDBFromAssets {
boolean copied = false;
public static boolean createDataBase(Context context, String databasename) {
boolean copied = false;
boolean dbExist = checkDataBase(context, databasename);
if(!dbExist) {
// calling this method will create an empty database
// which will hopefully be overidden, if not then
// empty database will exist ?????????
//this.getReadableDatabase(); <<<<< NOTE Commented out as empty db with no tables is useless
if (!checkAssetExists(context, databasename, "")) {
Log.e("CREATEDB", "Error getting asset " + databasename);
} else {
return copyDataBase(context, databasename);
}
return false;
}
return true;
}
private static boolean checkAssetExists(Context context, String assetfile, String path) {
boolean rv = false; // assume asset file doesn't exist
String[] assetsfound = new String[]{};
// Get the list of assets at the given path
try {
assetsfound = context.getAssets().list(path);
} catch (IOException e) {
Log.e("CHECKASSET","IO Exception when checking for the asset file." + e.getMessage());
return false;
}
// Check to see if the desired asset (passed assetfile) exists
for (String s: assetsfound) {
if (s.equals(assetfile)) {
rv = true;
break;
}
}
if (rv) {
Log.d("CHECKASSET", "Asset " + assetfile + "was found.");
} else {
String assetlist = "";
for (String s: assetsfound) {
assetlist = assetlist + " " + s;
}
Log.e("CHECKASSET", "Asset " + assetfile +
"could not be found. Assets that exists are:- " +
assetlist
);
}
// Asset not found lets try ignoring case
if (!rv) {
for (String s: assetsfound) {
if ((s.toLowerCase()).equals(assetfile.toLowerCase())) {
Log.e("CHECKASSET","Found asset as " + assetfile +
" but looking for " + s +
", although they are similar the case is different."
);
}
}
}
return rv;
}
// check if database exists to avoid recopying it
private static boolean checkDataBase (Context context, String database){
SQLiteDatabase checkDB = null;
String dbpath = context.getDatabasePath(database).getPath();
try{
checkDB = SQLiteDatabase.openDatabase(dbpath, null,
SQLiteDatabase.OPEN_READONLY);
} catch(SQLiteException e){
// database doesnt exist yet
}
if(checkDB !=null){
checkDB.close();
}
return checkDB !=null ? true : false;
}
// copies db from local assets file, were it can be accessed and handled
private static boolean copyDataBase(Context context, String databasename) {
InputStream asset;
OutputStream db;
int bytescopied = 0;
int length_read;
int buffersize = 16384;
int blockcount = 0;
boolean rv = false;
try {
asset = context.getAssets().open(databasename);
} catch (IOException e) {
Log.e("COPYDB",
"IO Error opening the asset " +
databasename +
". Error Message was " +
e.getMessage()
);
return false;
}
try {
db = new FileOutputStream(context.getDatabasePath(databasename).getPath());
} catch (IOException e) {
Log.e("COPYDB",
"IO Error opening the output file for the database with path " +
databasename +
". error Message was " +
e.getMessage()
);
try {
asset.close();
} catch (IOException e2) {
Log.e("COPYDB",
"IO Error closing the asset. Message was " + e2.getMessage()
);
}
return false;
}
byte[] buffer = new byte[buffersize];
try {
while ((length_read = asset.read(buffer)) > 0) {
db.write(buffer);
bytescopied = bytescopied + length_read;
blockcount++;
rv = true;
}
} catch (IOException e) {
Log.e("COPYDB",
"IO Error Copying Database. Bytes Copied = "
+ bytescopied +
" in " +
blockcount +
" blocks of " +
buffersize
);
}
Log.d("COPYDB","Succesfully copied Database " + databasename + " from the assets." +
" Number of bytes copied = " + bytescopied +
" in " + blockcount + " blocks of length " + buffersize
);
try {
db.flush();
db.close();
asset.close();
} catch (IOException e) {
Log.e("COPYDB",
"IO Error flushing or closing Database or closing asset."
);
}
return rv;
}
}
(因为它们在别处使用)。
这是代码: -
public static final
这只是使用上述代码的示例代码,请注意,如果数据库不存在则无法创建,那么将发出运行时异常(示例将如下): -
public class IntDataBaseHelper extends SQLiteOpenHelper {
private static String DB_PATH ="C:\\Users\\joelg\\AndroidStudioProjects\\CLAPP\\app\\build\\intermediates\\assets";
public static final String DB_NAME = "JobList";
public static final String DB_COLUMN = "JobNM";
public static final String DB_TABLE = "Job";
private static String DB_JOB_IS_DONE = "JobComplete";
private SQLiteDatabase JobListDatabase;
private final Context jobContext;
/**
* constructor t
*/
public IntDataBaseHelper (Context context) {
super (context, DB_NAME,null, 1);
this.jobContext = context;
DB_PATH = jobContext.getDatabasePath(DB_NAME).getPath();
}
public void openDataBase() {
// open the database
String JobListPath = DB_PATH;
JobListDatabase =
SQLiteDatabase.openDatabase(JobListPath,null,SQLiteDatabase.OPEN_READONLY);
}
// Getting Job Count
public ArrayList<String> getJobList() {
ArrayList<String> JobList = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(DB_TABLE,new String[]
{DB_COLUMN},null,null,null,null,null);
while(cursor.moveToNext()){
int index = cursor.getColumnIndex(DB_COLUMN);
JobList.add(cursor.getString(index));
}
cursor.close();
db.close();
return JobList;
}
@Override
public synchronized void close(){
if(JobListDatabase !=null){
JobListDatabase.close();
super.close();
}
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
首先,我们假设资源文件夹中的文件名称为作业而不是 JobList (或除JobList之外的任何内容),假设刚刚安装了应用程序。然后运行上面的内容将产生以下内容: -
根据Windows资源管理器的资源文件夹: -
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create the database (only if it doesn't exists)
// does so by copying from the assets
if (CopyDBFromAssets.createDataBase(this,IntDataBaseHelper.DB_NAME)) {
IntDataBaseHelper myhelper = new IntDataBaseHelper(this);
// Get the data from the database
ArrayList<String> jobs = myhelper.getJobList();
for (String s: jobs) {
Log.d("TESTDB","Found Job " + s);
}
} else {
throw new RuntimeException("No Usable Database exists or was copied from the assets.");
}
}
}
以下几行详细说明了问题: -
10-24 20:31:04.994 2346-2346/? E/SQLiteLog: (14) cannot open file at line 30046 of [9491ba7d73]
10-24 20:31:04.994 2346-2346/? E/SQLiteLog: (14) os_unix.c:30046: (2) open(/data/data/mjt.joblist/databases/JobList) -
10-24 20:31:04.994 2346-2346/? E/SQLiteDatabase: Failed to open database '/data/data/mjt.joblist/databases/JobList'.
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:806)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:791)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
at mjt.joblist.CopyDBFromAssets.checkDataBase(CopyDBFromAssets.java:93)
at mjt.joblist.CopyDBFromAssets.createDataBase(CopyDBFromAssets.java:25)
at mjt.joblist.MainActivity.onCreate(MainActivity.java:18)
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)
10-24 20:31:05.004 2346-2346/? E/CHECKASSET: Asset JobListcould not be found. Assets that exists are:- Job images sounds webkit
10-24 20:31:05.004 2346-2346/? E/CREATEDB: Error getting asset JobList
10-24 20:31:05.004 2346-2346/? D/AndroidRuntime: Shutting down VM
--------- beginning of crash
10-24 20:31:05.004 2346-2346/? E/AndroidRuntime: FATAL EXCEPTION: main
Process: mjt.joblist, PID: 2346
java.lang.RuntimeException: Unable to start activity ComponentInfo{mjt.joblist/mjt.joblist.MainActivity}: java.lang.RuntimeException: No Usable Database exists or was copied from the assets.
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: java.lang.RuntimeException: No Usable Database exists or was copied from the assets.
at mjt.joblist.MainActivity.onCreate(MainActivity.java:27)
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)
10-24 20:31:05.008 738-1262/? W/ActivityManager: Force finishing activity 1 mjt.joblist/.MainActivity
无法找到 JobList ,找到的资源是作业(错误命名)图像,声音和webkit(最后三个与此无关)。< / p>
运行时异常(第二个)与: -
一样10-24 20:31:05.004 2346-2346/? E/CHECKASSET: Asset JobListcould not be found. Assets that exists are:- Job images sounds webkit
10-24 20:31:05.004 2346-2346/? E/CREATEDB: Error getting asset JobList
日志显示: -
java.lang.RuntimeException: Unable to start activity ComponentInfo{mjt.joblist/mjt.joblist.MainActivity}: java.lang.RuntimeException: No Usable Database exists or was copied from the assets.
引发异常(找不到数据库,如检查它是否存在),但它没有崩溃,我们发现找到 JobList 并且在6个块中复制了98304个字节16K。
然后我们看到数据库中的数据,这是通过DBHelper方法获得的。
只是: -
10-24 20:43:01.160 8696-8696/? E/SQLiteLog: (14) cannot open file at line 30046 of [9491ba7d73]
10-24 20:43:01.160 8696-8696/? E/SQLiteLog: (14) os_unix.c:30046: (2) open(/data/data/mjt.joblist/databases/JobList) -
10-24 20:43:01.162 8696-8696/? E/SQLiteDatabase: Failed to open database '/data/data/mjt.joblist/databases/JobList'.
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:806)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:791)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
at mjt.joblist.CopyDBFromAssets.checkDataBase(CopyDBFromAssets.java:93)
at mjt.joblist.CopyDBFromAssets.createDataBase(CopyDBFromAssets.java:25)
at mjt.joblist.MainActivity.onCreate(MainActivity.java:18)
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)
10-24 20:43:01.169 8696-8696/? D/CHECKASSET: Asset JobListwas found.
10-24 20:43:01.175 8696-8696/? D/COPYDB: Succesfully copied Database JobList from the assets. Number of bytes copied = 98304 in 6 blocks of length 16384
10-24 20:43:01.204 8696-8696/? D/TESTDB: Found Job Job001
10-24 20:43:01.204 8696-8696/? D/TESTDB: Found Job Job002
10-24 20:43:01.204 8696-8696/? D/TESTDB: Found Job Job003
10-24 20:43:01.204 8696-8696/? D/TESTDB: Found Job Job004
答案 1 :(得分:0)
根据我的评论,您似乎指定了Assets文件夹的Windows路径,设备/模拟器将不会知道这一点。而是在构建和安装App时,资产将被包含并放置在devices / data / data /中的资产文件中。
e.g。
构建并运行并查看Android设备后: -
应用程序中用于访问数据库的代码: -
final String DBNAME = "books.sqlpro";
final String DBPATH = this.getDatabasePath(DBNAME).getPath();
final String TBNAME = "books";
final String AUTHOR_COL = "author";
String outfilename = DBPATH + DBNAME;
SQLiteDatabase booksdb;
try {
booksdb = SQLiteDatabase.openDatabase(outfilename, null, SQLiteDatabase.OPEN_READONLY);
} catch (Exception e) {
try {
InputStream is = this.getAssets().open(DBNAME);
OutputStream os = new FileOutputStream(outfilename);
byte[] buffer = new byte[32768];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer);
}
is.close();
os.flush();
os.close();
} catch (IOException io) {
io.printStackTrace();
}
try {
booksdb = SQLiteDatabase.openDatabase(outfilename, null, SQLiteDatabase.OPEN_READONLY);
} catch (Exception e2) {
e2.printStackTrace();
return;
}
}
Cursor csr = booksdb.query(TBNAME, null, null, null, null, null, null);
注意上面的this.getAssets().open(DBNAME);
获取路径。
在上面,数据库在被使用之前从资产复制到标准/默认数据库位置,但仅在尝试打开数据库失败时(很可能表明它不存在)。
正如您在这里遇到问题一样,有一些完整的工作代码: -
首先是DBHelper: -
public class IntDataBaseHelper extends SQLiteOpenHelper {
private static String DB_PATH ="C:\\Users\\joelg\\AndroidStudioProjects\\CLAPP\\app\\build\\intermediates\\assets";
private static String DB_NAME = "JobList";
private static String DB_COLUMN = "JobNM";
private static String DB_TABLE = "Job";
private static String DB_JOB_IS_DONE = "JobComplete";
private SQLiteDatabase JobListDatabase;
private final Context jobContext;
/**
* constructor t
*/
public IntDataBaseHelper (Context context) {
super (context, DB_NAME,null, 1);
this.jobContext = context;
DB_PATH = jobContext.getDatabasePath(DB_NAME).getPath();
}
public void createDataBase() throws IOException {
boolean dbExist = checkDataBase();
if(dbExist){
//do nothing database already exists
}else{
// calling this method will create an empty database
// which will hopefully be overidden, if not then
// empty database will exist ?????????
this.getReadableDatabase();
try {
copyDataBase();
} catch (IOException e){
throw new Error("Error copying database");
}
}
}
// check if database exists to avoid recopying it
private boolean checkDataBase (){
SQLiteDatabase checkDB = null;
try{
String JobListPath = DB_PATH;
checkDB = SQLiteDatabase.openDatabase(JobListPath, null,
SQLiteDatabase.OPEN_READONLY);
} catch(SQLiteException e){
// database doesnt exist yet
}
if(checkDB !=null){
checkDB.close();
}
return checkDB !=null ? true : false;
}
// copies db from local assets file, were it can be accessed and handled
private void copyDataBase() throws IOException {
InputStream dbfromassets;
OutputStream actualdb;
Boolean copyok = true;
/*
try {
dbfromassets = jobContext.getAssets().open(DB_NAME);
} catch (IOException e) {
Log.d("COPYDB","IO Error trying to open the Database in assets folder");
e.printStackTrace();
copyok = false;
return;
}
try {
actualdb = new FileOutputStream(DB_PATH);
} catch (IOException e) {
Log.d("COPYDB","IO Error trying to get get output file.");
e.printStackTrace();
copyok = false;
return;
}
if (dbfromassets != null && copyok) {
byte[] buffer = new byte[1024];
int length;
int copied = 0;
while ((length = dbfromassets.read(buffer)) > 0) {
actualdb.write(buffer);
copied = copied + length;
}
actualdb.flush();
actualdb.close();
dbfromassets.close();
Log.d("COPYDB","Bytes copied " + Integer.toString(copied));
}
*/
// open local database as the input stream
try {
InputStream JobInput = jobContext.getAssets().open(DB_NAME);
// path to the just created empty database
String OutFileName = DB_PATH;
// open the empty db as the output stra,
OutputStream myOutPut = new FileOutputStream(OutFileName);
// transfer bytes from the input file to the output file
byte[] buffer = new byte[1024];
int length;
while ((length = JobInput.read(buffer)) > 0) {
myOutPut.write(buffer, 0, length);
}
myOutPut.flush();
myOutPut.close();
JobInput.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public void openDataBase() throws SQLiteException {
// open the database
String JobListPath = DB_PATH;
JobListDatabase =
SQLiteDatabase.openDatabase(JobListPath,null,SQLiteDatabase.OPEN_READONLY);
}
// Getting Job Count
public ArrayList<String> getJobList() {
ArrayList<String> JobList = new ArrayList<>();
SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db.query(DB_TABLE,new String[]
{DB_COLUMN},null,null,null,null,null);
while(cursor.moveToNext()){
int index = cursor.getColumnIndex(DB_COLUMN);
JobList.add(cursor.getString(index));
}
cursor.close();
db.close();
return JobList;
}
@Override
public synchronized void close(){
if(JobListDatabase !=null){
JobListDatabase.close();
super.close();
}
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
为了测试以上内容,我有以下内容: - 公共类MainActivity扩展了AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
IntDataBaseHelper myhelper = new IntDataBaseHelper(this);
// List assets
try {
for (String s: this.getAssets().list("")) {
Log.d("ASSETS","Found asset (Directory or File) " + s);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
myhelper.createDataBase();
} catch (IOException e) {
}
ArrayList<String> jobs = myhelper.getJobList();
for (String s: jobs) {
Log.d("TESTDB","Found Job " + s);
}
}
}
没有DB时运行的结果(来自checkDatabase的stackTrace,但请注意下面提取的4行,预期): -
10-24 09:13:22.527 5991-5991/? E/SQLiteLog: (14) cannot open file at line 30046 of [9491ba7d73]
10-24 09:13:22.527 5991-5991/? E/SQLiteLog: (14) os_unix.c:30046: (2) open(/data/data/mjt.joblist/databases/JobList) -
10-24 09:13:22.530 5991-5991/? E/SQLiteDatabase: Failed to open database '/data/data/mjt.joblist/databases/JobList'.
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:806)
at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:791)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:694)
at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:669)
at mjt.joblist.IntDataBaseHelper.checkDataBase(IntDataBaseHelper.java:60)
at mjt.joblist.IntDataBaseHelper.createDataBase(IntDataBaseHelper.java:39)
at mjt.joblist.MainActivity.onCreate(MainActivity.java:21)
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)
10-24 09:13:22.561 5991-5991/? E/SQLiteLog: (1) no such table: Job
10-24 09:13:22.563 5991-5991/? D/TESTDB: Found Job Job001
10-24 09:13:22.563 5991-5991/? D/TESTDB: Found Job Job002
10-24 09:13:22.563 5991-5991/? D/TESTDB: Found Job Job003
10-24 09:13:22.563 5991-5991/? D/TESTDB: Found Job Job004
从后续运行(DB已经存在): -
10-24 09:16:04.884 7433-7433/? D/TESTDB: Found Job Job001
10-24 09:16:04.884 7433-7433/? D/TESTDB: Found Job Job002
10-24 09:16:04.884 7433-7433/? D/TESTDB: Found Job Job003
10-24 09:16:04.884 7433-7433/? D/TESTDB: Found Job Job004
在App之外创建了包含4行的数据库(我使用了SQlite Mnaager),然后将文件复制到 App / src / main / 中的assets文件夹(必须创建它)中strong>应用程序项目的目录(使用Windows资源管理器)。
在SQlite经理中: -