找不到/data/data/package.name/databases

时间:2013-11-25 14:27:21

标签: android sqlite

我需要将一个SQLite数据库从assets /复制到app的数据库/目录中,但正如我将在下面给出的那样,我不断获得空指针异常。下面是一些可能相关的Logcat和代码:

   [ 11-24 21:51:19.694  1652:0x67e E/AndroidRuntime ]
    FATAL EXCEPTION: AsyncTask #1
    java.lang.RuntimeException: An error occured while executing doInBackground()
        at android.os.AsyncTask$3.done(AsyncTask.java:200)
        at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
        at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
        at java.util.concurrent.FutureTask.run(FutureTask.java:138)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
        at java.lang.Thread.run(Thread.java:1019)
    Caused by: java.lang.NullPointerException
        at net.xx.wildedibles.full.common.DataBaseHelper.<init>(DataBaseHelper.java:27)
        at net.xx.wildedibles.full.common.DBAdapter.<init>(DBAdapter.java:21)
        at net.xx.wildedibles.full.intro.LoadingFragment$LoadingTask.doInBackground(LoadingFragment.java:75)
        at net.xx.wildedibles.full.intro.LoadingFragment$LoadingTask.doInBackground(LoadingFragment.java:68)
        at android.os.AsyncTask$2.call(AsyncTask.java:185)
        at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
        ... 4 more

DatabaseHelper的第27行:

  DB_PATH = context.getDatabasePath(DB_NAME).toString();

现在我知道有几种方法可以计算数据库的路径,而且我已经尝试了所有这些,但没有工作。仍然得到相同的NPE。

但是这里有点好奇:我决定做adb shell并查看应用程序的目录结构,以便更好地了解我出错的地方。这是导航到data / data / package.name /:

后得到的结果
# cd net.xx.wildedibles.full
# ls
lib
# 

为什么我看不到/ databases /,以及其他所有东西?当我进入lib /时,里面什么也没有。正如你所看到的,我在看的时候是根。鉴于此,我当然可以理解为什么我会得到一个空指针......

非常感谢您提供的任何建议!

根据要求,这是完整的代码:

这是一个DBAdapter类:

public class DBAdapter 
{
    protected static final String TAG = "DataAdapter";

    private final Context mContext;
    private SQLiteDatabase mDb;
    private DataBaseHelper mDbHelper;

    public DBAdapter(Context context) 
    {
    mContext = context;
        mDbHelper = new DataBaseHelper(mContext);
   }

    public DBAdapter createDatabase() throws SQLException 
    {
        try 
        {
            mDbHelper.createDataBase();
        } 
        catch (IOException mIOException) 
        {
            Log.e(TAG, mIOException.toString() + "  UnableToCreateDatabase");
            throw new Error("UnableToCreateDatabase");
        }
        return this;
    }

    public DBAdapter open() throws SQLException 
    {
        try 
        {
            mDbHelper.openDataBase();
            mDbHelper.close();
            mDb = mDbHelper.getReadableDatabase();
        } 
        catch (SQLException mSQLException) 
        {
            Log.e(TAG, "open >>"+ mSQLException.toString());
            throw mSQLException;
        }
        return this;
    }

    public void close() 
    {
        mDbHelper.close();
    }

     public Cursor getData(String query)
     {
         try
         {

             Cursor mCur = mDb.rawQuery(query, null);
             if (mCur!=null)
             {
                mCur.moveToNext();
             }
             return mCur;
         }
         catch (SQLException mSQLException) 
         {
             Log.e(TAG, "getData >>"+ mSQLException.toString());
             throw mSQLException;
         }
     }
}

以下是整个Helper类:

public class DataBaseHelper extends SQLiteOpenHelper{

    private static String TAG = "DataBaseHelper"; //tag for logcat
    private static String DB_PATH;
    private static String DB_NAME ="foraging.db";// Database name
    private SQLiteDatabase mDataBase; 
    private final Context mContext;

    public DataBaseHelper(Context context){

        super(context, DB_NAME, null, 1);
        if(android.os.Build.VERSION.SDK_INT >= 4.2){
           DB_PATH = context.getDatabasePath(DB_NAME).toString();

        }
        else
        {
           DB_PATH = "/data/data/" + context.getPackageName() + "/databases/";
        }
        this.mContext = context;
    }   

    public void onCreate(SQLiteDatabase db) {

    }

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
        //db.execSQL("DROP TABLE IF EXISTS" + DATABASE_TABLE);
        onCreate(db);
    }

    public void createDataBase() throws IOException
    {   
        //If database does not exist, copy from 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");
        }
    }
    }

    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();
    }


    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 void close() 
    {
        if(mDataBase != null)
            mDataBase.close();
        super.close();
    }

}

1 个答案:

答案 0 :(得分:0)

直接从the horse's mouth第一次致电getReadableDatabase()getWriteableDatabase(),才会创建您的数据库:

  

public SQLiteDatabase getReadableDatabase()

     

创建和/或打开数据库。 ...

如果您希望从您在assets文件夹中的预构建数据库中复制您创建的数据库(我喜欢这个想法,因为您不必在Java中使用SQL中的所有CREATE语句)我需要先调用getReadableDatabase()getWriteableDatabase() 然后复制文件。可以在this answer中找到一个例子。

编辑:只是在您的编辑中看到您使用了我链接的相同代码。请注意,答案中的代码不会调用getDatabasePath,而是尝试手动创建路径,因为它知道它可能不存在。

getDatabasePath正在投掷NPE,因为正如its description中所述,它返回the absolute path on the filesystem where a database created。您的文件尚未创建!