title: Opening externally created SQLite database on SDCard on Android
body: <p>I am writing an app that parses a database on a SD card from a camera, and I can't figure out how to get it working on Android, I keep getting "attempt to write a readonly database" exception.  The database isn't readonly and I have WRITE_EXTERNAL_STORAGE permission set in my manifest.</p>
  
  <p>My code snippet:</p>
  
  <pre><code>public class DatabaseHelper 
  { 
  
  public static final String  DATABASE_NAME      = "MISC/EREVIEW.DB"; 
   public static final String  SHARE_TABLE         = "Share"; 
   public static final String  PICTURE_TABLE   = "Picture"; 
  
  private SQLiteDatabase      database; 
   private File sdDir = Environment.getExternalStorageDirectory(); 
  
  public DatabaseHelper() 
   { 
       try 
       { 
           database = SQLiteDatabase.openDatabase(sdDir + 
  File.separator + DATABASE_NAME, null,SQLiteDatabase.OPEN_READWRITE); 
       } 
       catch (SQLiteException ex) 
       { 
           Log.e(TAG, "error -- " + ex.getMessage(), ex); 
       } 
       finally 
       { 
           DBUtil.safeCloseDataBase(database); 
       } 
   }
  </code></pre>
  
  <p>Manifest:</p>
  
  <pre><code>&lt;?xml version="1.0" encoding="utf-8"?&gt;
  &lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.mg.keas"
      android:versionCode="1"
      android:versionName="1.0" &gt;
  
       &lt;uses-sdk android:minSdkVersion="9" /&gt;
       &lt;uses-permission android:name="WRITE_EXTERNAL_STORAGE"/&gt;
  
       &lt;application
          android:icon="@drawable/ic_launcher"
          android:label="@string/app_name" &gt;
           &lt;activity
              android:label="@string/app_name"
              android:name=".KDEASButtonActivity" &gt;
               &lt;intent-filter &gt;
                   &lt;action android:name="android.intent.action.MAIN" /&gt;
  
                   &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
               &lt;/intent-filter&gt;
           &lt;/activity&gt;
       &lt;/application&gt;
  
  &lt;/manifest&gt;
  </code></pre>
  
  <p>The callstack suggests it's having problems adding a Android metadata table.</p>
  
  <pre><code>    12-04 19:51:12.665: I/Database(842): sqlite returned: error code = 8, 
          msg = prepared statement aborts at 37: [CREATE TABLE IF NOT EXISTS 
          android_metadata (locale TEXT)] 
          12-04 19:51:12.665: E/Database(842): CREATE TABLE android_metadata 
          failed 
          12-04 19:51:12.795: E/Database(842): Failed to setLocale() when 
          constructing, closing the database 
          12-04 19:51:12.795: E/Database(842): 
          android.database.sqlite.SQLiteException: attempt to write a readonly 
          database 
          12-04 19:51:12.795: E/Database(842):    at 
          android.database.sqlite.SQLiteDatabase.native_setLocale(Native Method) 
          12-04 19:51:12.795: E/Database(842):    at 
          android.database.sqlite.SQLiteDatabase.setLocale(SQLiteDatabase.java: 
          1967) 
          12-04 19:51:12.795: E/Database(842):    at 
          android.database.sqlite.SQLiteDatabase.&lt;init&gt;(SQLiteDatabase.java: 
          1835) 
          12-04 19:51:12.795: E/Database(842):    at 
          android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java: 
          820) 
          12-04 19:51:12.795: E/Database(842):    at 
          com.mg.keas.DatabaseHelper.&lt;init&gt;(DatabaseHelper.java:29) 
          12-04 19:51:12.795: E/Database(842):    at 
          com.mg.keas.KDEASButtonActivity.onCreate(KDEASButtonActivity.java:28) 
          12-04 19:51:12.795: E/Database(842):    at 
          android.app.Instrumentation.callActivityOnCreate(Instrumentation.java: 
          1047) 
          12-04 19:51:12.795: E/Database(842):    at 
          android.app.ActivityThread.performLaunchActivity(ActivityThread.java: 
          1586) 
          12-04 19:51:12.795: E/Database(842):    at 
          android.app.ActivityThread.handleLaunchActivity(ActivityThread.java: 
          1638) 
          12-04 19:51:12.795: E/Database(842):    at 
          android.app.ActivityThread.access$1500(ActivityThread.java:117) 
          12-04 19:51:12.795: E/Database(842):    at android.app.ActivityThread 
          $H.handleMessage(ActivityThread.java:928) 
          12-04 19:51:12.795: E/Database(842):    at 
          android.os.Handler.dispatchMessage(Handler.java:99) 
          12-04 19:51:12.795: E/Database(842):    at 
          android.os.Looper.loop(Looper.java:123) 
          12-04 19:51:12.795: E/Database(842):    at 
          android.app.ActivityThread.main(ActivityThread.java:3647) 
          12-04 19:51:12.795: E/Database(842):    at 
          java.lang.reflect.Method.invokeNative(Native Method) 
          12-04 19:51:12.795: E/Database(842):    at 
          java.lang.reflect.Method.invoke(Method.java:507) 
          12-04 19:51:12.795: E/Database(842):    at 
          com.android.internal.os.ZygoteInit 
          $MethodAndArgsCaller.run(ZygoteInit.java:839) 
          12-04 19:51:12.795: E/Database(842):    at 
          com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 
          12-04 19:51:12.795: E/Database(842):    at 
          dalvik.system.NativeStart.main(Native Method)
  </code></pre>