refactor(AsyncStorage): move android files from react-native-github

Summary:
## Changelog:
[Android] [Removed] - Removed AsyncStorage module

Reviewed By: lunaleaps

Differential Revision: D40175995

fbshipit-source-id: b583579b8c2fa6c502f265ffe464b81672bd7da5
This commit is contained in:
Ruslan Lesiutin
2022-10-31 14:39:19 -07:00
committed by Facebook GitHub Bot
parent 83e2126b57
commit 5738fe6426
9 changed files with 0 additions and 1136 deletions
@@ -1,125 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.modules.storage;
import static com.facebook.react.modules.storage.ReactDatabaseSupplier.KEY_COLUMN;
import static com.facebook.react.modules.storage.ReactDatabaseSupplier.TABLE_CATALYST;
import static com.facebook.react.modules.storage.ReactDatabaseSupplier.VALUE_COLUMN;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.ReadableArray;
import java.util.Arrays;
import java.util.Iterator;
import org.json.JSONException;
import org.json.JSONObject;
/** Helper for database operations. */
public class AsyncLocalStorageUtil {
/**
* Build the String required for an SQL select statement: WHERE key IN (?, ?, ..., ?) without
* 'WHERE' and with selectionCount '?'
*/
/* package */ static String buildKeySelection(int selectionCount) {
String[] list = new String[selectionCount];
Arrays.fill(list, "?");
return KEY_COLUMN + " IN (" + TextUtils.join(", ", list) + ")";
}
/**
* Build the String[] arguments needed for an SQL selection, i.e.: {a, b, c} to be used in the SQL
* select statement: WHERE key in (?, ?, ?)
*/
/* package */ static String[] buildKeySelectionArgs(ReadableArray keys, int start, int count) {
String[] selectionArgs = new String[count];
for (int keyIndex = 0; keyIndex < count; keyIndex++) {
selectionArgs[keyIndex] = keys.getString(start + keyIndex);
}
return selectionArgs;
}
/** Returns the value of the given key, or null if not found. */
public static @Nullable String getItemImpl(SQLiteDatabase db, String key) {
String[] columns = {VALUE_COLUMN};
String[] selectionArgs = {key};
Cursor cursor =
db.query(TABLE_CATALYST, columns, KEY_COLUMN + "=?", selectionArgs, null, null, null);
try {
if (!cursor.moveToFirst()) {
return null;
} else {
return cursor.getString(0);
}
} finally {
cursor.close();
}
}
/** Sets the value for the key given, returns true if successful, false otherwise. */
/* package */ static boolean setItemImpl(SQLiteDatabase db, String key, String value) {
ContentValues contentValues = new ContentValues();
contentValues.put(KEY_COLUMN, key);
contentValues.put(VALUE_COLUMN, value);
long inserted =
db.insertWithOnConflict(
TABLE_CATALYST, null, contentValues, SQLiteDatabase.CONFLICT_REPLACE);
return (-1 != inserted);
}
/**
* Does the actual merge of the (key, value) pair with the value stored in the database. NB: This
* assumes that a database lock is already in effect!
*
* @return the errorCode of the operation
*/
/* package */ static boolean mergeImpl(SQLiteDatabase db, String key, String value)
throws JSONException {
String oldValue = getItemImpl(db, key);
String newValue;
if (oldValue == null) {
newValue = value;
} else {
JSONObject oldJSON = new JSONObject(oldValue);
JSONObject newJSON = new JSONObject(value);
deepMergeInto(oldJSON, newJSON);
newValue = oldJSON.toString();
}
return setItemImpl(db, key, newValue);
}
/**
* Merges two {@link JSONObject}s. The newJSON object will be merged with the oldJSON object by
* either overriding its values, or merging them (if the values of the same key in both objects
* are of type {@link JSONObject}). oldJSON will contain the result of this merge.
*/
private static void deepMergeInto(JSONObject oldJSON, JSONObject newJSON) throws JSONException {
Iterator<?> keys = newJSON.keys();
while (keys.hasNext()) {
String key = (String) keys.next();
JSONObject newJSONObject = newJSON.optJSONObject(key);
JSONObject oldJSONObject = oldJSON.optJSONObject(key);
if (newJSONObject != null && oldJSONObject != null) {
deepMergeInto(oldJSONObject, newJSONObject);
oldJSON.put(key, oldJSONObject);
} else {
oldJSON.put(key, newJSON.get(key));
}
}
}
}
@@ -1,38 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.modules.storage;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.WritableMap;
/** Helper class for database errors. */
public class AsyncStorageErrorUtil {
/** Create Error object to be passed back to the JS callback. */
/* package */ static WritableMap getError(@Nullable String key, String errorMessage) {
WritableMap errorMap = Arguments.createMap();
errorMap.putString("message", errorMessage);
if (key != null) {
errorMap.putString("key", key);
}
return errorMap;
}
/* package */ static WritableMap getInvalidKeyError(@Nullable String key) {
return getError(key, "Invalid key");
}
/* package */ static WritableMap getInvalidValueError(@Nullable String key) {
return getError(key, "Invalid Value");
}
/* package */ static WritableMap getDBError(@Nullable String key) {
return getError(key, "Database Error");
}
}
@@ -1,433 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.modules.storage;
import static com.facebook.react.modules.storage.ReactDatabaseSupplier.KEY_COLUMN;
import static com.facebook.react.modules.storage.ReactDatabaseSupplier.TABLE_CATALYST;
import static com.facebook.react.modules.storage.ReactDatabaseSupplier.VALUE_COLUMN;
import android.database.Cursor;
import android.database.sqlite.SQLiteStatement;
import android.os.AsyncTask;
import com.facebook.common.logging.FLog;
import com.facebook.fbreact.specs.NativeAsyncSQLiteDBStorageSpec;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.GuardedAsyncTask;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.common.annotations.VisibleForTesting;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.modules.common.ModuleDataCleaner;
import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.concurrent.Executor;
@ReactModule(name = AsyncStorageModule.NAME)
public final class AsyncStorageModule extends NativeAsyncSQLiteDBStorageSpec
implements ModuleDataCleaner.Cleanable {
public static final String NAME = "AsyncSQLiteDBStorage";
// SQL variable number limit, defined by SQLITE_LIMIT_VARIABLE_NUMBER:
// https://raw.githubusercontent.com/android/platform_external_sqlite/master/dist/sqlite3.c
private static final int MAX_SQL_KEYS = 999;
private ReactDatabaseSupplier mReactDatabaseSupplier;
private boolean mShuttingDown = false;
// Adapted from
// https://android.googlesource.com/platform/frameworks/base.git/+/1488a3a19d4681a41fb45570c15e14d99db1cb66/core/java/android/os/AsyncTask.java#237
private class SerialExecutor implements Executor {
private final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
private Runnable mActive;
private final Executor executor;
SerialExecutor(Executor executor) {
this.executor = executor;
}
public synchronized void execute(final Runnable r) {
mTasks.offer(
new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
}
synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
executor.execute(mActive);
}
}
}
private final SerialExecutor executor;
public AsyncStorageModule(ReactApplicationContext reactContext) {
this(reactContext, AsyncTask.THREAD_POOL_EXECUTOR);
}
@VisibleForTesting
AsyncStorageModule(ReactApplicationContext reactContext, Executor executor) {
super(reactContext);
this.executor = new SerialExecutor(executor);
mReactDatabaseSupplier = ReactDatabaseSupplier.getInstance(reactContext);
}
@Override
public String getName() {
return NAME;
}
@Override
public void initialize() {
super.initialize();
mShuttingDown = false;
}
@Override
public void invalidate() {
mShuttingDown = true;
}
@Override
public void clearSensitiveData() {
// Clear local storage. If fails, crash, since the app is potentially in a bad state and could
// cause a privacy violation. We're still not recovering from this well, but at least the error
// will be reported to the server.
mReactDatabaseSupplier.clearAndCloseDatabase();
}
/**
* Given an array of keys, this returns a map of (key, value) pairs for the keys found, and (key,
* null) for the keys that haven't been found.
*/
@Override
public void multiGet(final ReadableArray keys, final Callback callback) {
if (keys == null) {
callback.invoke(AsyncStorageErrorUtil.getInvalidKeyError(null), null);
return;
}
new GuardedAsyncTask<Void, Void>(getReactApplicationContext()) {
@Override
protected void doInBackgroundGuarded(Void... params) {
if (!ensureDatabase()) {
callback.invoke(AsyncStorageErrorUtil.getDBError(null), null);
return;
}
String[] columns = {KEY_COLUMN, VALUE_COLUMN};
HashSet<String> keysRemaining = new HashSet<>();
WritableArray data = Arguments.createArray();
for (int keyStart = 0; keyStart < keys.size(); keyStart += MAX_SQL_KEYS) {
int keyCount = Math.min(keys.size() - keyStart, MAX_SQL_KEYS);
Cursor cursor =
mReactDatabaseSupplier
.get()
.query(
TABLE_CATALYST,
columns,
AsyncLocalStorageUtil.buildKeySelection(keyCount),
AsyncLocalStorageUtil.buildKeySelectionArgs(keys, keyStart, keyCount),
null,
null,
null);
keysRemaining.clear();
try {
if (cursor.getCount() != keys.size()) {
// some keys have not been found - insert them with null into the final array
for (int keyIndex = keyStart; keyIndex < keyStart + keyCount; keyIndex++) {
keysRemaining.add(keys.getString(keyIndex));
}
}
if (cursor.moveToFirst()) {
do {
WritableArray row = Arguments.createArray();
row.pushString(cursor.getString(0));
row.pushString(cursor.getString(1));
data.pushArray(row);
keysRemaining.remove(cursor.getString(0));
} while (cursor.moveToNext());
}
} catch (Exception e) {
FLog.w(ReactConstants.TAG, e.getMessage(), e);
callback.invoke(AsyncStorageErrorUtil.getError(null, e.getMessage()), null);
return;
} finally {
cursor.close();
}
for (String key : keysRemaining) {
WritableArray row = Arguments.createArray();
row.pushString(key);
row.pushNull();
data.pushArray(row);
}
keysRemaining.clear();
}
callback.invoke(null, data);
}
}.executeOnExecutor(executor);
}
/**
* Inserts multiple (key, value) pairs. If one or more of the pairs cannot be inserted, this will
* return AsyncLocalStorageFailure, but all other pairs will have been inserted. The insertion
* will replace conflicting (key, value) pairs.
*/
@Override
public void multiSet(final ReadableArray keyValueArray, final Callback callback) {
if (keyValueArray.size() == 0) {
callback.invoke(AsyncStorageErrorUtil.getInvalidKeyError(null));
return;
}
new GuardedAsyncTask<Void, Void>(getReactApplicationContext()) {
@Override
protected void doInBackgroundGuarded(Void... params) {
if (!ensureDatabase()) {
callback.invoke(AsyncStorageErrorUtil.getDBError(null));
return;
}
String sql = "INSERT OR REPLACE INTO " + TABLE_CATALYST + " VALUES (?, ?);";
SQLiteStatement statement = mReactDatabaseSupplier.get().compileStatement(sql);
WritableMap error = null;
try {
mReactDatabaseSupplier.get().beginTransaction();
for (int idx = 0; idx < keyValueArray.size(); idx++) {
if (keyValueArray.getArray(idx).size() != 2) {
error = AsyncStorageErrorUtil.getInvalidValueError(null);
return;
}
if (keyValueArray.getArray(idx).getString(0) == null) {
error = AsyncStorageErrorUtil.getInvalidKeyError(null);
return;
}
if (keyValueArray.getArray(idx).getString(1) == null) {
error = AsyncStorageErrorUtil.getInvalidValueError(null);
return;
}
statement.clearBindings();
statement.bindString(1, keyValueArray.getArray(idx).getString(0));
statement.bindString(2, keyValueArray.getArray(idx).getString(1));
statement.execute();
}
mReactDatabaseSupplier.get().setTransactionSuccessful();
} catch (Exception e) {
FLog.w(ReactConstants.TAG, e.getMessage(), e);
error = AsyncStorageErrorUtil.getError(null, e.getMessage());
} finally {
try {
mReactDatabaseSupplier.get().endTransaction();
} catch (Exception e) {
FLog.w(ReactConstants.TAG, e.getMessage(), e);
if (error == null) {
error = AsyncStorageErrorUtil.getError(null, e.getMessage());
}
}
}
if (error != null) {
callback.invoke(error);
} else {
callback.invoke();
}
}
}.executeOnExecutor(executor);
}
/** Removes all rows of the keys given. */
@Override
public void multiRemove(final ReadableArray keys, final Callback callback) {
if (keys.size() == 0) {
callback.invoke(AsyncStorageErrorUtil.getInvalidKeyError(null));
return;
}
new GuardedAsyncTask<Void, Void>(getReactApplicationContext()) {
@Override
protected void doInBackgroundGuarded(Void... params) {
if (!ensureDatabase()) {
callback.invoke(AsyncStorageErrorUtil.getDBError(null));
return;
}
WritableMap error = null;
try {
mReactDatabaseSupplier.get().beginTransaction();
for (int keyStart = 0; keyStart < keys.size(); keyStart += MAX_SQL_KEYS) {
int keyCount = Math.min(keys.size() - keyStart, MAX_SQL_KEYS);
mReactDatabaseSupplier
.get()
.delete(
TABLE_CATALYST,
AsyncLocalStorageUtil.buildKeySelection(keyCount),
AsyncLocalStorageUtil.buildKeySelectionArgs(keys, keyStart, keyCount));
}
mReactDatabaseSupplier.get().setTransactionSuccessful();
} catch (Exception e) {
FLog.w(ReactConstants.TAG, e.getMessage(), e);
error = AsyncStorageErrorUtil.getError(null, e.getMessage());
} finally {
try {
mReactDatabaseSupplier.get().endTransaction();
} catch (Exception e) {
FLog.w(ReactConstants.TAG, e.getMessage(), e);
if (error == null) {
error = AsyncStorageErrorUtil.getError(null, e.getMessage());
}
}
}
if (error != null) {
callback.invoke(error);
} else {
callback.invoke();
}
}
}.executeOnExecutor(executor);
}
/**
* Given an array of (key, value) pairs, this will merge the given values with the stored values
* of the given keys, if they exist.
*/
@Override
public void multiMerge(final ReadableArray keyValueArray, final Callback callback) {
new GuardedAsyncTask<Void, Void>(getReactApplicationContext()) {
@Override
protected void doInBackgroundGuarded(Void... params) {
if (!ensureDatabase()) {
callback.invoke(AsyncStorageErrorUtil.getDBError(null));
return;
}
WritableMap error = null;
try {
mReactDatabaseSupplier.get().beginTransaction();
for (int idx = 0; idx < keyValueArray.size(); idx++) {
if (keyValueArray.getArray(idx).size() != 2) {
error = AsyncStorageErrorUtil.getInvalidValueError(null);
return;
}
if (keyValueArray.getArray(idx).getString(0) == null) {
error = AsyncStorageErrorUtil.getInvalidKeyError(null);
return;
}
if (keyValueArray.getArray(idx).getString(1) == null) {
error = AsyncStorageErrorUtil.getInvalidValueError(null);
return;
}
if (!AsyncLocalStorageUtil.mergeImpl(
mReactDatabaseSupplier.get(),
keyValueArray.getArray(idx).getString(0),
keyValueArray.getArray(idx).getString(1))) {
error = AsyncStorageErrorUtil.getDBError(null);
return;
}
}
mReactDatabaseSupplier.get().setTransactionSuccessful();
} catch (Exception e) {
FLog.w(ReactConstants.TAG, e.getMessage(), e);
error = AsyncStorageErrorUtil.getError(null, e.getMessage());
} finally {
try {
mReactDatabaseSupplier.get().endTransaction();
} catch (Exception e) {
FLog.w(ReactConstants.TAG, e.getMessage(), e);
if (error == null) {
error = AsyncStorageErrorUtil.getError(null, e.getMessage());
}
}
}
if (error != null) {
callback.invoke(error);
} else {
callback.invoke();
}
}
}.executeOnExecutor(executor);
}
/** Clears the database. */
@Override
public void clear(final Callback callback) {
new GuardedAsyncTask<Void, Void>(getReactApplicationContext()) {
@Override
protected void doInBackgroundGuarded(Void... params) {
if (!mReactDatabaseSupplier.ensureDatabase()) {
callback.invoke(AsyncStorageErrorUtil.getDBError(null));
return;
}
try {
mReactDatabaseSupplier.clear();
callback.invoke();
} catch (Exception e) {
FLog.w(ReactConstants.TAG, e.getMessage(), e);
callback.invoke(AsyncStorageErrorUtil.getError(null, e.getMessage()));
}
}
}.executeOnExecutor(executor);
}
/** Returns an array with all keys from the database. */
@Override
public void getAllKeys(final Callback callback) {
new GuardedAsyncTask<Void, Void>(getReactApplicationContext()) {
@Override
protected void doInBackgroundGuarded(Void... params) {
if (!ensureDatabase()) {
callback.invoke(AsyncStorageErrorUtil.getDBError(null), null);
return;
}
WritableArray data = Arguments.createArray();
String[] columns = {KEY_COLUMN};
Cursor cursor =
mReactDatabaseSupplier
.get()
.query(TABLE_CATALYST, columns, null, null, null, null, null);
try {
if (cursor.moveToFirst()) {
do {
data.pushString(cursor.getString(0));
} while (cursor.moveToNext());
}
} catch (Exception e) {
FLog.w(ReactConstants.TAG, e.getMessage(), e);
callback.invoke(AsyncStorageErrorUtil.getError(null, e.getMessage()), null);
return;
} finally {
cursor.close();
}
callback.invoke(null, data);
}
}.executeOnExecutor(executor);
}
/** Verify the database is open for reads and writes. */
private boolean ensureDatabase() {
return !mShuttingDown && mReactDatabaseSupplier.ensureDatabase();
}
}
@@ -1,25 +0,0 @@
load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library")
rn_android_library(
name = "storage",
srcs = glob(["**/*.java"]),
autoglob = False,
labels = [
"pfh:ReactNative_CommonInfrastructurePlaceholder",
],
language = "JAVA",
visibility = [
"PUBLIC",
],
deps = [
react_native_dep("third-party/android/androidx:annotation"),
react_native_dep("libraries/fbcore/src/main/java/com/facebook/common/logging:logging"),
react_native_dep("third-party/java/infer-annotations:infer-annotations"),
react_native_dep("third-party/java/jsr-305:jsr-305"),
react_native_target("java/com/facebook/react/bridge:bridge"),
react_native_target("java/com/facebook/react/common:common"),
react_native_target("java/com/facebook/react/module/annotations:annotations"),
react_native_target("java/com/facebook/react/modules/common:common"),
],
exported_deps = [react_native_root_target(":FBReactNativeSpec")],
)
@@ -1,163 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.react.modules.storage;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import androidx.annotation.Nullable;
import com.facebook.common.logging.FLog;
import com.facebook.react.common.ReactConstants;
/**
* Database supplier of the database used by react native. This creates, opens and deletes the
* database as necessary.
*/
public class ReactDatabaseSupplier extends SQLiteOpenHelper {
// VisibleForTesting
public static final String DATABASE_NAME = "RKStorage";
private static final int DATABASE_VERSION = 1;
private static final int SLEEP_TIME_MS = 30;
static final String TABLE_CATALYST = "catalystLocalStorage";
static final String KEY_COLUMN = "key";
static final String VALUE_COLUMN = "value";
static final String VERSION_TABLE_CREATE =
"CREATE TABLE "
+ TABLE_CATALYST
+ " ("
+ KEY_COLUMN
+ " TEXT PRIMARY KEY, "
+ VALUE_COLUMN
+ " TEXT NOT NULL"
+ ")";
private static @Nullable ReactDatabaseSupplier sReactDatabaseSupplierInstance;
private Context mContext;
private @Nullable SQLiteDatabase mDb;
private long mMaximumDatabaseSize = 6L * 1024L * 1024L; // 6 MB in bytes
private ReactDatabaseSupplier(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
mContext = context;
}
public static ReactDatabaseSupplier getInstance(Context context) {
if (sReactDatabaseSupplierInstance == null) {
sReactDatabaseSupplierInstance = new ReactDatabaseSupplier(context.getApplicationContext());
}
return sReactDatabaseSupplierInstance;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(VERSION_TABLE_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion != newVersion) {
deleteDatabase();
onCreate(db);
}
}
/** Verify the database exists and is open. */
/* package */ synchronized boolean ensureDatabase() {
if (mDb != null && mDb.isOpen()) {
return true;
}
// Sometimes retrieving the database fails. We do 2 retries: first without database deletion
// and then with deletion.
SQLiteException lastSQLiteException = null;
for (int tries = 0; tries < 2; tries++) {
try {
if (tries > 0) {
deleteDatabase();
}
mDb = getWritableDatabase();
break;
} catch (SQLiteException e) {
lastSQLiteException = e;
}
// Wait before retrying.
try {
Thread.sleep(SLEEP_TIME_MS);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
}
}
if (mDb == null) {
throw lastSQLiteException;
}
// This is a sane limit to protect the user from the app storing too much data in the database.
// This also protects the database from filling up the disk cache and becoming malformed
// (endTransaction() calls will throw an exception, not rollback, and leave the db malformed).
mDb.setMaximumSize(mMaximumDatabaseSize);
return true;
}
/** Create and/or open the database. */
public synchronized SQLiteDatabase get() {
ensureDatabase();
return mDb;
}
public synchronized void clearAndCloseDatabase() throws RuntimeException {
try {
clear();
closeDatabase();
FLog.d(ReactConstants.TAG, "Cleaned " + DATABASE_NAME);
} catch (Exception e) {
// Clearing the database has failed, delete it instead.
if (deleteDatabase()) {
FLog.d(ReactConstants.TAG, "Deleted Local Database " + DATABASE_NAME);
return;
}
// Everything failed, throw
throw new RuntimeException("Clearing and deleting database " + DATABASE_NAME + " failed");
}
}
/* package */ synchronized void clear() {
get().delete(TABLE_CATALYST, null, null);
}
/**
* Sets the maximum size the database will grow to. The maximum size cannot be set below the
* current size.
*/
public synchronized void setMaximumSize(long size) {
mMaximumDatabaseSize = size;
if (mDb != null) {
mDb.setMaximumSize(mMaximumDatabaseSize);
}
}
private synchronized boolean deleteDatabase() {
closeDatabase();
return mContext.deleteDatabase(DATABASE_NAME);
}
private synchronized void closeDatabase() {
if (mDb != null && mDb.isOpen()) {
mDb.close();
mDb = null;
}
}
// For testing purposes only!
public static void deleteInstance() {
sReactDatabaseSupplierInstance = null;
}
}
@@ -46,7 +46,6 @@ rn_android_library(
react_native_target("java/com/facebook/react/modules/permissions:permissions"),
react_native_target("java/com/facebook/react/modules/share:share"),
react_native_target("java/com/facebook/react/modules/statusbar:statusbar"),
react_native_target("java/com/facebook/react/modules/storage:storage"),
react_native_target("java/com/facebook/react/modules/sound:sound"),
react_native_target("java/com/facebook/react/modules/toast:toast"),
react_native_target("java/com/facebook/react/modules/vibration:vibration"),
@@ -33,7 +33,6 @@ import com.facebook.react.modules.permissions.PermissionsModule;
import com.facebook.react.modules.share.ShareModule;
import com.facebook.react.modules.sound.SoundManagerModule;
import com.facebook.react.modules.statusbar.StatusBarModule;
import com.facebook.react.modules.storage.AsyncStorageModule;
import com.facebook.react.modules.toast.ToastModule;
import com.facebook.react.modules.vibration.VibrationModule;
import com.facebook.react.modules.websocket.WebSocketModule;
@@ -69,7 +68,6 @@ import java.util.Map;
AppStateModule.class,
BlobModule.class,
FileReaderModule.class,
AsyncStorageModule.class,
ClipboardModule.class,
DialogModule.class,
FrescoModule.class,
@@ -111,8 +109,6 @@ public class MainReactPackage extends TurboReactPackage {
return new BlobModule(context);
case FileReaderModule.NAME:
return new FileReaderModule(context);
case AsyncStorageModule.NAME:
return new AsyncStorageModule(context);
case ClipboardModule.NAME:
return new ClipboardModule(context);
case DialogModule.NAME:
@@ -193,7 +189,6 @@ public class MainReactPackage extends TurboReactPackage {
AppStateModule.class,
BlobModule.class,
FileReaderModule.class,
AsyncStorageModule.class,
ClipboardModule.class,
DialogModule.class,
FrescoModule.class,