diff options
Diffstat (limited to 'StoneIsland/platforms/android/src/nl')
| -rwxr-xr-x | StoneIsland/platforms/android/src/nl/xservices/plugins/LaunchMyApp.java | 136 | ||||
| -rwxr-xr-x | StoneIsland/platforms/android/src/nl/xservices/plugins/SocialSharing.java | 533 |
2 files changed, 669 insertions, 0 deletions
diff --git a/StoneIsland/platforms/android/src/nl/xservices/plugins/LaunchMyApp.java b/StoneIsland/platforms/android/src/nl/xservices/plugins/LaunchMyApp.java new file mode 100755 index 00000000..9d3f3d63 --- /dev/null +++ b/StoneIsland/platforms/android/src/nl/xservices/plugins/LaunchMyApp.java @@ -0,0 +1,136 @@ +package nl.xservices.plugins; + +import android.content.Intent; +import org.apache.cordova.CallbackContext; +import org.apache.cordova.CordovaActivity; +import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.PluginResult; +import org.json.JSONArray; +import org.json.JSONException; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.util.Locale; + +public class LaunchMyApp extends CordovaPlugin { + + private static final String ACTION_CHECKINTENT = "checkIntent"; + + @Override + public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { + if (ACTION_CHECKINTENT.equalsIgnoreCase(action)) { + final Intent intent = ((CordovaActivity) this.webView.getContext()).getIntent(); + final String intentString = intent.getDataString(); + if (intentString != null && intentString.contains("://") && intent.getScheme() != null) { + callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, intent.getDataString())); + intent.setData(null); + } else { + callbackContext.error("App was not started via the launchmyapp URL scheme. Ignoring this errorcallback is the best approach."); + } + return true; + } else { + callbackContext.error("This plugin only responds to the " + ACTION_CHECKINTENT + " action."); + return false; + } + } + + @Override + public void onNewIntent(Intent intent) { + final String intentString = intent.getDataString(); + if (intentString != null && intentString.contains("://") && intent.getScheme() != null) { + intent.setData(null); + try { + StringWriter writer = new StringWriter(intentString.length() * 2); + escapeJavaStyleString(writer, intentString, true, false); + webView.loadUrl("javascript:handleOpenURL('" + writer.toString() + "');"); + } catch (IOException ignore) { + } + } + } + + // Taken from commons StringEscapeUtils + private static void escapeJavaStyleString(Writer out, String str, boolean escapeSingleQuote, + boolean escapeForwardSlash) throws IOException { + if (out == null) { + throw new IllegalArgumentException("The Writer must not be null"); + } + if (str == null) { + return; + } + int sz; + sz = str.length(); + for (int i = 0; i < sz; i++) { + char ch = str.charAt(i); + + // handle unicode + if (ch > 0xfff) { + out.write("\\u" + hex(ch)); + } else if (ch > 0xff) { + out.write("\\u0" + hex(ch)); + } else if (ch > 0x7f) { + out.write("\\u00" + hex(ch)); + } else if (ch < 32) { + switch (ch) { + case '\b': + out.write('\\'); + out.write('b'); + break; + case '\n': + out.write('\\'); + out.write('n'); + break; + case '\t': + out.write('\\'); + out.write('t'); + break; + case '\f': + out.write('\\'); + out.write('f'); + break; + case '\r': + out.write('\\'); + out.write('r'); + break; + default: + if (ch > 0xf) { + out.write("\\u00" + hex(ch)); + } else { + out.write("\\u000" + hex(ch)); + } + break; + } + } else { + switch (ch) { + case '\'': + if (escapeSingleQuote) { + out.write('\\'); + } + out.write('\''); + break; + case '"': + out.write('\\'); + out.write('"'); + break; + case '\\': + out.write('\\'); + out.write('\\'); + break; + case '/': + if (escapeForwardSlash) { + out.write('\\'); + } + out.write('/'); + break; + default: + out.write(ch); + break; + } + } + } + } + + private static String hex(char ch) { + return Integer.toHexString(ch).toUpperCase(Locale.ENGLISH); + } +}
\ No newline at end of file diff --git a/StoneIsland/platforms/android/src/nl/xservices/plugins/SocialSharing.java b/StoneIsland/platforms/android/src/nl/xservices/plugins/SocialSharing.java new file mode 100755 index 00000000..f1168f89 --- /dev/null +++ b/StoneIsland/platforms/android/src/nl/xservices/plugins/SocialSharing.java @@ -0,0 +1,533 @@ +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.List; +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_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_SENDVIAEMAIL = 2; + + 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, false); + } 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", false); + } 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", false); + } 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", false); + } else if (ACTION_SHARE_VIA_WHATSAPP_EVENT.equals(action)) { + return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "whatsapp", false); + } 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", false); + } 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), 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), false); + } 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()); + } + + draft.setType("application/octet-stream"); + 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 doSendIntent(final CallbackContext callbackContext, final String msg, final String subject, final JSONArray files, final String url, final String appPackageName, final boolean peek) { + + 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); + } + } + + 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)); + 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 { + mycordova.startActivityForResult(plugin, Intent.createChooser(sendIntent, null), 1); + } + } + } + }); + 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; + 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._-]", ""); + 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"); + } + return Uri.parse(localImage); + } + + 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); + } + } + 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) { + if (ACTIVITY_CODE_SENDVIAEMAIL == requestCode) { + _callbackContext.success(); + } else { + _callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, resultCode == Activity.RESULT_OK)); + } + } + } + + 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) { + final String pattern = ".*/([^?#]+)?"; + Pattern r = Pattern.compile(pattern); + Matcher m = r.matcher(url); + if (m.find()) { + return m.group(1); + } else { + return null; + } + } + + 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("[:\\\\/*?|<> ]", "_"); + } +} |
