summaryrefslogtreecommitdiff
path: root/StoneIsland/platforms/android/src/nl/xservices/plugins/SocialSharing.java
diff options
context:
space:
mode:
Diffstat (limited to 'StoneIsland/platforms/android/src/nl/xservices/plugins/SocialSharing.java')
-rw-r--r--StoneIsland/platforms/android/src/nl/xservices/plugins/SocialSharing.java775
1 files changed, 0 insertions, 775 deletions
diff --git a/StoneIsland/platforms/android/src/nl/xservices/plugins/SocialSharing.java b/StoneIsland/platforms/android/src/nl/xservices/plugins/SocialSharing.java
deleted file mode 100644
index 8de31da8..00000000
--- a/StoneIsland/platforms/android/src/nl/xservices/plugins/SocialSharing.java
+++ /dev/null
@@ -1,775 +0,0 @@
-package nl.xservices.plugins;
-
-import android.annotation.SuppressLint;
-import android.app.Activity;
-import android.content.*;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Environment;
-import android.text.Html;
-import android.util.Base64;
-import android.view.Gravity;
-import android.widget.Toast;
-
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaInterface;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.PluginResult;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.*;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class SocialSharing extends CordovaPlugin {
-
- private static final String ACTION_AVAILABLE_EVENT = "available";
- private static final String ACTION_SHARE_EVENT = "share";
- private static final String ACTION_SHARE_WITH_OPTIONS_EVENT = "shareWithOptions";
- private static final String ACTION_CAN_SHARE_VIA = "canShareVia";
- private static final String ACTION_CAN_SHARE_VIA_EMAIL = "canShareViaEmail";
- private static final String ACTION_SHARE_VIA = "shareVia";
- private static final String ACTION_SHARE_VIA_TWITTER_EVENT = "shareViaTwitter";
- private static final String ACTION_SHARE_VIA_FACEBOOK_EVENT = "shareViaFacebook";
- private static final String ACTION_SHARE_VIA_FACEBOOK_WITH_PASTEMESSAGEHINT = "shareViaFacebookWithPasteMessageHint";
- private static final String ACTION_SHARE_VIA_WHATSAPP_EVENT = "shareViaWhatsApp";
- private static final String ACTION_SHARE_VIA_INSTAGRAM_EVENT = "shareViaInstagram";
- private static final String ACTION_SHARE_VIA_SMS_EVENT = "shareViaSMS";
- private static final String ACTION_SHARE_VIA_EMAIL_EVENT = "shareViaEmail";
-
- private static final int ACTIVITY_CODE_SEND__BOOLRESULT = 1;
- private static final int ACTIVITY_CODE_SEND__OBJECT = 2;
- private static final int ACTIVITY_CODE_SENDVIAEMAIL = 3;
- private static final int ACTIVITY_CODE_SENDVIAWHATSAPP = 4;
-
- private CallbackContext _callbackContext;
-
- private String pasteMessage;
-
- private abstract class SocialSharingRunnable implements Runnable {
- public CallbackContext callbackContext;
-
- SocialSharingRunnable(CallbackContext cb) {
- this.callbackContext = cb;
- }
- }
-
- @Override
- public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
- this._callbackContext = callbackContext; // only used for onActivityResult
- this.pasteMessage = null;
- if (ACTION_AVAILABLE_EVENT.equals(action)) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
- return true;
- } else if (ACTION_SHARE_EVENT.equals(action)) {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), null, null, false, true);
- } else if (ACTION_SHARE_WITH_OPTIONS_EVENT.equals(action)) {
- return shareWithOptions(callbackContext, args.getJSONObject(0));
- } else if (ACTION_SHARE_VIA_TWITTER_EVENT.equals(action)) {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "twitter", null, false, true);
- } else if (ACTION_SHARE_VIA_FACEBOOK_EVENT.equals(action)) {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "com.facebook.katana", null, false, true);
- } else if (ACTION_SHARE_VIA_FACEBOOK_WITH_PASTEMESSAGEHINT.equals(action)) {
- this.pasteMessage = args.getString(4);
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "com.facebook.katana", null, false, true);
- } else if (ACTION_SHARE_VIA_WHATSAPP_EVENT.equals(action)) {
- if (notEmpty(args.getString(4))) {
- return shareViaWhatsAppDirectly(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), args.getString(4));
- } else {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "whatsapp", null, false, true);
- }
- } else if (ACTION_SHARE_VIA_INSTAGRAM_EVENT.equals(action)) {
- if (notEmpty(args.getString(0))) {
- copyHintToClipboard(args.getString(0), "Instagram paste message");
- }
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "instagram", null, false, true);
- } else if (ACTION_CAN_SHARE_VIA.equals(action)) {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), args.getString(4), null, true, true);
- } else if (ACTION_CAN_SHARE_VIA_EMAIL.equals(action)) {
- if (isEmailAvailable()) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
- return true;
- } else {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, "not available"));
- return false;
- }
- } else if (ACTION_SHARE_VIA.equals(action)) {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), args.getString(4), null, false, true);
- } else if (ACTION_SHARE_VIA_SMS_EVENT.equals(action)) {
- return invokeSMSIntent(callbackContext, args.getJSONObject(0), args.getString(1));
- } else if (ACTION_SHARE_VIA_EMAIL_EVENT.equals(action)) {
- return invokeEmailIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.isNull(3) ? null : args.getJSONArray(3), args.isNull(4) ? null : args.getJSONArray(4), args.isNull(5) ? null : args.getJSONArray(5));
- } else {
- callbackContext.error("socialSharing." + action + " is not a supported function. Did you mean '" + ACTION_SHARE_EVENT + "'?");
- return false;
- }
- }
-
- private boolean isEmailAvailable() {
- final Intent intent = new Intent(Intent.ACTION_SENDTO, Uri.fromParts("mailto", "someone@domain.com", null));
- return cordova.getActivity().getPackageManager().queryIntentActivities(intent, 0).size() > 0;
- }
-
- private boolean invokeEmailIntent(final CallbackContext callbackContext, final String message, final String subject, final JSONArray to, final JSONArray cc, final JSONArray bcc, final JSONArray files) throws JSONException {
-
- final SocialSharing plugin = this;
- cordova.getThreadPool().execute(new SocialSharingRunnable(callbackContext) {
- public void run() {
- final Intent draft = new Intent(Intent.ACTION_SEND_MULTIPLE);
- if (notEmpty(message)) {
- Pattern htmlPattern = Pattern.compile(".*\\<[^>]+>.*", Pattern.DOTALL);
- if (htmlPattern.matcher(message).matches()) {
- draft.putExtra(android.content.Intent.EXTRA_TEXT, Html.fromHtml(message));
- draft.setType("text/html");
- } else {
- draft.putExtra(android.content.Intent.EXTRA_TEXT, message);
- draft.setType("text/plain");
- }
- }
- if (notEmpty(subject)) {
- draft.putExtra(android.content.Intent.EXTRA_SUBJECT, subject);
- }
- try {
- if (to != null && to.length() > 0) {
- draft.putExtra(android.content.Intent.EXTRA_EMAIL, toStringArray(to));
- }
- if (cc != null && cc.length() > 0) {
- draft.putExtra(android.content.Intent.EXTRA_CC, toStringArray(cc));
- }
- if (bcc != null && bcc.length() > 0) {
- draft.putExtra(android.content.Intent.EXTRA_BCC, toStringArray(bcc));
- }
- if (files.length() > 0) {
- final String dir = getDownloadDir();
- if (dir != null) {
- ArrayList<Uri> fileUris = new ArrayList<Uri>();
- for (int i = 0; i < files.length(); i++) {
- final Uri fileUri = getFileUriAndSetType(draft, dir, files.getString(i), subject, i);
- if (fileUri != null) {
- fileUris.add(fileUri);
- }
- }
- if (!fileUris.isEmpty()) {
- draft.putExtra(Intent.EXTRA_STREAM, fileUris);
- }
- }
- }
- } catch (Exception e) {
- callbackContext.error(e.getMessage());
- }
-
- // this was added to start the intent in a new window as suggested in #300 to prevent crashes upon return
- draft.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- draft.setType("application/octet-stream");
-
- // as an experiment for #300 we're explicitly running it on the ui thread here
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- cordova.startActivityForResult(plugin, Intent.createChooser(draft, "Choose Email App"), ACTIVITY_CODE_SENDVIAEMAIL);
- }
- });
- }
- });
-
- return true;
- }
-
- private String getDownloadDir() throws IOException {
- // better check, otherwise it may crash the app
- if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
- // we need to use external storage since we need to share to another app
- final String dir = webView.getContext().getExternalFilesDir(null) + "/socialsharing-downloads";
- createOrCleanDir(dir);
- return dir;
- } else {
- return null;
- }
- }
-
- private boolean shareWithOptions(CallbackContext callbackContext, JSONObject jsonObject) {
- return doSendIntent(
- callbackContext,
- jsonObject.optString("message", null),
- jsonObject.optString("subject", null),
- jsonObject.optJSONArray("files") == null ? new JSONArray() : jsonObject.optJSONArray("files"),
- jsonObject.optString("url", null),
- null,
- jsonObject.optString("chooserTitle", null),
- false,
- false
- );
- }
-
- private boolean doSendIntent(
- final CallbackContext callbackContext,
- final String msg,
- final String subject,
- final JSONArray files,
- final String url,
- final String appPackageName,
- final String chooserTitle,
- final boolean peek,
- final boolean boolResult) {
-
- final CordovaInterface mycordova = cordova;
- final CordovaPlugin plugin = this;
-
- cordova.getThreadPool().execute(new SocialSharingRunnable(callbackContext) {
- public void run() {
- String message = msg;
- final boolean hasMultipleAttachments = files.length() > 1;
- final Intent sendIntent = new Intent(hasMultipleAttachments ? Intent.ACTION_SEND_MULTIPLE : Intent.ACTION_SEND);
- sendIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
-
- try {
- if (files.length() > 0 && !"".equals(files.getString(0))) {
- final String dir = getDownloadDir();
- if (dir != null) {
- ArrayList<Uri> fileUris = new ArrayList<Uri>();
- Uri fileUri = null;
- for (int i = 0; i < files.length(); i++) {
- fileUri = getFileUriAndSetType(sendIntent, dir, files.getString(i), subject, i);
- if (fileUri != null) {
- fileUris.add(fileUri);
- }
- }
- if (!fileUris.isEmpty()) {
- if (hasMultipleAttachments) {
- sendIntent.putExtra(Intent.EXTRA_STREAM, fileUris);
- } else {
- sendIntent.putExtra(Intent.EXTRA_STREAM, fileUri);
- }
- }
- } else {
- sendIntent.setType("text/plain");
- }
- } else {
- sendIntent.setType("text/plain");
- }
- } catch (Exception e) {
- callbackContext.error(e.getMessage());
- }
-
- if (notEmpty(subject)) {
- sendIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
- }
-
- // add the URL to the message, as there seems to be no separate field
- if (notEmpty(url)) {
- if (notEmpty(message)) {
- message += " " + url;
- } else {
- message = url;
- }
- }
- if (notEmpty(message)) {
- sendIntent.putExtra(android.content.Intent.EXTRA_TEXT, message);
- // sometimes required when the user picks share via sms
- if (Build.VERSION.SDK_INT < 21) { // LOLLIPOP
- sendIntent.putExtra("sms_body", message);
- }
- }
-
- // this was added to start the intent in a new window as suggested in #300 to prevent crashes upon return
- sendIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- if (appPackageName != null) {
- String packageName = appPackageName;
- String passedActivityName = null;
- if (packageName.contains("/")) {
- String[] items = appPackageName.split("/");
- packageName = items[0];
- passedActivityName = items[1];
- }
- final ActivityInfo activity = getActivity(callbackContext, sendIntent, packageName);
- if (activity != null) {
- if (peek) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
- } else {
- sendIntent.addCategory(Intent.CATEGORY_LAUNCHER);
- sendIntent.setComponent(new ComponentName(activity.applicationInfo.packageName,
- passedActivityName != null ? passedActivityName : activity.name));
-
- // as an experiment for #300 we're explicitly running it on the ui thread here
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- mycordova.startActivityForResult(plugin, sendIntent, 0);
- }
- });
-
- if (pasteMessage != null) {
- // add a little delay because target app (facebook only atm) needs to be started first
- new Timer().schedule(new TimerTask() {
- public void run() {
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- copyHintToClipboard(msg, pasteMessage);
- showPasteMessage(pasteMessage);
- }
- });
- }
- }, 2000);
- }
- }
- }
- } else {
- if (peek) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
- } else {
- // experimenting a bit
- // as an experiment for #300 we're explicitly running it on the ui thread here
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- mycordova.startActivityForResult(plugin, Intent.createChooser(sendIntent, chooserTitle), boolResult ? ACTIVITY_CODE_SEND__BOOLRESULT : ACTIVITY_CODE_SEND__OBJECT);
- }
- });
- }
- }
- }
- });
- return true;
- }
-
- @SuppressLint("NewApi")
- private void copyHintToClipboard(String msg, String label) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
- return;
- }
- final ClipboardManager clipboard = (android.content.ClipboardManager) cordova.getActivity().getSystemService(Context.CLIPBOARD_SERVICE);
- final ClipData clip = android.content.ClipData.newPlainText(label, msg);
- clipboard.setPrimaryClip(clip);
- }
-
- @SuppressLint("NewApi")
- private void showPasteMessage(String label) {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
- return;
- }
- final Toast toast = Toast.makeText(webView.getContext(), label, Toast.LENGTH_LONG);
- toast.setGravity(Gravity.CENTER_VERTICAL | Gravity.CENTER_HORIZONTAL, 0, 0);
- toast.show();
- }
-
- private Uri getFileUriAndSetType(Intent sendIntent, String dir, String image, String subject, int nthFile) throws IOException {
- // we're assuming an image, but this can be any filetype you like
- String localImage = image;
- if (image.endsWith("mp4") || image.endsWith("mov") || image.endsWith("3gp")){
- sendIntent.setType("video/*");
- } else {
- sendIntent.setType("image/*");
- }
-
- if (image.startsWith("http") || image.startsWith("www/")) {
- String filename = getFileName(image);
- localImage = "file://" + dir + "/" + filename;
- if (image.startsWith("http")) {
- // filename optimisation taken from https://github.com/EddyVerbruggen/SocialSharing-PhoneGap-Plugin/pull/56
- URLConnection connection = new URL(image).openConnection();
- String disposition = connection.getHeaderField("Content-Disposition");
- if (disposition != null) {
- final Pattern dispositionPattern = Pattern.compile("filename=([^;]+)");
- Matcher matcher = dispositionPattern.matcher(disposition);
- if (matcher.find()) {
- filename = matcher.group(1).replaceAll("[^a-zA-Z0-9._-]", "");
- if (filename.length() == 0) {
- // in this case we can't determine a filetype so some targets (gmail) may not render it correctly
- filename = "file";
- }
- localImage = "file://" + dir + "/" + filename;
- }
- }
- saveFile(getBytes(connection.getInputStream()), dir, filename);
- } else {
- saveFile(getBytes(webView.getContext().getAssets().open(image)), dir, filename);
- }
- } else if (image.startsWith("data:")) {
- // safeguard for https://code.google.com/p/android/issues/detail?id=7901#c43
- if (!image.contains(";base64,")) {
- sendIntent.setType("text/plain");
- return null;
- }
- // image looks like this: data:image/png;base64,R0lGODlhDAA...
- final String encodedImg = image.substring(image.indexOf(";base64,") + 8);
- // correct the intent type if anything else was passed, like a pdf: data:application/pdf;base64,..
- if (!image.contains("data:image/")) {
- sendIntent.setType(image.substring(image.indexOf("data:") + 5, image.indexOf(";base64")));
- }
- // the filename needs a valid extension, so it renders correctly in target apps
- final String imgExtension = image.substring(image.indexOf("/") + 1, image.indexOf(";base64"));
- String fileName;
- // if a subject was passed, use it as the filename
- // filenames must be unique when passing in multiple files [#158]
- if (notEmpty(subject)) {
- fileName = sanitizeFilename(subject) + (nthFile == 0 ? "" : "_" + nthFile) + "." + imgExtension;
- } else {
- fileName = "file" + (nthFile == 0 ? "" : "_" + nthFile) + "." + imgExtension;
- }
- saveFile(Base64.decode(encodedImg, Base64.DEFAULT), dir, fileName);
- localImage = "file://" + dir + "/" + fileName;
- } else if (image.startsWith("df:")) {
- // safeguard for https://code.google.com/p/android/issues/detail?id=7901#c43
- if (!image.contains(";base64,")) {
- sendIntent.setType("text/plain");
- return null;
- }
- // format looks like this : df:filename.txt;data:image/png;base64,R0lGODlhDAA...
- final String fileName = image.substring(image.indexOf("df:") + 3, image.indexOf(";data:"));
- final String fileType = image.substring(image.indexOf(";data:") + 6, image.indexOf(";base64,"));
- final String encodedImg = image.substring(image.indexOf(";base64,") + 8);
- sendIntent.setType(fileType);
- saveFile(Base64.decode(encodedImg, Base64.DEFAULT), dir, sanitizeFilename(fileName));
- localImage = "file://" + dir + "/" + fileName;
- } else if (!image.startsWith("file://")) {
- throw new IllegalArgumentException("URL_NOT_SUPPORTED");
- } else {
- //get file MIME type
- String type = getMIMEType(image);
- //set intent data and Type
- sendIntent.setType(type);
- }
- return Uri.parse(localImage);
- }
-
- private String getMIMEType(String fileName) {
- String type = "*/*";
- int dotIndex = fileName.lastIndexOf(".");
- if (dotIndex == -1) {
- return type;
- }
- final String end = fileName.substring(dotIndex+1, fileName.length()).toLowerCase();
- String fromMap = MIME_Map.get(end);
- return fromMap == null ? type : fromMap;
- }
-
- private static final Map<String, String> MIME_Map = new HashMap<String, String>();
- static {
- MIME_Map.put("3gp", "video/3gpp");
- MIME_Map.put("apk", "application/vnd.android.package-archive");
- MIME_Map.put("asf", "video/x-ms-asf");
- MIME_Map.put("avi", "video/x-msvideo");
- MIME_Map.put("bin", "application/octet-stream");
- MIME_Map.put("bmp", "image/bmp");
- MIME_Map.put("c", "text/plain");
- MIME_Map.put("class", "application/octet-stream");
- MIME_Map.put("conf", "text/plain");
- MIME_Map.put("cpp", "text/plain");
- MIME_Map.put("doc", "application/msword");
- MIME_Map.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
- MIME_Map.put("xls", "application/vnd.ms-excel");
- MIME_Map.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
- MIME_Map.put("exe", "application/octet-stream");
- MIME_Map.put("gif", "image/gif");
- MIME_Map.put("gtar", "application/x-gtar");
- MIME_Map.put("gz", "application/x-gzip");
- MIME_Map.put("h", "text/plain");
- MIME_Map.put("htm", "text/html");
- MIME_Map.put("html", "text/html");
- MIME_Map.put("jar", "application/java-archive");
- MIME_Map.put("java", "text/plain");
- MIME_Map.put("jpeg", "image/jpeg");
- MIME_Map.put("jpg", "image/*");
- MIME_Map.put("js", "application/x-javascript");
- MIME_Map.put("log", "text/plain");
- MIME_Map.put("m3u", "audio/x-mpegurl");
- MIME_Map.put("m4a", "audio/mp4a-latm");
- MIME_Map.put("m4b", "audio/mp4a-latm");
- MIME_Map.put("m4p", "audio/mp4a-latm");
- MIME_Map.put("m4u", "video/vnd.mpegurl");
- MIME_Map.put("m4v", "video/x-m4v");
- MIME_Map.put("mov", "video/quicktime");
- MIME_Map.put("mp2", "audio/x-mpeg");
- MIME_Map.put("mp3", "audio/x-mpeg");
- MIME_Map.put("mp4", "video/mp4");
- MIME_Map.put("mpc", "application/vnd.mpohun.certificate");
- MIME_Map.put("mpe", "video/mpeg");
- MIME_Map.put("mpeg", "video/mpeg");
- MIME_Map.put("mpg", "video/mpeg");
- MIME_Map.put("mpg4", "video/mp4");
- MIME_Map.put("mpga", "audio/mpeg");
- MIME_Map.put("msg", "application/vnd.ms-outlook");
- MIME_Map.put("ogg", "audio/ogg");
- MIME_Map.put("pdf", "application/pdf");
- MIME_Map.put("png", "image/png");
- MIME_Map.put("pps", "application/vnd.ms-powerpoint");
- MIME_Map.put("ppt", "application/vnd.ms-powerpoint");
- MIME_Map.put("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation");
- MIME_Map.put("prop", "text/plain");
- MIME_Map.put("rc", "text/plain");
- MIME_Map.put("rmvb", "audio/x-pn-realaudio");
- MIME_Map.put("rtf", "application/rtf");
- MIME_Map.put("sh", "text/plain");
- MIME_Map.put("tar", "application/x-tar");
- MIME_Map.put("tgz", "application/x-compressed");
- MIME_Map.put("txt", "text/plain");
- MIME_Map.put("wav", "audio/x-wav");
- MIME_Map.put("wma", "audio/x-ms-wma");
- MIME_Map.put("wmv", "audio/x-ms-wmv");
- MIME_Map.put("wps", "application/vnd.ms-works");
- MIME_Map.put("xml", "text/plain");
- MIME_Map.put("z", "application/x-compress");
- MIME_Map.put("zip", "application/x-zip-compressed");
- MIME_Map.put("", "*/*");
- }
-
- private boolean shareViaWhatsAppDirectly(final CallbackContext callbackContext, String message, final String subject, final JSONArray files, final String url, final String number) {
- // add the URL to the message, as there seems to be no separate field
- if (notEmpty(url)) {
- if (notEmpty(message)) {
- message += " " + url;
- } else {
- message = url;
- }
- }
- final String shareMessage = message;
- final SocialSharing plugin = this;
- cordova.getThreadPool().execute(new SocialSharingRunnable(callbackContext) {
- public void run() {
- final Intent intent = new Intent(Intent.ACTION_SENDTO);
- intent.setData(Uri.parse("smsto:" + number));
-
- intent.putExtra("sms_body", shareMessage);
- intent.putExtra("sms_subject", subject);
- intent.setPackage("com.whatsapp");
-
- try {
- if (files.length() > 0 && !"".equals(files.getString(0))) {
- final boolean hasMultipleAttachments = files.length() > 1;
- final String dir = getDownloadDir();
- if (dir != null) {
- ArrayList<Uri> fileUris = new ArrayList<Uri>();
- Uri fileUri = null;
- for (int i = 0; i < files.length(); i++) {
- fileUri = getFileUriAndSetType(intent, dir, files.getString(i), subject, i);
- if (fileUri != null) {
- fileUris.add(fileUri);
- }
- }
- if (!fileUris.isEmpty()) {
- if (hasMultipleAttachments) {
- intent.putExtra(Intent.EXTRA_STREAM, fileUris);
- } else {
- intent.putExtra(Intent.EXTRA_STREAM, fileUri);
- }
- }
- }
- }
- } catch (Exception e) {
- callbackContext.error(e.getMessage());
- }
- try {
- // this was added to start the intent in a new window as suggested in #300 to prevent crashes upon return
- // update: didn't help (doesn't seem to hurt either though)
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- // as an experiment for #300 we're explicitly running it on the ui thread here
- cordova.getActivity().runOnUiThread(new Runnable() {
- public void run() {
- cordova.startActivityForResult(plugin, intent, ACTIVITY_CODE_SENDVIAWHATSAPP);
- }
- });
- } catch (Exception e) {
- callbackContext.error(e.getMessage());
- }
- }
- });
- return true;
- }
-
- private boolean invokeSMSIntent(final CallbackContext callbackContext, JSONObject options, String p_phonenumbers) {
- final String message = options.optString("message");
- // TODO test this on a real SMS enabled device before releasing it
-// final String subject = options.optString("subject");
-// final String image = options.optString("image");
- final String subject = null; //options.optString("subject");
- final String image = null; // options.optString("image");
- final String phonenumbers = getPhoneNumbersWithManufacturerSpecificSeparators(p_phonenumbers);
- final SocialSharing plugin = this;
- cordova.getThreadPool().execute(new SocialSharingRunnable(callbackContext) {
- public void run() {
- Intent intent;
-
- if (Build.VERSION.SDK_INT >= 19) { // Build.VERSION_CODES.KITKAT) {
- // passing in no phonenumbers for kitkat may result in an error,
- // but it may also work for some devices, so documentation will need to cover this case
- intent = new Intent(Intent.ACTION_SENDTO);
- intent.setData(Uri.parse("smsto:" + (notEmpty(phonenumbers) ? phonenumbers : "")));
- } else {
- intent = new Intent(Intent.ACTION_VIEW);
- intent.setType("vnd.android-dir/mms-sms");
- if (phonenumbers != null) {
- intent.putExtra("address", phonenumbers);
- }
- }
- intent.putExtra("sms_body", message);
- intent.putExtra("sms_subject", subject);
-
- try {
- if (image != null && !"".equals(image)) {
- final Uri fileUri = getFileUriAndSetType(intent, getDownloadDir(), image, subject, 0);
- if (fileUri != null) {
- intent.putExtra(Intent.EXTRA_STREAM, fileUri);
- }
- }
- // this was added to start the intent in a new window as suggested in #300 to prevent crashes upon return
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- cordova.startActivityForResult(plugin, intent, 0);
- } catch (Exception e) {
- callbackContext.error(e.getMessage());
- }
- }
- });
- return true;
- }
-
- private static String getPhoneNumbersWithManufacturerSpecificSeparators(String phonenumbers) {
- if (notEmpty(phonenumbers)) {
- char separator;
- if (android.os.Build.MANUFACTURER.equalsIgnoreCase("samsung")) {
- separator = ',';
- } else {
- separator = ';';
- }
- return phonenumbers.replace(';', separator).replace(',', separator);
- }
- return null;
- }
-
- private ActivityInfo getActivity(final CallbackContext callbackContext, final Intent shareIntent, final String appPackageName) {
- final PackageManager pm = webView.getContext().getPackageManager();
- List<ResolveInfo> activityList = pm.queryIntentActivities(shareIntent, 0);
- for (final ResolveInfo app : activityList) {
- if ((app.activityInfo.packageName).contains(appPackageName)) {
- return app.activityInfo;
- }
- }
- // no matching app found
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, getShareActivities(activityList)));
- return null;
- }
-
- private JSONArray getShareActivities(List<ResolveInfo> activityList) {
- List<String> packages = new ArrayList<String>();
- for (final ResolveInfo app : activityList) {
- packages.add(app.activityInfo.packageName);
- }
- return new JSONArray(packages);
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent intent) {
- super.onActivityResult(requestCode, resultCode, intent);
- if (_callbackContext != null) {
- switch (requestCode) {
- case ACTIVITY_CODE_SEND__BOOLRESULT:
- _callbackContext.sendPluginResult(new PluginResult(
- PluginResult.Status.OK,
- resultCode == Activity.RESULT_OK));
- break;
- case ACTIVITY_CODE_SEND__OBJECT:
- JSONObject json = new JSONObject();
- try {
- json.put("completed", resultCode == Activity.RESULT_OK);
- json.put("app", ""); // we need a completely different approach if we want to support this on Android. Idea: https://clickclickclack.wordpress.com/2012/01/03/intercepting-androids-action_send-intents/
- _callbackContext.sendPluginResult(new PluginResult(
- PluginResult.Status.OK,
- json));
- } catch (JSONException e) {
- _callbackContext.error(e.getMessage());
- }
- break;
- default:
- _callbackContext.success();
- }
- }
- }
-
- private void createOrCleanDir(final String downloadDir) throws IOException {
- final File dir = new File(downloadDir);
- if (!dir.exists()) {
- if (!dir.mkdirs()) {
- throw new IOException("CREATE_DIRS_FAILED");
- }
- } else {
- cleanupOldFiles(dir);
- }
- }
-
- private static String getFileName(String url) {
- if (url.endsWith("/")) {
- url = url.substring(0, url.length()-1);
- }
- final String pattern = ".*/([^?#]+)?";
- Pattern r = Pattern.compile(pattern);
- Matcher m = r.matcher(url);
- if (m.find()) {
- return m.group(1);
- } else {
- return "file";
- }
- }
-
- private byte[] getBytes(InputStream is) throws IOException {
- ByteArrayOutputStream buffer = new ByteArrayOutputStream();
- int nRead;
- byte[] data = new byte[16384];
- while ((nRead = is.read(data, 0, data.length)) != -1) {
- buffer.write(data, 0, nRead);
- }
- buffer.flush();
- return buffer.toByteArray();
- }
-
- private void saveFile(byte[] bytes, String dirName, String fileName) throws IOException {
- final File dir = new File(dirName);
- final FileOutputStream fos = new FileOutputStream(new File(dir, fileName));
- fos.write(bytes);
- fos.flush();
- fos.close();
- }
-
- /**
- * As file.deleteOnExit does not work on Android, we need to delete files manually.
- * Deleting them in onActivityResult is not a good idea, because for example a base64 encoded file
- * will not be available for upload to Facebook (it's deleted before it's uploaded).
- * So the best approach is deleting old files when saving (sharing) a new one.
- */
- private void cleanupOldFiles(File dir) {
- for (File f : dir.listFiles()) {
- //noinspection ResultOfMethodCallIgnored
- f.delete();
- }
- }
-
- private static boolean notEmpty(String what) {
- return what != null &&
- !"".equals(what) &&
- !"null".equalsIgnoreCase(what);
- }
-
- private static String[] toStringArray(JSONArray jsonArray) throws JSONException {
- String[] result = new String[jsonArray.length()];
- for (int i = 0; i < jsonArray.length(); i++) {
- result[i] = jsonArray.getString(i);
- }
- return result;
- }
-
- public static String sanitizeFilename(String name) {
- return name.replaceAll("[:\\\\/*?|<> ]", "_");
- }
-}