我的databasehelper类中的代码。
package com.app.testapp;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class DatabaseHelper extends SQLiteOpenHelper {
private String DB_PATH;
private static String DB_NAME = "test";
private final Context context;
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, 1);
this.context = context;
this.DB_PATH = "/data/data/" + context.getPackageName() + "/" + "databases/";
Log.e("Database Path:", DB_PATH);
}
public void copyDatabase() throws IOException {
InputStream myInput = context.getAssets().open(DB_NAME);
String outString = DB_PATH + DB_NAME;
OutputStream myOutput = new FileOutputStream(outString);
byte[] buffer = new byte[10];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
我的viewFragment类中的代码
package com.app.testapp;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.io.IOException;
public class ViewFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment, container, false);
DatabaseHelper db = new DatabaseHelper(getActivity());
initDatabase(db);
return view;
}
private void initDatabase(DatabaseHelper db) {
try {
db.copyDatabase();
} catch (IOException ioe) {
throw new Error("Error creating database");
}
}
}
MainActivity类中的代码。
package com.app.testapp;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
getSupportFragmentManager().beginTransaction().replace(R.id.frag_container, new ViewFragment()).commit();
}
}
我试图复制一个已经预制的数据库,然后创建一个新的本地数据库,我可以在程序中访问和使用它。我以前见过类似于此工作的代码,也有类似于此工作与按钮的代码,但是我无法使它工作。
我的错误如下
2019-03-17 23:32:46.645 13197-13197/com.app.testapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.app.testapp, PID: 13197
java.lang.Error: Error creating database
at com.app.testapp.ViewFragment.initDatabase(ViewFragment.java:28)
at com.app.testapp.ViewFragment.onCreateView(ViewFragment.java:20)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2439)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1460)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:802)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3273)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3229)
at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:201)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:620)
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1248)
at android.app.Activity.performStart(Activity.java:6679)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2609)
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)
其他日志:-
E/Database Path:: /data/data/com.app.testapp/databases/
W/System.err: java.io.FileNotFoundException: /data/data/com.app.testapp/databases/test (No such file or directory)
W/System.err: at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:221)
at java.io.FileOutputStream.<init>(FileOutputStream.java:108)
at com.app.testapp.DatabaseHelper.copyDatabase(DatabaseHelper.java:29)
at com.app.testapp.ViewFragment.initDatabase(ViewFragment.java:26)
at com.app.testapp.ViewFragment.onCreateView(ViewFragment.java:20)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:2439)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1460)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:802)
at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3273)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3229)
at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:201)
W/System.err: at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:620)
at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1248)
at android.app.Activity.performStart(Activity.java:6679)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2609)
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)
答案 0 :(得分:1)
您的代码有一些问题。
首先,我认为当数据库文件所在的 databases 目录不存在,因此复制将失败时,它不适合将App作为新App安装。输出文件无法打开。
第二次,每次运行该应用程序时都会尝试复制数据库,因为不会检查数据库是否确实存在。
虽然不是真正的问题,但是如果使用Context的 getDatabasePath 方法,则无需对路径进行硬编码,这可能是不正确的。它还应该对代码进行过时的验证。
我相信以下DatabaseHelper可以解决您的问题(除非问题是文件 test 已复制到 assets 文件夹中(并且是有效的数据库) ):-
public class DatabaseHelper extends SQLiteOpenHelper {
private String DB_PATH;
private static String DB_NAME = "test";
private final Context context;
public DatabaseHelper(Context context) {
super(context, DB_NAME, null, 1);
this.context = context;
this.DB_PATH = context.getDatabasePath(DB_NAME).getPath(); //<<<<<<<<<< REPLACES following line
//this.DB_PATH = "/data/data/" + context.getPackageName() + "/" + "databases/";
Log.e("Database Path:", DB_PATH);
if (!checkDatabase()) {
try {
copyDatabase();
} catch (IOException ioe) {
ioe.printStackTrace();
throw new RuntimeException("Error creating Database - see stack-trace above.");
}
}
}
private boolean checkDatabase() {
File dbpath = new File(DB_PATH);
if (dbpath.exists()) {
return true;
} else {
if (!dbpath.getParentFile().exists()) {
dbpath.getParentFile().mkdirs();
}
}
return false;
}
private void copyDatabase() throws IOException { // MADE PRIVATE AS USED INTERNALLY
InputStream myInput = context.getAssets().open(DB_NAME);
String outString = DB_PATH;
OutputStream myOutput = new FileOutputStream(outString);
byte[] buffer = new byte[10];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
在进行复制之前调用 checkDatabase ,并且仅在数据库不存在时才进行复制,可以解决在解决第一个问题之后遇到的第二个问题。
:-
public class ViewFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment, container, false);
DatabaseHelper db = new DatabaseHelper(getActivity());
return view;
}
}