package it.michelelacorte.androidshortcuts.util; import android.Manifest; import android.annotation.TargetApi; import android.app.Activity; import android.content.ComponentName; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.ColorFilter; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; import android.graphics.PorterDuffXfermode; import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Build; import android.support.annotation.RequiresApi; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.graphics.Palette; import android.util.DisplayMetrics; import android.util.Log; import android.util.TypedValue; import android.view.Display; import android.widget.AdapterView; import android.widget.GridView; import it.michelelacorte.androidshortcuts.R; import it.michelelacorte.androidshortcuts.RemoteShortcuts; import it.michelelacorte.androidshortcuts.ShortcutsCreation; /** * Created by Michele on 09/12/2016. */ public class Utils { private static final String TAG = "Utils"; /** * Get grid size * @param gridView AdapterView * @return GridSize */ public static GridSize getGridSize(AdapterView gridView){ int nColumn = ((GridView) gridView).getNumColumns(); double nRow = Math.ceil((double)gridView.getCount()/(double)((GridView) gridView).getNumColumns()); Log.d(TAG, "Number of Row: " + (int)nRow + "\nNumber of Column: " + nColumn); return new GridSize(nColumn, (int)nRow); } /** * Get toolbar height * @param activity Activity * @return int */ public static int getToolbarHeight(Activity activity){ TypedValue tv = new TypedValue(); if (activity.getTheme().resolveAttribute(R.attr.actionBarSize, tv, true)) { Log.d(TAG, "Toolbar found, height: " + String.valueOf(TypedValue.complexToDimensionPixelSize(tv.data,activity.getApplicationContext().getResources().getDisplayMetrics()))); return TypedValue.complexToDimensionPixelSize(tv.data,activity.getApplicationContext().getResources().getDisplayMetrics()); }else{ Log.d(TAG, "Toolbar not found, height: 0"); return 0; } } /** * Create shortcuts on launcher based on params * @param activity Activity * @param shortcutsImage Bitmap * @param shortcutsText String * @param className String * @param packageName String * @throws ClassNotFoundException */ public static void createShortcutsOnLauncher(Activity activity, Bitmap shortcutsImage, String shortcutsText, String className, String packageName, String action, Drawable packageImage, Bitmap shortcutsImageBadge) throws ClassNotFoundException { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { int result = ContextCompat.checkSelfPermission(activity, Manifest.permission.INSTALL_SHORTCUT); if (result != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.INSTALL_SHORTCUT)) { Log.e(TAG, "Install Shortcuts permission allows us to create shortcuts on launcher. Please allow this permission in App Settings."); } else { ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.INSTALL_SHORTCUT}, 111); Log.d(TAG, "Install Shortcuts permission allows us to create shortcuts on launcher."); } } } Intent shortcutIntent = new Intent(activity.getApplicationContext(), activity.getClass()); shortcutIntent.setComponent(new ComponentName( packageName, className.replaceAll(packageName, ""))); if(action != null && !action.equals("")) { shortcutIntent.setAction(action); } shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); shortcutIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); Intent addIntent = new Intent(); addIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent); addIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, shortcutsText); if(shortcutsImageBadge == null && !RemoteShortcuts.USE_SHORTCUTS_FROM_API_25&& !ShortcutsCreation.USE_SHORTCUTS_FOR_LAUNCHER_3) { Bitmap roundedBitmap = getRoundedBitmap(shortcutsImage, packageImage); addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, roundedBitmap); }else if(ShortcutsCreation.USE_SHORTCUTS_FOR_LAUNCHER_3){ Bitmap roundedBitmap = getRoundedBitmapForLauncher3(activity, shortcutsImage, packageImage); addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, roundedBitmap); }else{ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1 && shortcutsImageBadge != null) { Bitmap roundedBitmap = getRoundedBitmapForAPI25(shortcutsImageBadge, packageImage); addIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, roundedBitmap); }else{ Log.e(TAG, "This call requires API " + Build.VERSION_CODES.N_MR1); return; } } addIntent.putExtra("duplicate", false); addIntent.setAction("com.android.launcher.action.INSTALL_SHORTCUT"); activity.getApplicationContext().sendBroadcast(addIntent); Log.d(TAG, "Shortcuts created on Launcher!"); } /** * Resize bitmap method * @param bm Bitmap * @param newWidth int * @param newHeight int * @return Bitmap */ public static Bitmap getResizedBitmap(Bitmap bm, int newWidth, int newHeight) { int width = bm.getWidth(); int height = bm.getHeight(); float scaleWidth = ((float) newWidth) / width; float scaleHeight = ((float) newHeight) / height; // CREATE A MATRIX FOR THE MANIPULATION Matrix matrix = new Matrix(); // RESIZE THE BIT MAP matrix.postScale(scaleWidth, scaleHeight); // "RECREATE" THE NEW BITMAP Bitmap resizedBitmap = Bitmap.createBitmap( bm, 0, 0, width, height, matrix, false); //bm.recycle(); return resizedBitmap; } /** * This method return image with badge from icon and package icon. * @param bitmap Bitmap * @param packageImage Drawable * @return Bitmap */ @TargetApi(25) @RequiresApi(25) public static Bitmap getRoundedBitmapForAPI25(Bitmap bitmap, Drawable packageImage) { Bitmap packageIcon = null; if(packageImage != null) { packageIcon = convertDrawableToBitmap(packageImage); } Bitmap packageIconScaled = getResizedBitmap(packageIcon, bitmap.getWidth()/2, bitmap.getHeight()/2); Bitmap result = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig()); Canvas canvas = new Canvas(result); final int color = 0xffF5F5F5; final int colorShape = 0xffBDBDBD; final Paint paint = new Paint(); final Paint paintShape = new Paint(); paint.setAntiAlias(true); paintShape.setAntiAlias(true); paint.setColor(color); paintShape.setColor(colorShape); canvas.drawARGB(0, 0, 0, 0); paintShape.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER)); canvas.drawCircle(bitmap.getWidth()/2, bitmap.getHeight()/2+2, 45, paintShape); canvas.drawBitmap(bitmap, 0f, 0f, paint); canvas.drawBitmap(packageIconScaled, bitmap.getWidth()/2, bitmap.getHeight()/2, null); return result; } public static Bitmap getRoundedBitmapForLauncher3(Activity activity, Bitmap bitmap, Drawable packageImage) { Bitmap packageIcon = null; if(packageImage != null) { packageIcon = convertDrawableToBitmap(packageImage); } Bitmap packageIconScaled = null; Bitmap shortcutsIconScaled = null; switch (getScreenXDimension(activity)) { case 480: packageIconScaled = getResizedBitmap(packageIcon, (int)(bitmap.getWidth()*1.3), (int)(bitmap.getHeight()*1.3)); shortcutsIconScaled = getResizedBitmap(bitmap, (int)(bitmap.getWidth()*1.2), (int)(bitmap.getHeight()*1.2)); break; case 720: packageIconScaled = getResizedBitmap(packageIcon, (int)(bitmap.getWidth()*1.6), (int)(bitmap.getHeight()*1.6)); shortcutsIconScaled = getResizedBitmap(bitmap, (int)(bitmap.getWidth()*1.2), (int)(bitmap.getHeight()*1.2)); break; case 1080: packageIconScaled = getResizedBitmap(packageIcon, (int)(bitmap.getWidth()*1.3), (int)(bitmap.getHeight()*1.3)); shortcutsIconScaled = getResizedBitmap(bitmap, (int)(bitmap.getWidth()*1.1), (int)(bitmap.getHeight()*1.1)); break; case 1440: return getRoundedBitmap(bitmap, packageImage); //packageIconScaled = getResizedBitmap(packageIcon, bitmap.getWidth(), bitmap.getHeight()); //shortcutsIconScaled = getResizedBitmap(bitmap, bitmap.getWidth(), bitmap.getHeight()); //break; default: Log.e(TAG, "Resolution of screen not supported!"); break; } final int dominantColor = getDominantColor(packageIconScaled); //Find dominant color and set it to bitmap icon shortcuts if (dominantColor != 0) { shortcutsIconScaled = setColorOnBitmap(shortcutsIconScaled, dominantColor); } final Bitmap output = Bitmap.createBitmap(packageIcon.getWidth(), packageIcon.getHeight(), Bitmap.Config.ARGB_8888); final Canvas canvas = new Canvas(output); final int color = 0xffF5F5F5; final int colorShape = 0xffBDBDBD; final Paint paint = new Paint(); final Paint paintShape = new Paint(); paint.setAntiAlias(true); paintShape.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); paintShape.setColor(colorShape); paintShape.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER)); switch (getScreenXDimension(activity)) { case 480: canvas.drawCircle(packageIcon.getWidth()/2, packageIcon.getHeight()/2, 35, paint); canvas.drawCircle(packageIcon.getWidth()/2, packageIcon.getHeight()/2+2, 35, paintShape); break; case 720: canvas.drawCircle(packageIcon.getWidth()/2, packageIcon.getHeight()/2, 55, paint); canvas.drawCircle(packageIcon.getWidth()/2, packageIcon.getHeight()/2+2, 55, paintShape); break; case 1080: canvas.drawCircle((float)(packageIcon.getWidth()/2.4), (float)(packageIcon.getHeight()/2.4), 70, paint); canvas.drawCircle((float)(packageIcon.getWidth()/2.4), (float)(packageIcon.getHeight()/2.4+2), 70, paintShape); break; case 1440: canvas.drawCircle(packageIcon.getWidth()/2, packageIcon.getHeight()/2, 90, paint); canvas.drawCircle(packageIcon.getWidth()/2, packageIcon.getHeight()/2+2, 90, paintShape); break; default: Log.e(TAG, "Resolution of screen not supported!"); break; } paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)); canvas.drawBitmap(shortcutsIconScaled, shortcutsIconScaled.getWidth()/2, shortcutsIconScaled.getHeight()/2, paint); if(packageImage != null && packageIcon != null) canvas.drawBitmap(packageIconScaled, bitmap.getWidth(), bitmap.getHeight(), paint); //bitmap.recycle(); return output; } /** * Get rounded bitmap like Nougat shortcuts * @param bitmap Bitmap * @param packageImage Drawable * @return Bitmap */ public static Bitmap getRoundedBitmap(Bitmap bitmap, Drawable packageImage) { Bitmap packageIcon = null; if(packageImage != null) { packageIcon = convertDrawableToBitmap(packageImage); } Bitmap packageIconScaled = getResizedBitmap(packageIcon, bitmap.getWidth()/2, bitmap.getHeight()/2); Bitmap shortcutsIconScaled = getResizedBitmap(bitmap, bitmap.getWidth()/2, bitmap.getHeight()/2); final int dominantColor = getDominantColor(packageIconScaled); //Find dominant color and set it to bitmap icon shortcuts if (dominantColor != 0) { shortcutsIconScaled = setColorOnBitmap(shortcutsIconScaled, dominantColor); } final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); final Canvas canvas = new Canvas(output); final int color = 0xffF5F5F5; final int colorShape = 0xffBDBDBD; final Paint paint = new Paint(); final Paint paintShape = new Paint(); paint.setAntiAlias(true); paintShape.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); paintShape.setColor(colorShape); paintShape.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER)); canvas.drawCircle(bitmap.getWidth()/2, bitmap.getHeight()/2, 45, paint); canvas.drawCircle(bitmap.getWidth()/2, bitmap.getHeight()/2+2, 45, paintShape); paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)); canvas.drawBitmap(shortcutsIconScaled, shortcutsIconScaled.getWidth()/2, shortcutsIconScaled.getHeight()/2, paint); if(packageImage != null && packageIcon != null) canvas.drawBitmap(packageIconScaled, bitmap.getWidth()/2, bitmap.getHeight()/2, paint); //bitmap.recycle(); return output; } /** * Get dominant color of bitmap * @param bitmap Bitmap * @return int */ public static int getDominantColor(Bitmap bitmap){ Palette palette = Palette.from(bitmap).generate(); Palette.Swatch dominantSwatch = palette.getDominantSwatch(); if(dominantSwatch != null){ return dominantSwatch.getRgb(); } return 0; } /** * Change color of Bitmap * @param bitmap Bitmap * @param color int * @return Bitmap */ public static Bitmap setColorOnBitmap(Bitmap bitmap, int color){ Bitmap bm = bitmap.copy(Bitmap.Config.ARGB_8888, true); Paint paintColorDominant = new Paint(); if(!RemoteShortcuts.USE_SHORTCUTS_FROM_API_25) { ColorFilter filter = new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_IN); paintColorDominant.setColorFilter(filter); } Canvas canvasColorDominant = new Canvas(bm); canvasColorDominant.drawBitmap(bm, 0, 0, paintColorDominant); return bm; } /** * Convert drawable to bitmap * @param drawable Drawable * @return Bitmap */ public static Bitmap convertDrawableToBitmap(Drawable drawable) { if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888).copy(Bitmap.Config.ARGB_8888, true); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } /** * Get screen X dimension */ public static int getScreenXDimension(Activity activity){ Display mdisp = activity.getWindowManager().getDefaultDisplay(); Point mdispSize = new Point(); mdisp.getSize(mdispSize); return mdispSize.x; } /** * Get screen Y dimension */ public static int getScreenYDimension(Activity activity){ Display mdisp = activity.getWindowManager().getDefaultDisplay(); Point mdispSize = new Point(); mdisp.getSize(mdispSize); return mdispSize.y; } public static int getScreenDpi(Activity activity){ DisplayMetrics displayMetrics = activity.getApplicationContext().getResources().getDisplayMetrics(); return displayMetrics.densityDpi; } public static Bitmap getRoundedBitmapForUniversalLauncher(Activity activity, Bitmap bitmap) { final Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888); final Canvas canvas = new Canvas(output); final int color = 0xffFFFFFF; final Paint paint = new Paint(); paint.setAntiAlias(true); canvas.drawARGB(0, 0, 0, 0); paint.setColor(color); DisplayMetrics displayMetrics = activity.getApplicationContext().getResources().getDisplayMetrics(); int displayDensityDpi = displayMetrics.densityDpi; switch(getScreenXDimension(activity)){ case 480: canvas.drawCircle(bitmap.getWidth()/2, bitmap.getHeight()/2, 35, paint); break; case 720: canvas.drawCircle(bitmap.getWidth()/2, bitmap.getHeight()/2, 55, paint); break; case 1080: canvas.drawCircle(bitmap.getWidth()/2, bitmap.getHeight()/2, 70, paint); break; case 1440: if(displayDensityDpi == 560) { canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, 100, paint); }else{ canvas.drawCircle(bitmap.getWidth() / 2, bitmap.getHeight() / 2, 120, paint); } break; default: Log.e(TAG, "Resolution of screen not supported!"); break; } paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER)); Bitmap scaledIcon = getResizedBitmap(bitmap, (int)(bitmap.getWidth()/1.5), (int)(bitmap.getHeight()/1.5)); canvas.drawBitmap(scaledIcon, bitmap.getWidth()/6, bitmap.getHeight()/6, paint); return output; } }