3

有人可以指出我正确的方向。我可以在 /data/data/mypacket/databases 中创建一个空数据库,但我无法从 assets 文件夹中复制我的数据库?有什么建议么?谢谢您的帮助

代码:

import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 

import android.content.Context; 
import android.database.SQLException; 
import android.database.sqlite.SQLiteDatabase; 
import android.database.sqlite.SQLiteOpenHelper; 
import android.util.Log; 

public class DataBaseHelper extends SQLiteOpenHelper 
{ 
private static String TAG = "DataBaseHelper"; // Tag just for the LogCat window 
//destination path (location) of our database on device 
private static String DB_PATH = "";  
private static String DB_NAME ="MyDatabase";// Database name 
private SQLiteDatabase mDataBase;  
private final Context mContext; 

public DataBaseHelper(Context context)  
{ 
    super(context, DB_NAME, null, 1);// 1? its Database Version 
    DB_PATH = "/data/data/" + context.getPackageName() + "/databases/"; 
    this.mContext = context; 
}    

public void createDataBase() throws IOException 
{ 
    //If database not exists copy it from the assets 

    boolean mDataBaseExist = checkDataBase(); 
    if(!mDataBaseExist) 
    { 
        this.getReadableDatabase(); 
        this.close(); 
        try  
        { 
            //Copy the database from assests 
            copyDataBase(); 
            Log.e(TAG, "createDatabase database created"); 
        }  
        catch (IOException mIOException)  
        { 
            throw new Error("ErrorCopyingDataBase"); 
        } 
    } 
} 
    //Check that the database exists here: /data/data/your package/databases/Da Name 
    private boolean checkDataBase() 
    { 
        File dbFile = new File(DB_PATH + DB_NAME); 
        //Log.v("dbFile", dbFile + "   "+ dbFile.exists()); 
        return dbFile.exists(); 
    } 

    //Copy the database from assets 
    private void copyDataBase() throws IOException 
    { 
        InputStream mInput = mContext.getAssets().open(DB_NAME); 
        String outFileName = DB_PATH + DB_NAME; 
        OutputStream mOutput = new FileOutputStream(outFileName); 
        byte[] mBuffer = new byte[1024]; 
        int mLength; 
        while ((mLength = mInput.read(mBuffer))>0) 
        { 
            mOutput.write(mBuffer, 0, mLength); 
        } 
        mOutput.flush(); 
        mOutput.close(); 
        mInput.close(); 
    } 

    //Open the database, so we can query it 
    public boolean openDataBase() throws SQLException 
    { 
        String mPath = DB_PATH + DB_NAME; 
        //Log.v("mPath", mPath); 
        mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.CREATE_IF_NECESSARY); 
        //mDataBase = SQLiteDatabase.openDatabase(mPath, null, SQLiteDatabase.NO_LOCALIZED_COLLATORS); 
        return mDataBase != null; 
    } 

    @Override 
    public synchronized void close()  
    { 
        if(mDataBase != null) 
            mDataBase.close(); 
        super.close(); 
    }

    @Override
    public void onCreate(SQLiteDatabase arg0) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        // TODO Auto-generated method stub

    } 

} 

日志猫:

 09-03 02:22:32.459: E/AndroidRuntime(19099): FATAL EXCEPTION: main
    09-03 02:22:32.459: E/AndroidRuntime(19099): java.lang.IllegalStateException: Could not execute method of the activity
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at android.view.View$1.onClick(View.java:3597)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at android.view.View.performClick(View.java:4202)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at android.view.View$PerformClick.run(View.java:17340)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at android.os.Handler.handleCallback(Handler.java:725)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at android.os.Handler.dispatchMessage(Handler.java:92)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at android.os.Looper.loop(Looper.java:137)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at android.app.ActivityThread.main(ActivityThread.java:5039)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at java.lang.reflect.Method.invokeNative(Native Method)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at java.lang.reflect.Method.invoke(Method.java:511)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at dalvik.system.NativeStart.main(Native Method)
    09-03 02:22:32.459: E/AndroidRuntime(19099): Caused by: java.lang.reflect.InvocationTargetException
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at java.lang.reflect.Method.invokeNative(Native Method)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at java.lang.reflect.Method.invoke(Method.java:511)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at android.view.View$1.onClick(View.java:3592)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    ... 11 more
    09-03 02:22:32.459: E/AndroidRuntime(19099): Caused by: java.lang.Error: Error copying database
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at com.petermihaylov.scjajavaexamquestions.DataBaseHelper.createDataBase(DataBaseHelper.java:56)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at com.petermihaylov.scjajavaexamquestions.TestAdapter.createDatabase(TestAdapter.java:25)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    at com.petermihaylov.scjajavaexamquestions.TrueAndFalse.testasd(TrueAndFalse.java:25)
    09-03 02:22:32.459: E/AndroidRuntime(19099):    ... 14 more
4

3 回答 3

2

几点建议:

  • 检查文件 `DB_NAME` 是否存在于应用程序的“assets”文件夹中(而不是“raw”文件夹中)。
  • 如果资产文件扩展名为“.gz”,则扩展名将被删除。
  • 资产文件不应大于 1MB。如果是这种情况,请尝试将其压缩并解压缩到数据库文件夹。
  • 在复制文件之前检查 `outFileName` 的路径是否存在(即 `new File(outFileName).getParentFile().mkdirs();`
  • 根据 API 版本检查 `DB_PATH` 是否正确构建。

本答案所述:

if(android.os.Build.VERSION.SDK_INT >= 4.2){
    DB_PATH = context.getApplicationInfo().dataDir + "/databases/";         
}
else
{
    DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
}

此外,不要忘记创建android_metadata表,如本答案中所述。

于 2013-09-03T04:52:31.280 回答
1

我的问题的解决方案是这样的:

由于 Android Studio 使用新的基于 Gradle 的构建系统,您应该将 assets/ 放在源集示例 myproject/src/main/assets/ 中。

我创建了自己的资产文件夹并将其放在 Eclipse 通常放置的位置……这对我造成了所有这些问题。

于 2013-09-04T04:47:08.027 回答
0

这是一些从资产数据库文件夹复制到外部存储文件夹的代码。文件需要在 assets\databases 文件夹下。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import android.app.Activity;
import android.media.MediaScannerConnection;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;

public class Options extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        this.setContentView(R.layout.options);
    }            

    public void backupDatabase(View v) throws IOException {                 
        if (Environment.getExternalStorageState() != null)
        {
            File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyApp");
            if (dir.exists()) {
                //dir.delete();
            }
            else {
                dir.mkdir();
            }

            String fromPath = "";
            if(android.os.Build.VERSION.SDK_INT >= 4.2){
                fromPath = getApplicationInfo().dataDir + "/databases/" + "wl.db";         
            }
            else
            {
                fromPath = "/data/data/" + getPackageName() + "/databases/" + "wl.db";
            }

            String toPath = dir.getAbsolutePath() + "/wl.db";

            fileCopy(new File(fromPath), new File(toPath));

            //This is to refresh the folders in Windows USB conn.
            MediaScannerConnection.scanFile(this, new String[] { Environment.getExternalStorageDirectory().getAbsolutePath() + "/MyApp" }, null, null);         
            MediaScannerConnection.scanFile(this, new String[] { toPath }, null, null);         
        }                   
    }

    public void fileCopy(File src, File dst) throws IOException {
        InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(dst);

        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        in.close();
        out.close();
    }
}
于 2014-09-03T18:10:25.703 回答