@@ -1182,7 +1182,7 @@ public static SQLiteDatabase openDatabase(String path, String password, CursorFa
11821182 return openDatabase (path , password == null ? null : password .toCharArray (), factory , flags , hook , errorHandler );
11831183 }
11841184
1185- /**
1185+ /**
11861186 * Open the database according to the flags {@link #OPEN_READWRITE}
11871187 * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}
11881188 * with optional hook to run on pre/post key events.
@@ -1206,6 +1206,34 @@ public static SQLiteDatabase openDatabase(String path, String password, CursorFa
12061206 */
12071207 public static SQLiteDatabase openDatabase (String path , char [] password , CursorFactory factory , int flags ,
12081208 SQLiteDatabaseHook hook , DatabaseErrorHandler errorHandler ) {
1209+ byte [] keyMaterial = getBytes (password );
1210+ return openDatabase (path , keyMaterial , factory , flags , hook , errorHandler );
1211+ }
1212+
1213+ /**
1214+ * Open the database according to the flags {@link #OPEN_READWRITE}
1215+ * {@link #OPEN_READONLY} {@link #CREATE_IF_NECESSARY} and/or {@link #NO_LOCALIZED_COLLATORS}
1216+ * with optional hook to run on pre/post key events.
1217+ *
1218+ * <p>Sets the locale of the database to the the system's current locale.
1219+ * Call {@link #setLocale} if you would like something else.</p>
1220+ *
1221+ * @param path to database file to open and/or create
1222+ * @param password to use to open and/or create database file (byte array)
1223+ * @param factory an optional factory class that is called to instantiate a
1224+ * cursor when query is called, or null for default
1225+ * @param flags to control database access mode and other options
1226+ * @param hook to run on pre/post key events (may be null)
1227+ * @param errorHandler The {@link DatabaseErrorHandler} to be used when sqlite reports database
1228+ * corruption (or null for default).
1229+ *
1230+ * @return the newly opened database
1231+ *
1232+ * @throws SQLiteException if the database cannot be opened
1233+ * @throws IllegalArgumentException if the database path is null
1234+ */
1235+ public static SQLiteDatabase openDatabase (String path , byte [] password , CursorFactory factory , int flags ,
1236+ SQLiteDatabaseHook hook , DatabaseErrorHandler errorHandler ) {
12091237 SQLiteDatabase sqliteDatabase = null ;
12101238 DatabaseErrorHandler myErrorHandler = (errorHandler != null ) ? errorHandler : new DefaultDatabaseErrorHandler ();
12111239
@@ -1255,16 +1283,16 @@ public static SQLiteDatabase openOrCreateDatabase(File file, String password, Cu
12551283 /**
12561284 * Equivalent to openDatabase(path, password, factory, CREATE_IF_NECESSARY, databaseHook).
12571285 */
1258- public static SQLiteDatabase openOrCreateDatabase (String path , String password , CursorFactory factory , SQLiteDatabaseHook databaseHook ) {
1259- return openDatabase (path , password , factory , CREATE_IF_NECESSARY , databaseHook );
1286+ public static SQLiteDatabase openOrCreateDatabase (File file , String password , CursorFactory factory , SQLiteDatabaseHook databaseHook ,
1287+ DatabaseErrorHandler errorHandler ) {
1288+ return openOrCreateDatabase (file == null ? null : file .getPath (), password , factory , databaseHook , errorHandler );
12601289 }
12611290
12621291 /**
12631292 * Equivalent to openDatabase(path, password, factory, CREATE_IF_NECESSARY, databaseHook).
12641293 */
1265- public static SQLiteDatabase openOrCreateDatabase (File file , String password , CursorFactory factory , SQLiteDatabaseHook databaseHook ,
1266- DatabaseErrorHandler errorHandler ) {
1267- return openOrCreateDatabase (file == null ? null : file .getPath (), password , factory , databaseHook , errorHandler );
1294+ public static SQLiteDatabase openOrCreateDatabase (String path , String password , CursorFactory factory , SQLiteDatabaseHook databaseHook ) {
1295+ return openDatabase (path , password , factory , CREATE_IF_NECESSARY , databaseHook );
12681296 }
12691297
12701298 public static SQLiteDatabase openOrCreateDatabase (String path , String password , CursorFactory factory , SQLiteDatabaseHook databaseHook ,
@@ -1281,6 +1309,15 @@ public static SQLiteDatabase openOrCreateDatabase(String path, char[] password,
12811309 return openDatabase (path , password , factory , CREATE_IF_NECESSARY , databaseHook , errorHandler );
12821310 }
12831311
1312+ public static SQLiteDatabase openOrCreateDatabase (String path , byte [] password , CursorFactory factory , SQLiteDatabaseHook databaseHook ) {
1313+ return openDatabase (path , password , factory , CREATE_IF_NECESSARY , databaseHook , null );
1314+ }
1315+
1316+ public static SQLiteDatabase openOrCreateDatabase (String path , byte [] password , CursorFactory factory , SQLiteDatabaseHook databaseHook ,
1317+ DatabaseErrorHandler errorHandler ) {
1318+ return openDatabase (path , password , factory , CREATE_IF_NECESSARY , databaseHook , errorHandler );
1319+ }
1320+
12841321 /**
12851322 * Equivalent to openDatabase(file.getPath(), password, factory, CREATE_IF_NECESSARY).
12861323 */
@@ -1302,6 +1339,13 @@ public static SQLiteDatabase openOrCreateDatabase(String path, char[] password,
13021339 return openDatabase (path , password , factory , CREATE_IF_NECESSARY , null );
13031340 }
13041341
1342+ /**
1343+ * Equivalent to openDatabase(path, password, factory, CREATE_IF_NECESSARY).
1344+ */
1345+ public static SQLiteDatabase openOrCreateDatabase (String path , byte [] password , CursorFactory factory ) {
1346+ return openDatabase (path , password , factory , CREATE_IF_NECESSARY , null , null );
1347+ }
1348+
13051349 /**
13061350 * Create a memory backed SQLite database. Its contents will be destroyed
13071351 * when the database is closed.
@@ -2489,6 +2533,11 @@ public SQLiteDatabase(String path, char[] password, CursorFactory factory, int f
24892533 this .openDatabaseInternal (password , databaseHook );
24902534 }
24912535
2536+ public SQLiteDatabase (String path , byte [] password , CursorFactory factory , int flags , SQLiteDatabaseHook databaseHook ) {
2537+ this (path , factory , flags , null );
2538+ this .openDatabaseInternal (password , databaseHook );
2539+ }
2540+
24922541 /**
24932542 * Private constructor (without database password) which DOES NOT attempt to open the database.
24942543 *
@@ -2517,37 +2566,44 @@ private SQLiteDatabase(String path, CursorFactory factory, int flags, DatabaseEr
25172566 }
25182567
25192568 private void openDatabaseInternal (final char [] password , SQLiteDatabaseHook hook ) {
2520- boolean shouldCloseConnection = true ;
25212569 final byte [] keyMaterial = getBytes (password );
2570+ openDatabaseInternal (keyMaterial , hook );
2571+ }
2572+
2573+ private void openDatabaseInternal (final byte [] password , SQLiteDatabaseHook hook ) {
2574+ boolean shouldCloseConnection = true ;
25222575 dbopen (mPath , mFlags );
25232576 try {
2524-
25252577 keyDatabase (hook , new Runnable () {
25262578 public void run () {
2527- if (keyMaterial != null && keyMaterial .length > 0 ) {
2528- key (keyMaterial );
2579+ if (password != null && password .length > 0 ) {
2580+ key (password );
25292581 }
25302582 }
25312583 });
25322584 shouldCloseConnection = false ;
25332585
25342586 } catch (RuntimeException ex ) {
25352587
2536- if (containsNull (password )) {
2588+ final char [] keyMaterial = getChars (password );
2589+ if (containsNull (keyMaterial )) {
25372590 keyDatabase (hook , new Runnable () {
25382591 public void run () {
25392592 if (password != null ) {
2540- key_mutf8 (password );
2593+ key_mutf8 (keyMaterial );
25412594 }
25422595 }
25432596 });
2544- if (keyMaterial != null && keyMaterial .length > 0 ) {
2545- rekey (keyMaterial );
2597+ if (password != null && password .length > 0 ) {
2598+ rekey (password );
25462599 }
25472600 shouldCloseConnection = false ;
25482601 } else {
25492602 throw ex ;
25502603 }
2604+ if (keyMaterial != null && keyMaterial .length > 0 ) {
2605+ Arrays .fill (keyMaterial , (char )0 );
2606+ }
25512607
25522608 } finally {
25532609 if (shouldCloseConnection ) {
@@ -2556,9 +2612,6 @@ public void run() {
25562612 mTimeClosed = getTime ();
25572613 }
25582614 }
2559- if (keyMaterial != null && keyMaterial .length > 0 ) {
2560- Arrays .fill (keyMaterial , (byte ) 0 );
2561- }
25622615 }
25632616
25642617 }
@@ -2838,6 +2891,24 @@ public synchronized void setMaxSqlCacheSize(int cacheSize) {
28382891 mMaxSqlCacheSize = cacheSize ;
28392892 }
28402893
2894+ public static byte [] getBytes (char [] data ) {
2895+ if (data == null || data .length == 0 ) return null ;
2896+ CharBuffer charBuffer = CharBuffer .wrap (data );
2897+ ByteBuffer byteBuffer = Charset .forName (KEY_ENCODING ).encode (charBuffer );
2898+ byte [] result = new byte [byteBuffer .limit ()];
2899+ byteBuffer .get (result );
2900+ return result ;
2901+ }
2902+
2903+ public static char [] getChars (byte [] data ){
2904+ if (data == null || data .length == 0 ) return null ;
2905+ ByteBuffer byteBuffer = ByteBuffer .wrap (data );
2906+ CharBuffer charBuffer = Charset .forName (KEY_ENCODING ).decode (byteBuffer );
2907+ char [] result = new char [charBuffer .limit ()];
2908+ charBuffer .get (result );
2909+ return result ;
2910+ }
2911+
28412912 private void beginTransactionWithListenerInternal (SQLiteTransactionListener transactionListener ,
28422913 SQLiteDatabaseTransactionType transactionType ) {
28432914 lockForced ();
@@ -2993,15 +3064,6 @@ private static ArrayList<Pair<String, String>> getAttachedDbs(SQLiteDatabase dbO
29933064 return attachedDbs ;
29943065 }
29953066
2996- private byte [] getBytes (char [] data ) {
2997- if (data == null || data .length == 0 ) return null ;
2998- CharBuffer charBuffer = CharBuffer .wrap (data );
2999- ByteBuffer byteBuffer = Charset .forName (KEY_ENCODING ).encode (charBuffer );
3000- byte [] result = new byte [byteBuffer .limit ()];
3001- byteBuffer .get (result );
3002- return result ;
3003- }
3004-
30053067 private Pair <Boolean , String > getResultFromPragma (String command ) {
30063068 Cursor cursor = rawQuery (command , new Object []{});
30073069 if (cursor == null ) return new Pair (false , "" );
@@ -3084,10 +3146,6 @@ private Pair<Boolean, String> getResultFromPragma(String command) {
30843146
30853147 private native int native_status (int operation , boolean reset );
30863148
3087- private native void native_key (char [] key ) throws SQLException ;
3088-
3089- private native void native_rekey (String key ) throws SQLException ;
3090-
30913149 private native void key (byte [] key ) throws SQLException ;
30923150 private native void key_mutf8 (char [] key ) throws SQLException ;
30933151 private native void rekey (byte [] key ) throws SQLException ;
0 commit comments