diff --git a/README.md b/README.md
index 3122655..b88b8ab 100644
--- a/README.md
+++ b/README.md
@@ -7,54 +7,69 @@ The ShortcutBadger makes your Android App showing the count of unread messages a
-
-Android
-(before 4.4)
-(Deprecated since 1.1.0)
-
-
- |
-
-Sony
-
-
- |
-
-Samsung
-
-
- |
+
+ Sony
+
+
+ |
+
+ Samsung
+
+
+ |
+
+ LG
+
+
+ |
-
-LG
-
-
- |
-
-HTC
-
-
- |
-
-Xiaomi
-
-
- |
+
+ HTC
+
+
+ |
+
+ Xiaomi
+
+
+ |
+
+ ASUS
+
+
+ |
+
+
+ ADW
+
+
+ |
+
+ APEX
+
+
+ |
+
+ NOVA
+
+
+ |
+
-ASUS
+Android
+(before 4.4)
+(Deprecated since 1.1.0)
-
- |
-
- |
-
+
|
+
+
Nova launcher with TeslaUnread,Apex launcher,Adw Launcher provided by [notz](https://github.com/notz)
Solid launcher provided by [MajeurAndroid](https://github.com/MajeurAndroid)
@@ -70,18 +85,17 @@ USAGE
2. Add dependencies for ShortcutBadger, it's available from maven now.
dependencies {
- compile 'me.leolin:ShortcutBadger:1.1.0@aar'
+ compile 'me.leolin:ShortcutBadger:1.1.1@aar'
}
3. Add the codes below:
int badgeCount = 1;
- try {
- ShortcutBadger.setBadge(getApplicationContext(), badgeCount);
- } catch (ShortcutBadgeException e) {
- //handle the Exception
- }
-
4. If you want to remove the badge, just set the badgeCount as 0.
+ ShortcutBadger.with(getApplicationContext()).count(badgeCount);
+
+
4. If you want to remove the badge
+
+ ShortcutBadger.with(getApplicationContext()).remove();
@@ -105,6 +119,11 @@ Please use version 1.1.0+
CHANGE LOG
===================================
+1.1.1:
+Add DefaultBadger because some launchers use android.intent.action.BADGE_COUNT_UPDATE to update count.
+
+Since the ShortcutBadgerException is helpless. So change api to set badge and never have to handle the exception again.
+
1.1.0:
Remove Android Launcher support due to Google Play Developer Term Violation since 4.4
diff --git a/SampleApp/src/main/java/me/leolin/shortcutbadger/example/MainActivity.java b/SampleApp/src/main/java/me/leolin/shortcutbadger/example/MainActivity.java
index f58a07c..93cdcd3 100644
--- a/SampleApp/src/main/java/me/leolin/shortcutbadger/example/MainActivity.java
+++ b/SampleApp/src/main/java/me/leolin/shortcutbadger/example/MainActivity.java
@@ -10,7 +10,6 @@
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
-import me.leolin.shortcutbadger.ShortcutBadgeException;
import me.leolin.shortcutbadger.ShortcutBadger;
@@ -29,20 +28,17 @@ protected void onCreate(Bundle savedInstanceState) {
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
+ int badgeCount = 0;
try {
- int badgeCount = 0;
- try {
- badgeCount = Integer.parseInt(numInput.getText().toString());
- } catch (NumberFormatException e) {
- Toast.makeText(getApplicationContext(), "Error input", Toast.LENGTH_SHORT).show();
- }
-
- ShortcutBadger.setBadge(getApplicationContext(), badgeCount);
-
- Toast.makeText(getApplicationContext(), "Set count=" + badgeCount, Toast.LENGTH_SHORT).show();
- } catch (ShortcutBadgeException e) {
- Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
+ badgeCount = Integer.parseInt(numInput.getText().toString());
+ } catch (NumberFormatException e) {
+ Toast.makeText(getApplicationContext(), "Error input", Toast.LENGTH_SHORT).show();
}
+
+// ShortcutBadger.setBadge(getApplicationContext(), badgeCount);
+ ShortcutBadger.with(getApplicationContext()).count(badgeCount);
+
+ Toast.makeText(getApplicationContext(), "Set count=" + badgeCount, Toast.LENGTH_SHORT).show();
}
});
diff --git a/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/ShortcutBadgeException.java b/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/ShortcutBadgeException.java
index f6fdc55..5aad647 100644
--- a/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/ShortcutBadgeException.java
+++ b/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/ShortcutBadgeException.java
@@ -1,12 +1,6 @@
package me.leolin.shortcutbadger;
-/**
- * Created with IntelliJ IDEA.
- * User: leolin
- * Date: 2013/11/14
- * Time: 下午6:19
- * To change this template use File | Settings | File Templates.
- */
+@Deprecated
public class ShortcutBadgeException extends Exception {
public ShortcutBadgeException(String message) {
super(message);
diff --git a/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/ShortcutBadger.java b/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/ShortcutBadger.java
index c03d4be..7abfd68 100644
--- a/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/ShortcutBadger.java
+++ b/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/ShortcutBadger.java
@@ -6,10 +6,10 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Build;
+import android.util.Log;
import me.leolin.shortcutbadger.impl.*;
import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
import java.util.LinkedList;
import java.util.List;
@@ -19,12 +19,12 @@
*/
public abstract class ShortcutBadger {
+ private static final String LOG_TAG = ShortcutBadger.class.getSimpleName();
+
private static final List> BADGERS = new LinkedList>();
static {
BADGERS.add(AdwHomeBadger.class);
-// BADGERS.add(AndroidHomeBadger.class);
-// BADGERS.add(Android2HomeBadger.class);
BADGERS.add(ApexHomeBadger.class);
BADGERS.add(LGHomeBadger.class);
BADGERS.add(NewHtcHomeBadger.class);
@@ -36,86 +36,73 @@ public abstract class ShortcutBadger {
BADGERS.add(AsusHomeLauncher.class);
}
- private static final String MESSAGE_NOT_SUPPORT_BADGE_COUNT = "ShortBadger is currently not support the badgeCount \"%d\"";
- private static final String MESSAGE_NOT_SUPPORT_THIS_HOME = "ShortcutBadger is currently not support the home launcher package \"%s\"";
-
- private static final int MIN_BADGE_COUNT = 0;
- private static final int MAX_BADGE_COUNT = 99;
-
private static ShortcutBadger mShortcutBadger;
- private ShortcutBadger() {
- }
-
- protected Context mContext;
-
- protected ShortcutBadger(Context context) {
- this.mContext = context;
+ public static ShortcutBadger with(Context context) {
+ return getShortcutBadger(context);
}
- protected abstract void executeBadge(int badgeCount) throws ShortcutBadgeException;
public static void setBadge(Context context, int badgeCount) throws ShortcutBadgeException {
- //badgeCount should between 0 to 99
- if (badgeCount < MIN_BADGE_COUNT || badgeCount > MAX_BADGE_COUNT) {
- String exceptionMessage = String.format(MESSAGE_NOT_SUPPORT_BADGE_COUNT, badgeCount);
- throw new ShortcutBadgeException(exceptionMessage);
- }
-
- //find the home launcher Package
- Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.addCategory(Intent.CATEGORY_HOME);
- ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
- String currentHomePackage = resolveInfo.activityInfo.packageName;
-
-
try {
- ShortcutBadger shortcutBadger = getShortcutBadger(currentHomePackage, context);
-
- //not support this home launcher package
- if (shortcutBadger == null) {
- String exceptionMessage = String.format(MESSAGE_NOT_SUPPORT_THIS_HOME, currentHomePackage);
- throw new ShortcutBadgeException(exceptionMessage);
- }
-
- shortcutBadger.executeBadge(badgeCount);
+ getShortcutBadger(context).executeBadge(badgeCount);
} catch (Throwable e) {
throw new ShortcutBadgeException("Unable to execute badge:" + e.getMessage());
}
}
- private static ShortcutBadger getShortcutBadger(String currentHomePackage, Context context) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
+ private static ShortcutBadger getShortcutBadger(Context context) {
if (mShortcutBadger != null) {
return mShortcutBadger;
}
+ Log.d(LOG_TAG, "Finding badger");
- // Workaround for Meizu:
- // Meizu declare 'com.android.launcher', but hold something else
- // Icons get duplicated on restart after badge change
- if (Build.MANUFACTURER.toLowerCase().contains("meizu")) {
- return null;
- }
-
- if (Build.MANUFACTURER.equalsIgnoreCase("Xiaomi")) {
- mShortcutBadger = new XiaomiHomeBadger(context);
- return mShortcutBadger;
- }
+ //find the home launcher Package
+ try {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_HOME);
+ ResolveInfo resolveInfo = context.getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
+ String currentHomePackage = resolveInfo.activityInfo.packageName;
+
+ if (Build.MANUFACTURER.equalsIgnoreCase("Xiaomi")) {
+ mShortcutBadger = new XiaomiHomeBadger(context);
+ return mShortcutBadger;
+ }
- for (Class extends ShortcutBadger> badger : BADGERS) {
- Constructor extends ShortcutBadger> constructor = badger.getConstructor(Context.class);
- ShortcutBadger shortcutBadger = constructor.newInstance(context);
- if (shortcutBadger.getSupportLaunchers().contains(currentHomePackage)) {
- mShortcutBadger = shortcutBadger;
- break;
+ for (Class extends ShortcutBadger> badger : BADGERS) {
+ Constructor extends ShortcutBadger> constructor = badger.getConstructor(Context.class);
+ ShortcutBadger shortcutBadger = constructor.newInstance(context);
+ if (shortcutBadger.getSupportLaunchers().contains(currentHomePackage)) {
+ mShortcutBadger = shortcutBadger;
+ break;
+ }
}
+ } catch (Exception e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
}
+ if (mShortcutBadger == null) {
+ mShortcutBadger = new DefaultBadger(context);
+ }
+ Log.d(LOG_TAG, "Returning badger:" + mShortcutBadger.getClass().getCanonicalName());
return mShortcutBadger;
}
- public abstract List getSupportLaunchers();
+
+ private ShortcutBadger() {
+ }
+
+ protected Context mContext;
+
+ protected ShortcutBadger(Context context) {
+ this.mContext = context;
+ }
+
+ protected abstract void executeBadge(int badgeCount) throws ShortcutBadgeException;
+
+ protected abstract List getSupportLaunchers();
protected String getEntryActivityName() {
ComponentName componentName = mContext.getPackageManager().getLaunchIntentForPackage(mContext.getPackageName()).getComponent();
@@ -125,4 +112,16 @@ protected String getEntryActivityName() {
protected String getContextPackageName() {
return mContext.getPackageName();
}
+
+ public void count(int count) {
+ try {
+ executeBadge(count);
+ } catch (Exception e) {
+ Log.e(LOG_TAG, e.getMessage(), e);
+ }
+ }
+
+ public void remove() {
+ count(0);
+ }
}
diff --git a/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/impl/Android2HomeBadger.java b/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/impl/Android2HomeBadger.java
deleted file mode 100644
index e27b848..0000000
--- a/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/impl/Android2HomeBadger.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package me.leolin.shortcutbadger.impl;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.net.Uri;
-import me.leolin.shortcutbadger.ShortcutBadgeException;
-import me.leolin.shortcutbadger.ShortcutBadger;
-import me.leolin.shortcutbadger.util.ImageUtil;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * @author Leo Lin
- */
-@Deprecated
-public class Android2HomeBadger extends ShortcutBadger {
- private static final String CONTENT_URI = "content://com.android.launcher2.settings/favorites?notify=true";
-
- public Android2HomeBadger(Context context) {
- super(context);
- }
-
- @Override
- protected void executeBadge(int badgeCount) throws ShortcutBadgeException {
- byte[] bytes = ImageUtil.drawBadgeOnAppIcon(mContext, badgeCount);
- String appName = mContext.getResources().getText(mContext.getResources().getIdentifier("app_name",
- "string", getContextPackageName())).toString();
-
- Uri mUri = Uri.parse(CONTENT_URI);
- ContentResolver contentResolver = mContext.getContentResolver();
- ContentValues contentValues = new ContentValues();
- contentValues.put("iconType", 1);
- contentValues.put("itemType", 1);
- contentValues.put("icon", bytes);
- contentResolver.update(mUri, contentValues, "title=?", new String[]{appName});
- }
-
- @Override
- public List getSupportLaunchers() {
- return Arrays.asList(
- "com.android.launcher2",
- "com.google.android.googlequicksearchbox"
- );
- }
-}
diff --git a/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/impl/AndroidHomeBadger.java b/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/impl/AndroidHomeBadger.java
deleted file mode 100644
index 8f4e83f..0000000
--- a/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/impl/AndroidHomeBadger.java
+++ /dev/null
@@ -1,46 +0,0 @@
-package me.leolin.shortcutbadger.impl;
-
-import android.content.ContentResolver;
-import android.content.ContentValues;
-import android.content.Context;
-import android.net.Uri;
-import me.leolin.shortcutbadger.ShortcutBadgeException;
-import me.leolin.shortcutbadger.ShortcutBadger;
-import me.leolin.shortcutbadger.util.ImageUtil;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * @author Leo Lin
- */
-@Deprecated
-public class AndroidHomeBadger extends ShortcutBadger {
- private static final String CONTENT_URI = "content://com.android.launcher2.settings/favorites?notify=true";
-
- public AndroidHomeBadger(Context context) {
- super(context);
- }
-
- @Override
- protected void executeBadge(int badgeCount) throws ShortcutBadgeException {
- byte[] bytes = ImageUtil.drawBadgeOnAppIcon(mContext, badgeCount);
- String appName = mContext.getResources().getText(mContext.getResources().getIdentifier("app_name",
- "string", getContextPackageName())).toString();
-
- Uri mUri = Uri.parse(CONTENT_URI);
- ContentResolver contentResolver = mContext.getContentResolver();
- ContentValues contentValues = new ContentValues();
- contentValues.put("iconType", 1);
- contentValues.put("itemType", 1);
- contentValues.put("icon", bytes);
- contentResolver.update(mUri, contentValues, "title=?", new String[]{appName});
- }
-
- @Override
- public List getSupportLaunchers() {
- return Arrays.asList(
- "com.android.launcher"
- );
- }
-}
diff --git a/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/impl/DefaultBadger.java b/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/impl/DefaultBadger.java
new file mode 100644
index 0000000..2963b5b
--- /dev/null
+++ b/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/impl/DefaultBadger.java
@@ -0,0 +1,36 @@
+package me.leolin.shortcutbadger.impl;
+
+import android.content.Context;
+import android.content.Intent;
+import me.leolin.shortcutbadger.ShortcutBadger;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author leolin
+ */
+public class DefaultBadger extends ShortcutBadger {
+ private static final String INTENT_ACTION = "android.intent.action.BADGE_COUNT_UPDATE";
+ private static final String INTENT_EXTRA_BADGE_COUNT = "badge_count";
+ private static final String INTENT_EXTRA_PACKAGENAME = "badge_count_package_name";
+ private static final String INTENT_EXTRA_ACTIVITY_NAME = "badge_count_class_name";
+
+ public DefaultBadger(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void executeBadge(int badgeCount) {
+ Intent intent = new Intent(INTENT_ACTION);
+ intent.putExtra(INTENT_EXTRA_BADGE_COUNT, badgeCount);
+ intent.putExtra(INTENT_EXTRA_PACKAGENAME, getContextPackageName());
+ intent.putExtra(INTENT_EXTRA_ACTIVITY_NAME, getEntryActivityName());
+ mContext.sendBroadcast(intent);
+ }
+
+ @Override
+ public List getSupportLaunchers() {
+ return new ArrayList(0);
+ }
+}
diff --git a/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/util/ImageUtil.java b/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/util/ImageUtil.java
deleted file mode 100644
index 8c67d04..0000000
--- a/ShortcutBadger/src/main/java/me/leolin/shortcutbadger/util/ImageUtil.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package me.leolin.shortcutbadger.util;
-
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.graphics.*;
-import android.graphics.drawable.Drawable;
-import me.leolin.shortcutbadger.ShortcutBadgeException;
-
-import java.io.ByteArrayOutputStream;
-
-/**
- * Created with IntelliJ IDEA.
- * User: leolin
- * Date: 2013/11/14
- * Time: 下午7:15
- * To change this template use File | Settings | File Templates.
- */
-public class ImageUtil {
- public static Bitmap drawableToBitmap(Drawable drawable) {
-
- Bitmap bitmap = Bitmap
- .createBitmap(
- drawable.getIntrinsicWidth(),
- drawable.getIntrinsicHeight(),
- drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
- : Bitmap.Config.RGB_565);
- Canvas canvas = new Canvas(bitmap);
-
- drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
- drawable.draw(canvas);
- return bitmap;
- }
-
- public static byte[] bitmapToByteArray(Bitmap bitmap) {
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- bitmap.compress(Bitmap.CompressFormat.PNG, 100, baos);
- return baos.toByteArray();
-
- }
-
- public static byte[] drawBadgeOnAppIcon(Context context, int badgeCount) throws ShortcutBadgeException {
-
- Bitmap appIcon;
- String gText = String.valueOf(badgeCount);
-
- try {
- Drawable iconDrawable = context.getPackageManager().getApplicationIcon(context.getPackageName());
- appIcon = drawableToBitmap(iconDrawable);
- } catch (PackageManager.NameNotFoundException e) {
- throw new ShortcutBadgeException("Could not load the app Icon");
- }
-
- if (appIcon == null) {
- throw new ShortcutBadgeException("Could not load the app Icon");
- }
-
- if (badgeCount == 0) {
- return bitmapToByteArray(appIcon);
- }
-
- float scale = context.getResources().getDisplayMetrics().density;
-
- android.graphics.Bitmap.Config bitmapConfig =
- appIcon.getConfig();
- // set default bitmap config if none
- if (bitmapConfig == null) {
- bitmapConfig = android.graphics.Bitmap.Config.ARGB_8888;
- }
- // resource bitmaps are imutable,
- // so we need to convert it to mutable one
- appIcon = appIcon.copy(bitmapConfig, true);
-
- float width = appIcon.getWidth();
- float height = appIcon.getHeight();
- float radius = ((width > height ? width : height) / 4);
- float cx = appIcon.getWidth() - radius;
- float cy = radius;
-
- Canvas canvas = new Canvas(appIcon);
- //ANTI_ALIAS to avoid glitched circles
- Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
- paint.setColor(Color.WHITE);
- canvas.drawCircle(cx, cy, radius, paint);
- paint.setColor(Color.RED);
- canvas.drawCircle(cx, cy, radius * 6 / 7, paint);
-
- paint.setColor(Color.WHITE);
- // text size in pixels
- int textSize = (int) (radius * 0.7);
- if (gText.length() > 1) {
- textSize = (int) (radius * 0.5);
- }
- paint.setTextSize((int) (textSize * scale));
- paint.setFakeBoldText(true);
- // draw text to the Canvas center
- Rect bounds = new Rect();
- paint.getTextBounds(gText, 0, gText.length(), bounds);
- float bw = bounds.width() / 2;
- if (gText.endsWith("1")) {
- bw *= 1.25;
- }
- float bh = bounds.height() / 2;
- canvas.drawText(gText, cx - bw, cy + bh, paint);
-
- return bitmapToByteArray(appIcon);
- }
-
-
-}
diff --git a/screenshots/ss_adw.png b/screenshots/ss_adw.png
new file mode 100644
index 0000000..35ba93f
Binary files /dev/null and b/screenshots/ss_adw.png differ
diff --git a/screenshots/ss_apex.png b/screenshots/ss_apex.png
new file mode 100644
index 0000000..a660e8b
Binary files /dev/null and b/screenshots/ss_apex.png differ
diff --git a/screenshots/ss_nova.png b/screenshots/ss_nova.png
new file mode 100644
index 0000000..ce26b1d
Binary files /dev/null and b/screenshots/ss_nova.png differ