Skip to content

Commit

Permalink
plugin: add app.datadir API to get writable path
Browse files Browse the repository at this point in the history
Adds app.datadir to the bridge to access a writable persistent path
from the nodejs-mobile runtime, which should be the FilesDir on
Android and the NSDocumentDirectory on iOS.
Also sets the os.tmpdir() to the CacheDir on Android.
  • Loading branch information
jaimecbernardo committed Aug 9, 2018
1 parent 10c1d3e commit 1116698
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 0 deletions.
11 changes: 11 additions & 0 deletions android/src/main/cpp/native-lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ Java_com_janeasystems_rn_1nodejs_1mobile_RNNodeJsMobileModule_getCurrentABIName(
return env->NewStringUTF(CURRENT_ABI_NAME);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_janeasystems_rn_1nodejs_1mobile_RNNodeJsMobileModule_registerNodeDataDirPath(
JNIEnv *env,
jobject /* this */,
jstring dataDir) {
const char* nativeDataDir = env->GetStringUTFChars(dataDir, 0);
rn_register_node_data_dir_path(nativeDataDir);
env->ReleaseStringUTFChars(dataDir, nativeDataDir);
}

#define APPNAME "RNBRIDGE"

void rcv_message(const char* channel_name, const char* msg) {
Expand Down
24 changes: 24 additions & 0 deletions android/src/main/cpp/rn-bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,18 @@ class Channel {
};
};

char* datadir_path = NULL;
/*
* Called by the react-native plug-in to register the datadir,
* representing a writable path. Expected to be called once,
* while the plug-in initializes.
*/
void rn_register_node_data_dir_path(const char* path) {
size_t pathLength = strlen(path);
datadir_path = (char*)calloc(sizeof(char), pathLength + 1);
strncpy(datadir_path, path, pathLength);
}

rn_bridge_cb embedder_callback=NULL;

/**
Expand Down Expand Up @@ -304,6 +316,17 @@ napi_value Method_SendMessage(napi_env env, napi_callback_info info) {
return nullptr;
}

/**
* Get the registered datadir
*/
napi_value Method_GetDataDir(napi_env env, napi_callback_info info) {
NAPI_ASSERT(env, datadir_path!=NULL, "Data directory not set from native side.");
napi_value return_datadir;
size_t str_len = strlen(datadir_path);
NAPI_CALL(env, napi_create_string_utf8(env, datadir_path, str_len, &return_datadir));
return return_datadir;
}

#define DECLARE_NAPI_METHOD(name, func) \
{ name, 0, func, 0, 0, 0, napi_default, 0 }

Expand All @@ -312,6 +335,7 @@ napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor properties[] = {
DECLARE_NAPI_METHOD("sendMessage", Method_SendMessage),
DECLARE_NAPI_METHOD("registerChannel", Method_RegisterChannel),
DECLARE_NAPI_METHOD("getDataDir", Method_GetDataDir),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(*properties), properties));
return exports;
Expand Down
1 change: 1 addition & 0 deletions android/src/main/cpp/rn-bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
typedef void (*rn_bridge_cb)(const char* channelName, const char* message);
void rn_register_bridge_cb(rn_bridge_cb);
void rn_bridge_notify(const char* channelName, const char *message);
void rn_register_node_data_dir_path(const char* path);

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.SharedPreferences;
import android.system.Os;
import android.system.ErrnoException;

import java.io.*;
import java.util.*;
Expand Down Expand Up @@ -74,6 +76,16 @@ public RNNodeJsMobileModule(ReactApplicationContext reactContext) {
trashDirPath = filesDirPath + "/" + TRASH_DIR;
nativeAssetsPath = BUILTIN_NATIVE_ASSETS_PREFIX + getCurrentABIName();

// Sets the TMPDIR environment to the cacheDir, to be used in Node as os.tmpdir
try {
Os.setenv("TMPDIR", reactContext.getCacheDir().getAbsolutePath(), true);
} catch (ErrnoException e) {
e.printStackTrace();
}

// Register the filesDir as the Node data dir.
registerNodeDataDirPath(filesDirPath);

asyncInit();
}

Expand Down Expand Up @@ -241,6 +253,8 @@ public void run() {
}
}

public native void registerNodeDataDirPath(String dataDir);

public native String getCurrentABIName();

public native Integer startNodeWithArguments(String[] arguments, String modulesPath, boolean option_redirectOutputToLogcat);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ class SystemEventLock {
class SystemChannel extends ChannelSuper {
constructor(name) {
super(name);
// datadir should not change during runtime, so we cache it.
this._cacheDataDir = null;
};

emitWrapper(type) {
Expand Down Expand Up @@ -163,6 +165,13 @@ class SystemChannel extends ChannelSuper {
this.emitWrapper(data);
};

// Get a writable data directory for persistent file storage.
datadir() {
if (this._cacheDataDir === null) {
this._cacheDataDir = NativeBridge.getDataDir();
}
return this._cacheDataDir;
}
};
/**
* Manage the registered channels to emit events/messages received by the
Expand Down
3 changes: 3 additions & 0 deletions ios/NodeRunner.mm
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ - (id)init {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onResume)
name:UIApplicationWillEnterForegroundNotification object:nil];
// Register the Documents Directory as the node dataDir.
NSString* nodeDataDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
rn_register_node_data_dir_path([nodeDataDir UTF8String]);
return self;
}

Expand Down
24 changes: 24 additions & 0 deletions ios/rn-bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,18 @@ class Channel {
};
};

char* datadir_path = NULL;
/*
* Called by the react-native plug-in to register the datadir,
* representing a writable path. Expected to be called once,
* while the plug-in initializes.
*/
void rn_register_node_data_dir_path(const char* path) {
size_t pathLength = strlen(path);
datadir_path = (char*)calloc(sizeof(char), pathLength + 1);
strncpy(datadir_path, path, pathLength);
}

rn_bridge_cb embedder_callback=NULL;

/**
Expand Down Expand Up @@ -304,6 +316,17 @@ napi_value Method_SendMessage(napi_env env, napi_callback_info info) {
return nullptr;
}

/**
* Get the registered datadir
*/
napi_value Method_GetDataDir(napi_env env, napi_callback_info info) {
NAPI_ASSERT(env, datadir_path!=NULL, "Data directory not set from native side.");
napi_value return_datadir;
size_t str_len = strlen(datadir_path);
NAPI_CALL(env, napi_create_string_utf8(env, datadir_path, str_len, &return_datadir));
return return_datadir;
}

#define DECLARE_NAPI_METHOD(name, func) \
{ name, 0, func, 0, 0, 0, napi_default, 0 }

Expand All @@ -312,6 +335,7 @@ napi_value Init(napi_env env, napi_value exports) {
napi_property_descriptor properties[] = {
DECLARE_NAPI_METHOD("sendMessage", Method_SendMessage),
DECLARE_NAPI_METHOD("registerChannel", Method_RegisterChannel),
DECLARE_NAPI_METHOD("getDataDir", Method_GetDataDir),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(properties) / sizeof(*properties), properties));
return exports;
Expand Down
1 change: 1 addition & 0 deletions ios/rn-bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
typedef void (*rn_bridge_cb)(const char* channelName, const char* message);
void rn_register_bridge_cb(rn_bridge_cb);
void rn_bridge_notify(const char* channelName, const char *message);
void rn_register_node_data_dir_path(const char* path);

#endif

0 comments on commit 1116698

Please sign in to comment.