diff options
Diffstat (limited to 'plugins/de.appplant.cordova.plugin.badge/src/android')
4 files changed, 555 insertions, 0 deletions
diff --git a/plugins/de.appplant.cordova.plugin.badge/src/android/Badge.java b/plugins/de.appplant.cordova.plugin.badge/src/android/Badge.java new file mode 100644 index 00000000..97f710e6 --- /dev/null +++ b/plugins/de.appplant.cordova.plugin.badge/src/android/Badge.java @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2013-2015 by appPlant UG. All rights reserved. + * + * @APPPLANT_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apache License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://opensource.org/licenses/Apache-2.0/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPPLANT_LICENSE_HEADER_END@ + */ + +package de.appplant.cordova.plugin.badge; + +import android.content.Context; + +import org.apache.cordova.CallbackContext; +import org.apache.cordova.CordovaPlugin; +import org.json.JSONArray; +import org.json.JSONException; + + +public class Badge extends CordovaPlugin { + + /** + * Implementation of the badge interface methods. + */ + private final BadgeImpl badgeImpl = new BadgeImpl(); + + /** + * Executes the request. + * + * @param action The action to execute. + * @param args The exec() arguments. + * @param callback The callback context used when + * calling back into JavaScript. + * + * @return + * Returning false results in a "MethodNotFound" error. + * + * @throws JSONException + */ + @Override + public boolean execute (String action, JSONArray args, CallbackContext callback) + throws JSONException { + + if (action.equalsIgnoreCase("clearBadge")) { + clearBadge(callback); + return true; + } + + if (action.equalsIgnoreCase("getBadge")) { + getBadge(callback); + return true; + } + + if (action.equalsIgnoreCase("hasPermission")) { + hasPermission(callback); + return true; + } + + if (action.equalsIgnoreCase("registerPermission")) { + hasPermission(callback); + return true; + } + + if (action.equalsIgnoreCase("setBadge")) { + setBadge(args, callback); + return true; + } + + return false; + } + + /** + * Clears the badge of the app icon. + * + * @param callback + * The function to be exec as the callback + */ + private void clearBadge (final CallbackContext callback) { + cordova.getThreadPool().execute(new Runnable() { + @Override + public void run() { + badgeImpl.clearBadge(getContext()); + badgeImpl.getBadge(callback, getContext()); + } + }); + } + + /** + * Retrieves the badge of the app icon. + * + * @param callback + * The function to be exec as the callback + */ + private void getBadge (final CallbackContext callback) { + cordova.getThreadPool().execute(new Runnable() { + @Override + public void run() { + badgeImpl.getBadge(callback, getContext()); + } + }); + } + + /** + * Informs if the app has the permission to show badges. + * + * @param callback + * The function to be exec as the callback + */ + private void hasPermission (final CallbackContext callback) { + cordova.getThreadPool().execute(new Runnable() { + @Override + public void run() { + badgeImpl.hasPermission(callback); + } + }); + } + + /** + * Sets the badge of the app icon. + * + * @param args + * The new badge number + * @param callback + * The function to be exec as the callback + */ + private void setBadge (final JSONArray args, + final CallbackContext callback) { + + cordova.getThreadPool().execute(new Runnable() { + @Override + public void run() { + badgeImpl.clearBadge(getContext()); + badgeImpl.setBadge(args, getContext()); + badgeImpl.getBadge(callback, getContext()); + } + }); + } + + /** + * Returns the context of the activity. + */ + private Context getContext () { + return cordova.getActivity(); + } + +} diff --git a/plugins/de.appplant.cordova.plugin.badge/src/android/BadgeImpl.java b/plugins/de.appplant.cordova.plugin.badge/src/android/BadgeImpl.java new file mode 100644 index 00000000..9f55c920 --- /dev/null +++ b/plugins/de.appplant.cordova.plugin.badge/src/android/BadgeImpl.java @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2014-2015 by appPlant UG. All rights reserved. + * + * @APPPLANT_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apache License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://opensource.org/licenses/Apache-2.0/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPPLANT_LICENSE_HEADER_END@ + */ + +package de.appplant.cordova.plugin.badge; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.os.Build; + +import org.apache.cordova.CallbackContext; +import org.apache.cordova.PluginResult; +import org.json.JSONArray; + +import me.leolin.shortcutbadger.ShortcutBadger; +import me.leolin.shortcutbadger.impl.DefaultBadger; + +/** + * Implementation of the badge interface methods. + */ +class BadgeImpl { + + /** + * The ID for the notification + */ + private final int ID = -450793490; + + /** + * The name for the shared preferences key + */ + protected static final String KEY = "badge"; + + /** + * Bundle identifier for the autoCancel value + */ + protected static final String EXTRA_AUTO_CANCEL = "EXTRA_AUTO_CANCEL"; + + /** + * Finds out if badgeing the app icon is possible on that device. + * + * @param ctx + * The application context. + * @return + * true if its supported. + */ + private boolean canBadgeAppIcon (Context ctx) { + ShortcutBadger badger = ShortcutBadger.with(ctx); + + return !(badger instanceof DefaultBadger); + } + + /** + * Clears the badge of the app icon. + * + * @param ctx + * The application context. + */ + protected void clearBadge (Context ctx) { + saveBadge(0, ctx); + getNotificationManager(ctx).cancel(ID); + ShortcutBadger.with(ctx).remove(); + } + + /** + * Retrieves the badge of the app icon. + * + * @param ctx + * The application context. + * @param callback + * The function to be exec as the callback. + */ + protected void getBadge (CallbackContext callback, Context ctx) { + SharedPreferences settings = getSharedPreferences(ctx); + int badge = settings.getInt(KEY, 0); + PluginResult result; + + result = new PluginResult(PluginResult.Status.OK, badge); + + callback.sendPluginResult(result); + } + + /** + * Sets the badge of the app icon. + * + * @param args + * The new badge number + * @param ctx + * The application context + */ + protected void setBadge (JSONArray args, Context ctx) { + int badge = args.optInt(0); + + saveBadge(badge, ctx); + + if (canBadgeAppIcon(ctx)) { + ShortcutBadger.with(ctx).count(badge); + } else { + setBadgeNotification(badge, args, ctx); + } + } + + /** + * Sets the badge of the app icon. + * + * @param args + * The new badge number + * @param ctx + * The application context + */ + @SuppressWarnings("deprecation") + private void setBadgeNotification (int badge, JSONArray args, Context ctx) { + String title = args.optString(1, "%d new messages"); + String icon = args.optString(2); + boolean autoCancel = args.optBoolean(3, false); + + Resources res = ctx.getResources(); + Bitmap appIcon = BitmapFactory.decodeResource( + res, getDrawableIcon(ctx)); + + Intent intent = new Intent(ctx, LaunchActivity.class) + .setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); + + intent.putExtra(EXTRA_AUTO_CANCEL, autoCancel); + + PendingIntent contentIntent = PendingIntent.getActivity( + ctx, ID, intent, PendingIntent.FLAG_CANCEL_CURRENT); + + String title_ = String.format(title, badge); + + Notification.Builder notification = new Notification.Builder(ctx) + .setContentTitle(title_) + .setNumber(badge) + .setTicker(title_) + .setAutoCancel(autoCancel) + .setSmallIcon(getResIdForSmallIcon(icon, ctx)) + .setLargeIcon(appIcon) + .setContentIntent(contentIntent); + + if (Build.VERSION.SDK_INT<16) { + // Build notification for HoneyComb to ICS + getNotificationManager(ctx).notify(ID, notification.getNotification()); + } else if (Build.VERSION.SDK_INT>15) { + // Notification for Jellybean and above + getNotificationManager(ctx).notify(ID, notification.build()); + } + } + + /** + * Persist the badge of the app icon so that `getBadge` is able to return + * the badge number back to the client. + * + * @param badge + * The badge of the app icon. + * @param ctx + * The application context. + */ + protected void saveBadge (int badge, Context ctx) { + SharedPreferences.Editor editor = getSharedPreferences(ctx).edit(); + + editor.putInt(KEY, badge); + editor.apply(); + } + + /** + * Informs if the app has the permission to show badges. + * + * @param callback + * The function to be exec as the callback + */ + protected void hasPermission (final CallbackContext callback) { + PluginResult result = new PluginResult(PluginResult.Status.OK, true); + + callback.sendPluginResult(result); + } + + /** + * The Local storage for the application. + */ + private SharedPreferences getSharedPreferences (Context context) { + return context.getSharedPreferences(KEY, Context.MODE_PRIVATE); + } + + /** + * The NotificationManager for the app. + */ + private NotificationManager getNotificationManager (Context context) { + return (NotificationManager) context.getSystemService( + Context.NOTIFICATION_SERVICE); + } + + /** + * Returns the ID for the given resource. + * + * @return + * The resource ID of the app icon + */ + private int getDrawableIcon (Context ctx) { + Resources res = ctx.getResources(); + String pkgName = ctx.getPackageName(); + + int resId; + resId = res.getIdentifier("icon", "drawable", pkgName); + + return resId; + } + + /** + * Returns the ID for the given resource. + * + * @return + * The resource ID for the small icon. + */ + private int getResIdForSmallIcon (String smallIcon, Context ctx) { + int resId; + + String pkgName = ctx.getPackageName(); + + resId = getResId(pkgName, smallIcon); + + if (resId == 0) { + resId = getResId("android", smallIcon); + } + + if (resId == 0) { + resId = getResId("android", "ic_dialog_email"); + } + + return resId; + } + + /** + * Returns numerical icon Value. + * + * @param className + * The class name prefix either from Android or the app. + * @param iconName + * The resource name. + */ + private int getResId (String className, String iconName) { + int icon = 0; + + try { + Class<?> klass = Class.forName(className + ".R$drawable"); + + icon = (Integer) klass.getDeclaredField(iconName).get(Integer.class); + } catch (Exception ignored) {} + + return icon; + } + +} diff --git a/plugins/de.appplant.cordova.plugin.badge/src/android/LaunchActivity.java b/plugins/de.appplant.cordova.plugin.badge/src/android/LaunchActivity.java new file mode 100644 index 00000000..8e2227fb --- /dev/null +++ b/plugins/de.appplant.cordova.plugin.badge/src/android/LaunchActivity.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2013-2015 by appPlant UG. All rights reserved. + * + * @APPPLANT_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apache License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://opensource.org/licenses/Apache-2.0/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPPLANT_LICENSE_HEADER_END@ + */ + +package de.appplant.cordova.plugin.badge; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; + +public class LaunchActivity extends Activity { + + /** + * Clears the badge and moves the launch intent + * (web view) back to front. + */ + @Override + public void onCreate (Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Intent intent = getIntent(); + boolean cancel = intent.getBooleanExtra( + BadgeImpl.EXTRA_AUTO_CANCEL, false); + + if (cancel) { + clearBagde(); + } + + launchMainIntent(); + } + + /** + * Launch main intent for package. + */ + private void launchMainIntent () { + Context context = getApplicationContext(); + String pkgName = context.getPackageName(); + Intent intent = context.getPackageManager() + .getLaunchIntentForPackage(pkgName); + + intent.addFlags( + Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP); + + context.startActivity(intent); + } + + /** + * Removes the badge of the app icon so that `getBadge` + * will return 0 back to the client. + */ + private void clearBagde () { + SharedPreferences.Editor editor = getSharedPreferences().edit(); + + editor.putInt(BadgeImpl.KEY, 0); + editor.apply(); + } + + /** + * The Local storage for the application. + */ + private SharedPreferences getSharedPreferences () { + Context context = getApplicationContext(); + + return context.getSharedPreferences(BadgeImpl.KEY, Context.MODE_PRIVATE); + } + +} diff --git a/plugins/de.appplant.cordova.plugin.badge/src/android/badge.gradle b/plugins/de.appplant.cordova.plugin.badge/src/android/badge.gradle new file mode 100644 index 00000000..b2a7b07d --- /dev/null +++ b/plugins/de.appplant.cordova.plugin.badge/src/android/badge.gradle @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013-2015 by appPlant UG. All rights reserved. + * + * @APPPLANT_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apache License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://opensource.org/licenses/Apache-2.0/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPPLANT_LICENSE_HEADER_END@ + */ + +repositories { + mavenCentral() +} + +dependencies { + compile 'me.leolin:ShortcutBadger:1.1.2@aar' +} |
