diff --git a/ReactNativeClient/android/app/src/main/AndroidManifest.xml b/ReactNativeClient/android/app/src/main/AndroidManifest.xml
index eb803a6d2e..fd3be6cbeb 100644
--- a/ReactNativeClient/android/app/src/main/AndroidManifest.xml
+++ b/ReactNativeClient/android/app/src/main/AndroidManifest.xml
@@ -1,67 +1,109 @@
-
-
-
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
+
+
+
+
-
-
-
-
-
-
-
+
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
diff --git a/ReactNativeClient/android/app/src/main/java/net/cozic/joplin/MainApplication.java b/ReactNativeClient/android/app/src/main/java/net/cozic/joplin/MainApplication.java
index 7f86c7b415..1924a703c0 100644
--- a/ReactNativeClient/android/app/src/main/java/net/cozic/joplin/MainApplication.java
+++ b/ReactNativeClient/android/app/src/main/java/net/cozic/joplin/MainApplication.java
@@ -2,15 +2,18 @@ package net.cozic.joplin;
import android.app.Application;
import android.content.Context;
+import android.database.CursorWindow;
+import androidx.multidex.MultiDex;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;
+import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
-import androidx.multidex.MultiDex;
+import net.cozic.joplin.share.SharePackage;
public class MainApplication extends Application implements ReactApplication {
@@ -33,7 +36,7 @@ public class MainApplication extends Application implements ReactApplication {
@SuppressWarnings("UnnecessaryLocalVariable")
List packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
- // packages.add(new MyReactNativePackage());
+ packages.add(new SharePackage());
return packages;
}
@@ -51,6 +54,18 @@ public class MainApplication extends Application implements ReactApplication {
@Override
public void onCreate() {
super.onCreate();
+
+ // To try to fix the error "Row too big to fit into CursorWindow"
+ // https://github.com/andpor/react-native-sqlite-storage/issues/364#issuecomment-526423153
+ // https://github.com/laurent22/joplin/issues/1767#issuecomment-515617991
+ try {
+ Field field = CursorWindow.class.getDeclaredField("sCursorWindowSize");
+ field.setAccessible(true);
+ field.set(null, 50 * 1024 * 1024); //the 102400 is the new size added
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}
diff --git a/ReactNativeClient/android/app/src/main/java/net/cozic/joplin/share/ShareActivity.java b/ReactNativeClient/android/app/src/main/java/net/cozic/joplin/share/ShareActivity.java
new file mode 100644
index 0000000000..4baf7b9f45
--- /dev/null
+++ b/ReactNativeClient/android/app/src/main/java/net/cozic/joplin/share/ShareActivity.java
@@ -0,0 +1,12 @@
+package net.cozic.joplin.share;
+
+import com.facebook.react.ReactActivity;
+
+public class ShareActivity extends ReactActivity {
+ @Override
+ protected String getMainComponentName() {
+ // this is the name AppRegistry will use to launch the Share View
+ return "Joplin";
+ }
+}
+
diff --git a/ReactNativeClient/android/app/src/main/java/net/cozic/joplin/share/SharePackage.java b/ReactNativeClient/android/app/src/main/java/net/cozic/joplin/share/SharePackage.java
new file mode 100644
index 0000000000..ebb61102ef
--- /dev/null
+++ b/ReactNativeClient/android/app/src/main/java/net/cozic/joplin/share/SharePackage.java
@@ -0,0 +1,184 @@
+package net.cozic.joplin.share;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.OpenableColumns;
+import android.util.Log;
+import android.webkit.MimeTypeMap;
+
+import androidx.annotation.NonNull;
+
+import com.facebook.react.ReactPackage;
+import com.facebook.react.bridge.ActivityEventListener;
+import com.facebook.react.bridge.Arguments;
+import com.facebook.react.bridge.NativeModule;
+import com.facebook.react.bridge.Promise;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReactContextBaseJavaModule;
+import com.facebook.react.bridge.ReactMethod;
+import com.facebook.react.bridge.WritableArray;
+import com.facebook.react.bridge.WritableMap;
+import com.facebook.react.uimanager.ViewManager;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class SharePackage implements ReactPackage {
+
+ @NonNull
+ @Override
+ public List createNativeModules(@NonNull ReactApplicationContext reactContext) {
+ return Collections.singletonList(new ShareModule(reactContext));
+ }
+
+ @NonNull
+ @Override
+ public List createViewManagers(@NonNull ReactApplicationContext reactContext) {
+ return Collections.emptyList();
+ }
+
+ public static class ShareModule extends ReactContextBaseJavaModule implements ActivityEventListener {
+
+ ShareModule(@NonNull ReactApplicationContext reactContext) {
+ super(reactContext);
+ reactContext.addActivityEventListener(this);
+ }
+
+ @Override
+ public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
+ }
+
+ @Override
+ public void onNewIntent(Intent intent) {
+ }
+
+ @NonNull
+ @Override
+ public String getName() {
+ return "ShareExtension";
+ }
+
+ @ReactMethod
+ public void close() {
+ Activity currentActivity = getCurrentActivity();
+ if (currentActivity != null) {
+ currentActivity.finish();
+ }
+ }
+
+ @ReactMethod
+ public void data(Promise promise) {
+ promise.resolve(processIntent());
+ }
+
+ private WritableMap processIntent() {
+ Activity currentActivity = getCurrentActivity();
+ WritableMap map = Arguments.createMap();
+
+ if (currentActivity == null) {
+ return null;
+ }
+
+ Intent intent = currentActivity.getIntent();
+
+ if (intent == null || !(Intent.ACTION_SEND.equals(intent.getAction())
+ || Intent.ACTION_SEND_MULTIPLE.equals(intent.getAction()))) {
+ return null;
+ }
+
+ String type = intent.getType() == null ? "" : intent.getType();
+ map.putString("type", type);
+ map.putString("title", getTitle(intent));
+ map.putString("text", intent.getStringExtra(Intent.EXTRA_TEXT));
+
+ WritableArray resources = Arguments.createArray();
+
+ if (Intent.ACTION_SEND.equals(intent.getAction())) {
+ if (intent.hasExtra(Intent.EXTRA_STREAM)) {
+ resources.pushMap(getFileData(intent.getParcelableExtra(Intent.EXTRA_STREAM)));
+ }
+ } else if (Intent.ACTION_SEND_MULTIPLE.equals(intent.getAction())) {
+ ArrayList imageUris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
+ if (imageUris != null) {
+ for (Uri uri : imageUris) {
+ resources.pushMap(getFileData(uri));
+ }
+ }
+ }
+
+ map.putArray("resources", resources);
+ return map;
+ }
+
+ private String getTitle(Intent intent) {
+ if (intent.hasExtra(Intent.EXTRA_SUBJECT)) {
+ return intent.getStringExtra(Intent.EXTRA_SUBJECT);
+ } else if (intent.hasExtra(Intent.EXTRA_TITLE)) {
+ return intent.getStringExtra(Intent.EXTRA_TITLE);
+ } else {
+ return null;
+ }
+ }
+
+ private WritableMap getFileData(Uri uri) {
+ Log.d("joplin", "getFileData: " + uri);
+
+ WritableMap imageData = Arguments.createMap();
+
+ ContentResolver contentResolver = getCurrentActivity().getContentResolver();
+ String mimeType = contentResolver.getType(uri);
+ String name = getFileName(uri, contentResolver);
+
+ if (mimeType == null || mimeType.equals("image/*")) {
+ String extension = getFileExtension(name);
+ mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
+ }
+
+ imageData.putString("uri", uri.toString());
+ imageData.putString("name", name);
+ imageData.putString("mimeType", mimeType);
+ return imageData;
+ }
+
+ private String getFileName(Uri uri, ContentResolver contentResolver) {
+ if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
+ File file = new File(uri.getPath());
+ return file.getName();
+ } else if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
+ String name = null;
+ Cursor cursor = contentResolver.query(uri, null, null, null, null);
+ if (cursor != null) {
+ try {
+ if (cursor.moveToFirst()) {
+ int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
+ name = cursor.getString(nameIndex);
+ }
+ } finally {
+ cursor.close();
+ }
+ }
+ return name;
+ } else {
+ Log.w("joplin", "Unknown URI scheme: " + uri.getScheme());
+ return null;
+ }
+ }
+
+ private String getFileExtension(String file) {
+ if (file == null) {
+ return null;
+ }
+ String ext = null;
+ int i = file.lastIndexOf('.');
+ if (i > 0) {
+ ext = file.substring(i + 1);
+ }
+ return ext;
+ }
+ }
+}