Android SQLite从外部存储文件夹读取数据库

时间:2016-10-25 07:00:24

标签: android sqlite

目前,我正在开发一个Android应用程序,我的要求是从外部位置中的固定位置读取SQLite数据库。但我无法打开数据库。我正在尝试的代码如下:

DatabaseHelper:

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

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

public class DataBaseHelper extends SQLiteOpenHelper
{
    private static final int DB_VERSION = 1;
    //private static final String DB_NAME = "MedRec.db";
    private static final String DB_NAME = "MedRec";

    public DataBaseHelper(Context context)
    {
        //super(context,DB_NAME,null,DB_VERSION);

        super(context, Environment.getExternalStorageDirectory() + "/EMIS/MedRec", null, 1);
        //super(context, context.getExternalFilesDir(null).getAbsolutePath() + "/EMIS/" + DB_NAME, null, 1);

        Log.d("DB_PATH:", context.getExternalFilesDir(null).getAbsolutePath() + "/EMIS/" + DB_NAME);
    }

    @Override
    public void onCreate(SQLiteDatabase database)
    {
        Log.d("CREATING TABLE :", "SUCCESS");
    }

    @Override
    public void onUpgrade(SQLiteDatabase database,int oldVersion,int newVersion)
    {

        Log.d("UPGRADING TABLE :", "SUCCESS");

        onCreate(database);
    }
}

PatientDataSource:

package com.medrecordapp.main.database;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
import com.medrecordapp.main.model.Patient;
import java.util.ArrayList;

public class PatientDataSource
{
    private SQLiteDatabase database;
    private DataBaseHelper dbHelper;

    public static final String TABLE_PATIENT = "Patient";

    public final static String ID                = "_id";
    public final static String PATIENT_ID        = "PatientID";
    public final static String NHS_NUMBER        = "NHSNumber";
    public final static String FIRST_NAME        = "FirstName";
    public final static String LAST_NAME         = "LastName";
    public final static String CATEGORY          = "category";
    public final static String PHONE_1           = "phone1";
    public final static String PHONE_2           = "phone2";
    public final static String PHOTO_FILE        = "photofile";
    public final static String PROFESSION        = "profession";
    public final static String STREET            = "Street";
    public final static String VILLAGE           = "Village";
    public final static String TOWN              = "Town";
    public final static String COUNTRY           = "County";
    public final static String POST_CODE         = "PostCode";
    public final static String COMMENT           = "comment";
    public final static String E1                = "E1";
    public final static String E2                = "E2";
    public final static String E3                = "E3";
    public final static String E4                = "E4";
    public final static String E5                = "E5";
    public final static String UPD_DATE          = "upddate";

    public PatientDataSource(Context context)
    {
        dbHelper = new DataBaseHelper(context);
    }

    public void open() throws SQLException
    {
        ///dbHelper.openDataBase();
        //dbHelper.getReadableDatabase();
        //database = dbHelper.getReadableDatabase();

        database = dbHelper.getWritableDatabase();
    }

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

    public long addPatient(Patient patient)
    {
        open();

        ContentValues patientValue = new ContentValues();

        patientValue.put(PATIENT_ID, patient.getPatientId());
        patientValue.put(NHS_NUMBER, patient.getNhsNumber());
        patientValue.put(FIRST_NAME, patient.getFirstName());
        patientValue.put(LAST_NAME, patient.getFirstName());
        patientValue.put(CATEGORY, patient.getFirstName());
        patientValue.put(PHONE_1, patient.getFirstName());
        patientValue.put(PHONE_2, patient.getFirstName());
        patientValue.put(PHOTO_FILE, patient.getFirstName());
        patientValue.put(PROFESSION, patient.getFirstName());
        patientValue.put(STREET, patient.getFirstName());
        patientValue.put(VILLAGE, patient.getFirstName());
        patientValue.put(TOWN, patient.getFirstName());
        patientValue.put(COUNTRY, patient.getFirstName());
        patientValue.put(POST_CODE, patient.getFirstName());
        patientValue.put(COMMENT, patient.getFirstName());
        patientValue.put(E1, patient.getFirstName());
        patientValue.put(E2, patient.getFirstName());
        patientValue.put(E3, patient.getFirstName());
        patientValue.put(E4, patient.getFirstName());
        patientValue.put(E5, patient.getFirstName());
        patientValue.put(UPD_DATE, patient.getFirstName());

        long insertId = database.insert(TABLE_PATIENT,null,patientValue);

        Log.d("RESULT :", insertId + "");

        close();

        return insertId;
    }

    public ArrayList<Patient> loadPatient()
    {
        open();

        ArrayList<Patient> patientList = new ArrayList<Patient>();

        Cursor cursor = database.rawQuery(" SELECT * FROM Patient " , null );

        cursor.moveToFirst();

        while (!cursor.isAfterLast())
        {
            Patient patient = new Patient(
                                            cursor.getInt(cursor.getColumnIndex("_id"))   ,  cursor.getString(cursor.getColumnIndex("PatientID")),  cursor.getString(2),  cursor.getString(3),
                                            cursor.getString(4),  cursor.getString(5),  cursor.getString(6),  cursor.getString(6),
                                            cursor.getString(7),  cursor.getString(8),  cursor.getString(9),  cursor.getString(10),
                                            cursor.getString(11), cursor.getString(12), cursor.getString(13), cursor.getString(14),
                                            cursor.getString(15), cursor.getString(16), cursor.getString(17), cursor.getString(18),
                                            cursor.getString(19), cursor.getString(20), cursor.getString(21)
                                         );

            patientList.add(patient);

            cursor.moveToNext();
        }

        cursor.close();

        close();

        return patientList;
    }

    public ArrayList<Patient> loadPatient(String patientId)
    {
        open();

        ArrayList<Patient> patientList = new ArrayList<Patient>();

        Cursor cursor = database.rawQuery(" SELECT * FROM Patient WHERE _id = ?" , new String[]{ patientId } );

        cursor.moveToFirst();

        while (!cursor.isAfterLast())
        {
            Patient patient = new Patient(
                                                cursor.getInt(0)   ,  cursor.getString(1),  cursor.getString(2),  cursor.getString(3),
                                                cursor.getString(4),  cursor.getString(5),  cursor.getString(6),  cursor.getString(6),
                                                cursor.getString(7),  cursor.getString(8),  cursor.getString(9),  cursor.getString(10),
                                                cursor.getString(11), cursor.getString(12), cursor.getString(13), cursor.getString(14),
                                                cursor.getString(15), cursor.getString(16), cursor.getString(17), cursor.getString(18),
                                                cursor.getString(19), cursor.getString(20), cursor.getString(21)
                                         );

            patientList.add(patient);

            cursor.moveToNext();
        }

        cursor.close();

        close();

        return patientList;
    }

    /*public void updateFavorites(Favorites favoritesInfo,String id)
    {
        open();

        ContentValues favoritesInfoValues = new ContentValues();

        String strFilter = "id = " + id;

        favoritesInfoValues.put(ID, favoritesInfo.getFavoritesId());
        favoritesInfoValues.put(JOKES_ID, favoritesInfo.getJokesId());

        //Update using the SQLite update function.
        database.update(TABLE_FAVORITES, favoritesInfoValues, strFilter, null);

        //Close the opened database connection
        close();
    }*/

    public boolean deletePatient(String id)
    {
        open();

        String strFilter = "_id =" + id;

        boolean res = database.delete(TABLE_PATIENT, strFilter , null) > 0;

        close();

        return res;
    }
}

清单权限:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

但我得到的是以下例外情况:

    10-25 12:49:25.838  30502-30502/com.medrecodapp.main.database E/SQLiteLog﹕ (14) cannot open file at line 31278 of [2ef4f3a5b1]
10-25 12:49:25.838  30502-30502/com.medrecodapp.main.database E/SQLiteLog﹕ (14) os_unix.c:31278: (2) open(/storage/emulated/0/EMIS/MedRec) -
10-25 12:49:25.838  30502-30502/com.medrecodapp.main.database E/SQLiteConnection﹕ DB info: sqlite3_open_v2, path: /storage/emulated/0/EMIS/MedRec, flag: 6, ret: 14
10-25 12:49:25.838  30502-30502/com.medrecodapp.main.database E/SQLiteConnection﹕ DB info: errno = 2, errno message = No such file or directory
10-25 12:49:25.839  30502-30502/com.medrecodapp.main.database E/SQLiteDatabase﹕ Failed to open database '/storage/emulated/0/EMIS/MedRec'.
    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:237)
            at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:221)
            at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:468)
            at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:190)
            at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:182)
            at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:876)
            at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:856)
            at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:754)
            at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:579)
            at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:269)
            at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:223)
            at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
            at com.medrecordapp.main.database.PatientDataSource.open(PatientDataSource.java:53)
            at com.medrecordapp.main.database.PatientDataSource.loadPatient(PatientDataSource.java:100)
            at com.medrecordapp.main.activity.PatientListActivity.onCreate(PatientListActivity.java:90)
            at android.app.Activity.performCreate(Activity.java:6262)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1125)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2462)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2569)
            at android.app.ActivityThread.access$900(ActivityThread.java:150)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1399)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:168)
            at android.app.ActivityThread.main(ActivityThread.java:5885)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:819)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:709)
10-25 12:49:25.840  30502-30502/com.medrecodapp.main.database E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.medrecodapp.main.database, PID: 30502
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.medrecodapp.main.database/com.medrecordapp.main.activity.PatientListActivity}: android.database.sqlite.SQLiteCantOpenDatabaseException: unknown error (code 14): Could not open database
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2509)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2569)
            at android.app.ActivityThread.access$900(ActivityThread.java:150)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1399)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:168)
            at android.app.ActivityThread.main(ActivityThread.java:5885)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:819)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:709)
     Caused by: 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:237)
            at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:221)
            at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:468)
            at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:190)
            at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:182)
            at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:876)
            at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:856)
            at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:754)
            at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:579)
            at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:269)
            at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:223)
            at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:163)
            at com.medrecordapp.main.database.PatientDataSource.open(PatientDataSource.java:53)
            at com.medrecordapp.main.database.PatientDataSource.loadPatient(PatientDataSource.java:100)
            at com.medrecordapp.main.activity.PatientListActivity.onCreate(PatientListActivity.java:90)
            at android.app.Activity.performCreate(Activity.java:6262)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1125)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2462)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2569)
            at android.app.ActivityThread.access$900(ActivityThread.java:150)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1399)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:168)
            at android.app.ActivityThread.main(ActivityThread.java:5885)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:819)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:709)

该文件已放入以下文件夹中:

enter image description here

enter image description here

我要提到的最后一件事是我在HTC 10上测试它,它没有任何外部存储,但是模拟存储。任何帮助将受到高度赞赏。

由于

3 个答案:

答案 0 :(得分:6)

取自@k3b answers

如果您提供自定义 ContextClass 并且您对目标目录具有写入权限,则可以将 SQLiteOpenHelper 与自定义路径一起使用。

public class DatabaseHelper extends SQLiteOpenHelper {
  private static final int DATABASE_VERSION = 3;
    .....

  DatabaseHelper(final Context context, String databaseName) {
    super(new DatabaseContext(context), databaseName, null, DATABASE_VERSION);
  }
}

这是自定义的DatabaseContext类,可以完成所有的魔术:

class DatabaseContext extends ContextWrapper {

  private static final String DEBUG_CONTEXT = "DatabaseContext";

  public DatabaseContext(Context base) {
    super(base);
  }

  @Override
  public File getDatabasePath(String name)  {
    File sdcard = Environment.getExternalStorageDirectory();    
    String dbfile = sdcard.getAbsolutePath() + File.separator+ "databases" + File.separator + name;
    if (!dbfile.endsWith(".db")) {
      dbfile += ".db" ;
    }

    File result = new File(dbfile);

    if (!result.getParentFile().exists()) {
      result.getParentFile().mkdirs();
    }

    if (Log.isLoggable(DEBUG_CONTEXT, Log.WARN)) {
      Log.w(DEBUG_CONTEXT, "getDatabasePath(" + name + ") = " + result.getAbsolutePath());
    }

    return result;
  }

  /* this version is called for android devices >= api-11. thank to @damccull for fixing this. */
  @Override
  public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) {
    return openOrCreateDatabase(name,mode, factory);
  }

  /* this version is called for android devices < api-11 */
  @Override
  public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory) {
    SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null);
    // SQLiteDatabase result = super.openOrCreateDatabase(name, mode, factory);
    if (Log.isLoggable(DEBUG_CONTEXT, Log.WARN)) {
      Log.w(DEBUG_CONTEXT, "openOrCreateDatabase(" + name + ",,) = " + result.getPath());
    }
    return result;
  }
}

这是如何运作的:

普通的Android应用程序拥有相对于app文件夹的本地数据库文件。通过使用覆盖getDatabasePath()的客户上下文,数据库现在相对于SD卡上的不同目录。

答案 1 :(得分:4)

首先想一想,如果您使用上面的marshmallow(ANDROID 6.0)操作系统,那么即使您在清单文件中提到它,您也需要获取用户访问外部存储设备的运行时权限。所以要小心这个。之后,我们可以使用以下代码进行检查。我只提到文件选择代码并将其写入数据库。你应该为select文件调用intent。

 String yourDatabaseLocation = "/data/data/yourPackageName/databases/YourdaatabaseName.db";
        String stringArray[] = filePath.split(":");
        FileInputStream fis = null;
        OutputStream os = null;
            String selectedFile = Environment.getExternalStorageDirectory() + "/" + stringArray[1];
            File file = new File(selectedFile);
            fis = new FileInputStream(file);
                os = new FileOutputStream(yourDatabaseLocation);
                byte[] buffer = new byte[1024];
                while ((int length = fis.read(buffer)) > 0) {
                    os.write(buffer, 0, length);
                }
                os.flush();
                os.close();
                fis.close();

此块将帮助您将外部存储上存在的数据库插入当前数据库。数据库结构应该是相同的。

答案 2 :(得分:0)

为什么不尝试将db文件复制到通常应该的位置?路径可能看起来像这样:

String currentDBPath = "//data//" + getActivity().getPackageName() + "//databases//" + DbOpenHelper.DB_NAME;
相关问题