From ebb1364de262972fcb169633a6cfecdaf2b302f7 Mon Sep 17 00:00:00 2001 From: Esteban Fuentealba Date: Fri, 22 Jul 2016 12:57:50 -0400 Subject: [PATCH 01/10] added base64 files in URL --- README.md | 11 ++- android/react-native-share.iml | 17 +++-- android/src/main/java/cl/json/FileBase64.java | 74 +++++++++++++++++++ .../src/main/java/cl/json/RNShareModule.java | 57 +++++++++++--- index.js | 31 +++++++- 5 files changed, 169 insertions(+), 21 deletions(-) create mode 100644 android/src/main/java/cl/json/FileBase64.java diff --git a/README.md b/README.md index 93d9b810..ec3f1af7 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Share Social , Sending Simple Data to Other Apps #### Android 1. `npm install react-native-share --save` -2. Open up `android/app/src/main/java/[...]/MainActivity.java` +2. Open up `android/app/src/main/java/[...]/MainApplication.java` - Add `import cl.json.RNSharePackage;` to the imports at the top of the file - Add `new RNSharePackage()` to the list returned by the `getPackages()` method 3. Append the following lines to `android/settings.gradle`: @@ -45,6 +45,15 @@ Share Social , Sending Simple Data to Other Apps - Add `new RNSharePackage()` to the `List` returned by the `Packages` method + + +- url (string) - a URL to share +- message (string) - a message to share +- subject (optional) (string) - a subject for the message +- excludedActivityTypes (optional) (array) - the activites to exclude from the ActionSheet + + + ## Usage ```javascript diff --git a/android/react-native-share.iml b/android/react-native-share.iml index 81e86c34..2a9cbe1f 100644 --- a/android/react-native-share.iml +++ b/android/react-native-share.iml @@ -62,13 +62,6 @@ - - - - - - - @@ -76,8 +69,16 @@ + + + + + + + + @@ -91,11 +92,13 @@ + + diff --git a/android/src/main/java/cl/json/FileBase64.java b/android/src/main/java/cl/json/FileBase64.java new file mode 100644 index 00000000..acd29d0d --- /dev/null +++ b/android/src/main/java/cl/json/FileBase64.java @@ -0,0 +1,74 @@ +package cl.json; + +import android.content.Intent; +import android.net.Uri; +import android.os.Environment; +import android.util.Base64; +import android.webkit.MimeTypeMap; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.StringReader; +import java.net.URI; + +/** + * Created by disenodosbbcl on 22-07-16. + */ +public class FileBase64 { + private String url; + private URI uri; + private String type = "*/*"; + private String extension = ""; + + public FileBase64(String url){ + this.url = url; + this.uri = URI.create(this.url); + } + private static String getMimeType(String url) { + String type = "*/*"; + String extension = MimeTypeMap.getFileExtensionFromUrl(url); + if (extension != null) { + type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); + } + return type; + } + public boolean isFile() { + return this.isBase64File(); + } + public boolean isBase64File() { + if(uri.getScheme().equals("data")) { + this.type = this.uri.getSchemeSpecificPart().substring(0, this.uri.getSchemeSpecificPart().indexOf(";")); + final MimeTypeMap mime = MimeTypeMap.getSingleton(); + this.extension = mime.getExtensionFromMimeType(this.type); + return true; + } + return false; + } + public String getType() { + return this.type; + } + public Uri getURI() { + if(this.isBase64File()) { + String encodedImg = this.uri.getSchemeSpecificPart().substring(this.uri.getSchemeSpecificPart().indexOf(";base64,") + 8); + try { + File dir = new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DOWNLOADS ); + if (!dir.exists()) + { + dir.mkdirs(); + } + File file = new File(dir, System.currentTimeMillis() + "." + this.extension); + final FileOutputStream fos = new FileOutputStream(file); + fos.write(Base64.decode(encodedImg, Base64.DEFAULT)); + fos.flush(); + fos.close(); + return Uri.fromFile(file); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + return null; + } +} diff --git a/android/src/main/java/cl/json/RNShareModule.java b/android/src/main/java/cl/json/RNShareModule.java index 5e3fd38c..97125675 100644 --- a/android/src/main/java/cl/json/RNShareModule.java +++ b/android/src/main/java/cl/json/RNShareModule.java @@ -1,7 +1,12 @@ package cl.json; +import android.content.Context; import android.content.Intent; import android.content.ActivityNotFoundException; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Environment; +import android.util.Base64; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; @@ -10,6 +15,11 @@ import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.Callback; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URI; + public class RNShareModule extends ReactContextBaseJavaModule { private final ReactApplicationContext reactContext; @@ -36,7 +46,15 @@ public void open(ReadableMap options, Callback callback) { callback.invoke("not_available"); } } - + private boolean isPackageInstalled(String packagename, Context context) { + PackageManager pm = context.getPackageManager(); + try { + pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES); + return true; + } catch (PackageManager.NameNotFoundException e) { + return false; + } + } /** * Creates an {@link Intent} to be shared from a set of {@link ReadableMap} options * @param {@link ReadableMap} options @@ -46,16 +64,33 @@ private Intent createShareIntent(ReadableMap options) { Intent intent = new Intent(android.content.Intent.ACTION_SEND); intent.setType("text/plain"); - if (hasValidKey("share_subject", options) ) { - intent.putExtra(Intent.EXTRA_SUBJECT, options.getString("share_subject")); + if (hasValidKey("subject", options) ) { + intent.putExtra(Intent.EXTRA_SUBJECT, options.getString("subject")); } - - if (hasValidKey("share_text", options) && hasValidKey("share_URL", options)) { - intent.putExtra(Intent.EXTRA_TEXT, options.getString("share_text") + " " + options.getString("share_URL")); - } else if (hasValidKey("share_URL", options)) { - intent.putExtra(Intent.EXTRA_TEXT, options.getString("share_URL")); - } else if (hasValidKey("share_text", options) ) { - intent.putExtra(Intent.EXTRA_TEXT, options.getString("share_text")); + //isPackageInstalled("com.whatsapp", this.reactContext); + if (hasValidKey("message", options) && hasValidKey("url", options)) { + FileBase64 fileShare = new FileBase64(options.getString("url")); + if(fileShare.isFile()) { + Uri uriFile = fileShare.getURI(); + intent.setType(fileShare.getType()); + System.out.println("es base 64 file"); + System.out.printf(options.getString("url")); + intent.putExtra(Intent.EXTRA_STREAM, uriFile); + intent.putExtra(Intent.EXTRA_TEXT, options.getString("message")); + } else { + System.out.println("no es base 64 file"); + intent.putExtra(Intent.EXTRA_TEXT, options.getString("message") + " " + options.getString("url")); + } + } else if (hasValidKey("url", options)) { + URI uri = URI.create(options.getString("url")); + if(uri.getScheme().equals("data")) { + System.out.println("IS DATA FILE L"); + } else { + intent.putExtra(Intent.EXTRA_TEXT, options.getString("url")); + } + + } else if (hasValidKey("message", options) ) { + intent.putExtra(Intent.EXTRA_TEXT, options.getString("message")); } return intent; } @@ -88,4 +123,4 @@ private boolean hasValidKey(String key, ReadableMap options) { return options.hasKey(key) && !options.isNull(key); } -} \ No newline at end of file +} diff --git a/index.js b/index.js index 8fdcd047..4d86115b 100644 --- a/index.js +++ b/index.js @@ -1,2 +1,29 @@ -var { NativeModules } = require('react-native'); -module.exports = NativeModules.RNShare; +import ReactNative, { + Platform, + ActionSheetIOS, + NativeModules +} from "react-native"; + +const RNShare = function (options) { + return new Promise((resolve, reject) => { + if (Platform.OS === "ios") { + ActionSheetIOS.showShareActionSheetWithOptions(options, (error) => { + return reject({ error: error }); + }, (success, activityType) => { + if(success) { + return resolve({ + app: activityType + }); + } else { + reject({ error: "User did not share" }); + } + }); + } else { + NativeModules.RNShare.open(options,(e) => { + return reject({ error: e }); + }); + } + }); + +} +module.exports = RNShare; From 797dc89cb7368011ccda74c4b7ff585186e9304a Mon Sep 17 00:00:00 2001 From: Esteban Fuentealba Date: Fri, 22 Jul 2016 13:59:44 -0400 Subject: [PATCH 02/10] added: local files shared in android --- .../src/main/java/cl/json/RNShareModule.java | 11 +--- .../json/{FileBase64.java => ShareFile.java} | 52 +++++++++++++++---- 2 files changed, 43 insertions(+), 20 deletions(-) rename android/src/main/java/cl/json/{FileBase64.java => ShareFile.java} (54%) diff --git a/android/src/main/java/cl/json/RNShareModule.java b/android/src/main/java/cl/json/RNShareModule.java index 97125675..69d9b76c 100644 --- a/android/src/main/java/cl/json/RNShareModule.java +++ b/android/src/main/java/cl/json/RNShareModule.java @@ -5,19 +5,13 @@ import android.content.ActivityNotFoundException; import android.content.pm.PackageManager; import android.net.Uri; -import android.os.Environment; -import android.util.Base64; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.Callback; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; import java.net.URI; public class RNShareModule extends ReactContextBaseJavaModule { @@ -69,16 +63,13 @@ private Intent createShareIntent(ReadableMap options) { } //isPackageInstalled("com.whatsapp", this.reactContext); if (hasValidKey("message", options) && hasValidKey("url", options)) { - FileBase64 fileShare = new FileBase64(options.getString("url")); + ShareFile fileShare = new ShareFile(options.getString("url"), this.reactContext); if(fileShare.isFile()) { Uri uriFile = fileShare.getURI(); intent.setType(fileShare.getType()); - System.out.println("es base 64 file"); - System.out.printf(options.getString("url")); intent.putExtra(Intent.EXTRA_STREAM, uriFile); intent.putExtra(Intent.EXTRA_TEXT, options.getString("message")); } else { - System.out.println("no es base 64 file"); intent.putExtra(Intent.EXTRA_TEXT, options.getString("message") + " " + options.getString("url")); } } else if (hasValidKey("url", options)) { diff --git a/android/src/main/java/cl/json/FileBase64.java b/android/src/main/java/cl/json/ShareFile.java similarity index 54% rename from android/src/main/java/cl/json/FileBase64.java rename to android/src/main/java/cl/json/ShareFile.java index acd29d0d..afa89b2b 100644 --- a/android/src/main/java/cl/json/FileBase64.java +++ b/android/src/main/java/cl/json/ShareFile.java @@ -1,11 +1,17 @@ package cl.json; +import android.content.CursorLoader; import android.content.Intent; +import android.database.Cursor; +import android.media.MediaScannerConnection; import android.net.Uri; import android.os.Environment; +import android.provider.MediaStore; import android.util.Base64; import android.webkit.MimeTypeMap; +import com.facebook.react.bridge.ReactApplicationContext; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -15,17 +21,20 @@ /** * Created by disenodosbbcl on 22-07-16. */ -public class FileBase64 { +public class ShareFile { + + private final ReactApplicationContext reactContext; private String url; - private URI uri; + private Uri uri; private String type = "*/*"; private String extension = ""; - public FileBase64(String url){ + public ShareFile(String url, ReactApplicationContext reactContext){ this.url = url; - this.uri = URI.create(this.url); + this.uri = Uri.parse(this.url); + this.reactContext = reactContext; } - private static String getMimeType(String url) { + private String getMimeType(String url) { String type = "*/*"; String extension = MimeTypeMap.getFileExtensionFromUrl(url); if (extension != null) { @@ -34,13 +43,20 @@ private static String getMimeType(String url) { return type; } public boolean isFile() { - return this.isBase64File(); + return this.isBase64File() || this.isLocalFile(); } public boolean isBase64File() { if(uri.getScheme().equals("data")) { this.type = this.uri.getSchemeSpecificPart().substring(0, this.uri.getSchemeSpecificPart().indexOf(";")); - final MimeTypeMap mime = MimeTypeMap.getSingleton(); - this.extension = mime.getExtensionFromMimeType(this.type); + return true; + } + return false; + } + public boolean isLocalFile() { + if(uri.getScheme().equals("content") || uri.getScheme().equals("file")) { + String realPath = this.getRealPathFromURI(uri); + this.type = this.getMimeType(realPath); + return true; } return false; @@ -48,13 +64,25 @@ public boolean isBase64File() { public String getType() { return this.type; } + private String getRealPathFromURI(Uri contentUri) { + String[] proj = { MediaStore.Images.Media.DATA }; + CursorLoader loader = new CursorLoader(this.reactContext, contentUri, proj, null, null, null); + Cursor cursor = loader.loadInBackground(); + int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); + cursor.moveToFirst(); + String result = cursor.getString(column_index); + cursor.close(); + return result; + } public Uri getURI() { + + final MimeTypeMap mime = MimeTypeMap.getSingleton(); + this.extension = mime.getExtensionFromMimeType(this.type); if(this.isBase64File()) { String encodedImg = this.uri.getSchemeSpecificPart().substring(this.uri.getSchemeSpecificPart().indexOf(";base64,") + 8); try { File dir = new File(Environment.getExternalStorageDirectory(), Environment.DIRECTORY_DOWNLOADS ); - if (!dir.exists()) - { + if (!dir.exists()) { dir.mkdirs(); } File file = new File(dir, System.currentTimeMillis() + "." + this.extension); @@ -67,6 +95,10 @@ public Uri getURI() { } catch (IOException e) { e.printStackTrace(); } + } else if(this.isLocalFile()) { + Uri uri = Uri.parse(this.url); + + return uri; } return null; From 6fc4b14d65c1249821e943ce850ed50242eede98 Mon Sep 17 00:00:00 2001 From: Esteban Fuentealba Date: Sat, 23 Jul 2016 03:10:59 -0400 Subject: [PATCH 03/10] added icons to ios - android --- android/react-native-share.iml | 26 ++- .../src/main/java/cl/json/RNShareModule.java | 52 +++++- android/src/main/java/cl/json/ShareFile.java | 9 ++ assets/ic_share_copiar_link.png | Bin 0 -> 1294 bytes assets/ic_share_correo.png | Bin 0 -> 724 bytes assets/ic_share_facebook.png | Bin 0 -> 325 bytes assets/ic_share_google.png | Bin 0 -> 1414 bytes assets/ic_share_icon.png | Bin 0 -> 1472 bytes assets/ic_share_mas.png | Bin 0 -> 263 bytes assets/ic_share_twitter.png | Bin 0 -> 1045 bytes assets/ic_share_whatsapp.png | Bin 0 -> 1771 bytes components/Button.js | 46 ++++++ components/Overlay.js | 54 +++++++ components/Sheet.js | 33 ++++ index.js | 151 +++++++++++++++++- ios/RNShare.m | 9 +- ios/RNShare.xcodeproj/project.pbxproj | 26 ++- 17 files changed, 374 insertions(+), 32 deletions(-) create mode 100644 assets/ic_share_copiar_link.png create mode 100644 assets/ic_share_correo.png create mode 100644 assets/ic_share_facebook.png create mode 100644 assets/ic_share_google.png create mode 100644 assets/ic_share_icon.png create mode 100644 assets/ic_share_mas.png create mode 100644 assets/ic_share_twitter.png create mode 100644 assets/ic_share_whatsapp.png create mode 100644 components/Button.js create mode 100644 components/Overlay.js create mode 100644 components/Sheet.js diff --git a/android/react-native-share.iml b/android/react-native-share.iml index 2a9cbe1f..7a84c9b9 100644 --- a/android/react-native-share.iml +++ b/android/react-native-share.iml @@ -18,7 +18,7 @@