1 /* Copyright 2016 Braden Farmer
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
16 package com.farmerbb.taskbar.util;
18 import android.annotation.TargetApi;
19 import android.app.ActivityManager;
20 import android.app.ActivityOptions;
21 import android.app.AlertDialog;
22 import android.app.Service;
23 import android.app.admin.DevicePolicyManager;
24 import android.content.ActivityNotFoundException;
25 import android.content.ComponentName;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.SharedPreferences;
29 import android.content.pm.ActivityInfo;
30 import android.content.pm.LauncherActivityInfo;
31 import android.content.pm.LauncherApps;
32 import android.content.pm.PackageManager;
33 import android.content.pm.ResolveInfo;
34 import android.content.pm.ShortcutInfo;
35 import android.content.res.Configuration;
36 import android.graphics.Rect;
37 import android.graphics.drawable.BitmapDrawable;
38 import android.hardware.display.DisplayManager;
39 import android.net.Uri;
40 import android.os.Build;
41 import android.os.Bundle;
42 import android.os.Handler;
43 import android.os.Process;
44 import android.os.UserHandle;
45 import android.os.UserManager;
46 import android.provider.Settings;
47 import android.support.v4.content.LocalBroadcastManager;
48 import android.util.DisplayMetrics;
49 import android.view.Display;
50 import android.view.Surface;
51 import android.view.WindowManager;
52 import android.widget.Toast;
54 import com.farmerbb.taskbar.BuildConfig;
55 import com.farmerbb.taskbar.R;
56 import com.farmerbb.taskbar.activity.DummyActivity;
57 import com.farmerbb.taskbar.activity.InvisibleActivityFreeform;
58 import com.farmerbb.taskbar.activity.ShortcutActivity;
59 import com.farmerbb.taskbar.activity.StartTaskbarActivity;
60 import com.farmerbb.taskbar.receiver.LockDeviceReceiver;
61 import com.farmerbb.taskbar.service.PowerMenuService;
63 import java.util.ArrayList;
64 import java.util.List;
66 import moe.banana.support.ToastCompat;
72 private static SharedPreferences pref;
73 private static Integer cachedRotation;
74 private static ToastCompat toast;
76 private static final int FULLSCREEN = 0;
77 private static final int LEFT = -1;
78 private static final int RIGHT = 1;
80 public static final int HIDDEN = 0;
81 public static final int TOP_APPS = 1;
83 public static SharedPreferences getSharedPreferences(Context context) {
84 if(pref == null) pref = context.getSharedPreferences(BuildConfig.APPLICATION_ID + "_preferences", Context.MODE_PRIVATE);
88 @TargetApi(Build.VERSION_CODES.M)
89 public static void showPermissionDialog(final Context context) {
90 AlertDialog.Builder builder = new AlertDialog.Builder(context);
91 builder.setTitle(R.string.permission_dialog_title)
92 .setMessage(R.string.permission_dialog_message)
93 .setPositiveButton(R.string.action_grant_permission, (dialog, which) -> {
95 context.startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
96 Uri.parse("package:" + BuildConfig.APPLICATION_ID)));
97 } catch (ActivityNotFoundException e) {
98 showErrorDialog(context, "SYSTEM_ALERT_WINDOW");
102 AlertDialog dialog = builder.create();
104 dialog.setCancelable(false);
107 public static void showErrorDialog(final Context context, String appopCmd) {
108 AlertDialog.Builder builder = new AlertDialog.Builder(context);
109 builder.setTitle(R.string.error_dialog_title)
110 .setMessage(context.getString(R.string.error_dialog_message, BuildConfig.APPLICATION_ID, appopCmd))
111 .setPositiveButton(R.string.action_ok, null);
113 AlertDialog dialog = builder.create();
117 public static void lockDevice(Context context) {
118 ComponentName component = new ComponentName(context, LockDeviceReceiver.class);
119 context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
120 PackageManager.DONT_KILL_APP);
122 DevicePolicyManager mDevicePolicyManager = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
123 if(mDevicePolicyManager.isAdminActive(component))
124 mDevicePolicyManager.lockNow();
126 Intent intent = new Intent(context, DummyActivity.class);
127 intent.putExtra("device_admin", true);
128 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
129 context.startActivity(intent);
133 public static void showPowerMenu(Context context) {
134 ComponentName component = new ComponentName(context, PowerMenuService.class);
135 context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
136 PackageManager.DONT_KILL_APP);
138 if(isAccessibilityServiceEnabled(context))
139 LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.SHOW_POWER_MENU"));
141 Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
142 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
145 context.startActivity(intent);
146 showToastLong(context, R.string.enable_accessibility);
147 } catch (ActivityNotFoundException e) {
148 showToast(context, R.string.lock_device_not_supported);
153 private static boolean isAccessibilityServiceEnabled(Context context) {
154 String accessibilityServices = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
155 ComponentName component = new ComponentName(context, PowerMenuService.class);
157 return accessibilityServices != null
158 && (accessibilityServices.contains(component.flattenToString())
159 || accessibilityServices.contains(component.flattenToShortString()));
162 public static void showToast(Context context, int message) {
163 showToast(context, context.getString(message), Toast.LENGTH_SHORT);
166 public static void showToastLong(Context context, int message) {
167 showToast(context, context.getString(message), Toast.LENGTH_LONG);
170 public static void showToast(Context context, String message, int length) {
173 toast = ToastCompat.makeText(context, message, length);
177 public static void cancelToast() {
178 if(toast != null) toast.cancel();
181 public static void startShortcut(Context context, String packageName, String componentName, ShortcutInfo shortcut) {
192 public static void launchApp(final Context context,
193 final String packageName,
194 final String componentName,
195 final long userId, final String windowSize,
196 final boolean launchedFromTaskbar,
197 final boolean openInNewWindow) {
208 private static void launchApp(final Context context,
209 final String packageName,
210 final String componentName,
211 final long userId, final String windowSize,
212 final boolean launchedFromTaskbar,
213 final boolean openInNewWindow,
214 final ShortcutInfo shortcut) {
215 boolean shouldDelay = false;
217 SharedPreferences pref = getSharedPreferences(context);
218 FreeformHackHelper helper = FreeformHackHelper.getInstance();
219 boolean openInFullscreen = pref.getBoolean("open_in_fullscreen", true);
220 boolean freeformHackActive = openInNewWindow
221 ? helper.isInFreeformWorkspace()
223 ? helper.isInFreeformWorkspace()
224 : helper.isFreeformHackActive());
226 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
227 && pref.getBoolean("freeform_hack", false)
228 && !freeformHackActive) {
231 new Handler().postDelayed(() -> {
232 startFreeformHack(context, true, launchedFromTaskbar);
234 new Handler().postDelayed(() -> continueLaunchingApp(context, packageName, componentName, userId,
235 windowSize, launchedFromTaskbar, openInNewWindow, shortcut), 100);
236 }, launchedFromTaskbar ? 0 : 100);
239 if(!helper.isFreeformHackActive()) {
241 continueLaunchingApp(context, packageName, componentName, userId,
242 windowSize, launchedFromTaskbar, openInNewWindow, shortcut);
243 } else if(helper.isInFreeformWorkspace() || !openInFullscreen)
244 continueLaunchingApp(context, packageName, componentName, userId,
245 windowSize, launchedFromTaskbar, openInNewWindow, shortcut);
248 @SuppressWarnings("deprecation")
249 @TargetApi(Build.VERSION_CODES.N)
250 public static void startFreeformHack(Context context, boolean checkMultiWindow, boolean launchedFromTaskbar) {
251 Intent freeformHackIntent = new Intent(context, InvisibleActivityFreeform.class);
252 freeformHackIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
255 freeformHackIntent.putExtra("check_multiwindow", true);
257 if(launchedFromTaskbar) {
258 SharedPreferences pref = getSharedPreferences(context);
259 if(pref.getBoolean("disable_animations", false))
260 freeformHackIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
263 launchAppLowerRight(context, freeformHackIntent);
266 @TargetApi(Build.VERSION_CODES.N)
267 private static void continueLaunchingApp(Context context,
269 String componentName,
272 boolean launchedFromTaskbar,
273 boolean openInNewWindow,
274 ShortcutInfo shortcut) {
275 SharedPreferences pref = getSharedPreferences(context);
276 Intent intent = new Intent();
277 intent.setComponent(ComponentName.unflattenFromString(componentName));
278 intent.setAction(Intent.ACTION_MAIN);
279 intent.addCategory(Intent.CATEGORY_LAUNCHER);
280 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
281 intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
283 if(FreeformHackHelper.getInstance().isInFreeformWorkspace())
284 intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
286 if(launchedFromTaskbar) {
287 if(pref.getBoolean("disable_animations", false))
288 intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
291 if(openInNewWindow || pref.getBoolean("force_new_window", false)) {
292 intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
294 ActivityInfo activityInfo = intent.resolveActivityInfo(context.getPackageManager(), 0);
295 if(activityInfo != null) {
296 switch(activityInfo.launchMode) {
297 case ActivityInfo.LAUNCH_SINGLE_TASK:
298 case ActivityInfo.LAUNCH_SINGLE_INSTANCE:
299 intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
305 if(windowSize == null) {
306 if(pref.getBoolean("save_window_sizes", true))
307 windowSize = SavedWindowSizes.getInstance(context).getWindowSize(context, packageName);
309 windowSize = pref.getString("window_size", "standard");
312 if(Build.VERSION.SDK_INT < Build.VERSION_CODES.N || !pref.getBoolean("freeform_hack", false)) {
313 if(shortcut == null) {
314 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
315 if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
317 context.startActivity(intent, null);
318 } catch (ActivityNotFoundException e) {
319 launchAndroidForWork(context, intent.getComponent(), null, userId);
320 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
322 launchAndroidForWork(context, intent.getComponent(), null, userId);
324 launchShortcut(context, shortcut, null);
325 } else switch(windowSize) {
327 if(FreeformHackHelper.getInstance().isInFreeformWorkspace()) {
328 if(shortcut == null) {
329 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
330 if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
332 context.startActivity(intent);
333 } catch (ActivityNotFoundException e) {
334 launchAndroidForWork(context, intent.getComponent(), null, userId);
335 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
337 launchAndroidForWork(context, intent.getComponent(), null, userId);
339 launchShortcut(context, shortcut, null);
341 launchMode1(context, intent, 1, userId, shortcut);
344 launchMode1(context, intent, 2, userId, shortcut);
347 launchMode2(context, intent, FULLSCREEN, userId, shortcut);
350 launchMode2(context, intent, LEFT, userId, shortcut);
353 launchMode2(context, intent, RIGHT, userId, shortcut);
356 launchMode3(context, intent, userId, shortcut);
360 if(pref.getBoolean("hide_taskbar", true) && !FreeformHackHelper.getInstance().isInFreeformWorkspace())
361 LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_TASKBAR"));
363 LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_START_MENU"));
366 @SuppressWarnings("deprecation")
367 @TargetApi(Build.VERSION_CODES.N)
368 private static void launchMode1(Context context, Intent intent, int factor, long userId, ShortcutInfo shortcut) {
369 DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
370 Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
372 int width1 = display.getWidth() / (4 * factor);
373 int width2 = display.getWidth() - width1;
374 int height1 = display.getHeight() / (4 * factor);
375 int height2 = display.getHeight() - height1;
377 Bundle bundle = ActivityOptions.makeBasic().setLaunchBounds(new Rect(
384 if(shortcut == null) {
385 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
386 if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
388 context.startActivity(intent, bundle);
389 } catch (ActivityNotFoundException e) {
390 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
391 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
393 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
395 launchShortcut(context, shortcut, bundle);
398 @SuppressWarnings("deprecation")
399 @TargetApi(Build.VERSION_CODES.N)
400 private static void launchMode2(Context context, Intent intent, int launchType, long userId, ShortcutInfo shortcut) {
401 DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
402 Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
404 int statusBarHeight = getStatusBarHeight(context);
405 String position = getTaskbarPosition(context);
407 boolean isPortrait = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
408 boolean isLandscape = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
410 int left = launchType == RIGHT && isLandscape
411 ? display.getWidth() / 2
414 int top = launchType == RIGHT && isPortrait
415 ? display.getHeight() / 2
418 int right = launchType == LEFT && isLandscape
419 ? display.getWidth() / 2
420 : display.getWidth();
422 int bottom = launchType == LEFT && isPortrait
423 ? display.getHeight() / 2
424 : display.getHeight();
426 int iconSize = context.getResources().getDimensionPixelSize(R.dimen.icon_size);
428 if(position.contains("vertical_left")) {
429 if(launchType != RIGHT || isPortrait) left = left + iconSize;
430 } else if(position.contains("vertical_right")) {
431 if(launchType != LEFT || isPortrait) right = right - iconSize;
432 } else if(position.contains("bottom")) {
433 if(isLandscape || (launchType != LEFT && isPortrait))
434 bottom = bottom - iconSize;
435 } else if(isLandscape || (launchType != RIGHT && isPortrait))
436 top = top + iconSize;
438 Bundle bundle = ActivityOptions.makeBasic().setLaunchBounds(new Rect(
445 if(shortcut == null) {
446 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
447 if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
449 context.startActivity(intent, bundle);
450 } catch (ActivityNotFoundException e) {
451 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
452 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
454 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
456 launchShortcut(context, shortcut, bundle);
459 @SuppressWarnings("deprecation")
460 @TargetApi(Build.VERSION_CODES.N)
461 private static void launchMode3(Context context, Intent intent, long userId, ShortcutInfo shortcut) {
462 DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
463 Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
465 int width1 = display.getWidth() / 2;
466 int width2 = context.getResources().getDimensionPixelSize(R.dimen.phone_size_width) / 2;
467 int height1 = display.getHeight() / 2;
468 int height2 = context.getResources().getDimensionPixelSize(R.dimen.phone_size_height) / 2;
470 Bundle bundle = ActivityOptions.makeBasic().setLaunchBounds(new Rect(
477 if(shortcut == null) {
478 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
479 if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
481 context.startActivity(intent, bundle);
482 } catch (ActivityNotFoundException e) {
483 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
484 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
486 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
488 launchShortcut(context, shortcut, bundle);
491 private static void launchAndroidForWork(Context context, ComponentName componentName, Bundle bundle, long userId) {
492 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
493 LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
496 launcherApps.startMainActivity(componentName, userManager.getUserForSerialNumber(userId), null, bundle);
497 } catch (ActivityNotFoundException | NullPointerException e) { /* Gracefully fail */ }
500 @TargetApi(Build.VERSION_CODES.N_MR1)
501 private static void launchShortcut(Context context, ShortcutInfo shortcut, Bundle bundle) {
502 LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
505 launcherApps.startShortcut(shortcut, null, bundle);
506 } catch (ActivityNotFoundException | NullPointerException e) { /* Gracefully fail */ }
509 public static void launchAppFullscreen(Context context, Intent intent) {
510 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
511 long userId = userManager.getSerialNumberForUser(Process.myUserHandle());
513 launchMode2(context, intent, FULLSCREEN, userId, null);
516 @SuppressWarnings("deprecation")
517 @TargetApi(Build.VERSION_CODES.N)
518 public static void launchAppLowerRight(Context context, Intent intent) {
519 DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
520 Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
522 context.startActivity(intent, ActivityOptions.makeBasic().setLaunchBounds(new Rect(
525 display.getWidth() + 1,
526 display.getHeight() + 1
528 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
531 public static void checkForUpdates(Context context) {
532 if(!BuildConfig.DEBUG) {
535 context.getPackageManager().getPackageInfo("com.android.vending", 0);
536 url = "https://play.google.com/store/apps/details?id=" + BuildConfig.APPLICATION_ID;
537 } catch (PackageManager.NameNotFoundException e) {
538 url = "https://f-droid.org/repository/browse/?fdid=" + BuildConfig.BASE_APPLICATION_ID;
541 Intent intent = new Intent(Intent.ACTION_VIEW);
542 intent.setData(Uri.parse(url));
543 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
546 context.startActivity(intent);
547 } catch (ActivityNotFoundException e) { /* Gracefully fail */ }
549 showToast(context, R.string.debug_build);
552 public static boolean launcherIsDefault(Context context) {
553 Intent homeIntent = new Intent(Intent.ACTION_MAIN);
554 homeIntent.addCategory(Intent.CATEGORY_HOME);
555 ResolveInfo defaultLauncher = context.getPackageManager().resolveActivity(homeIntent, PackageManager.MATCH_DEFAULT_ONLY);
557 return defaultLauncher.activityInfo.packageName.equals(BuildConfig.APPLICATION_ID);
560 public static void setCachedRotation(int cachedRotation) {
561 U.cachedRotation = cachedRotation;
564 public static String getTaskbarPosition(Context context) {
565 SharedPreferences pref = getSharedPreferences(context);
566 String position = pref.getString("position", "bottom_left");
568 if(pref.getBoolean("anchor", false)) {
569 WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
570 int rotation = cachedRotation != null ? cachedRotation : windowManager.getDefaultDisplay().getRotation();
575 case Surface.ROTATION_0:
576 return "bottom_left";
577 case Surface.ROTATION_90:
578 return "bottom_vertical_right";
579 case Surface.ROTATION_180:
581 case Surface.ROTATION_270:
582 return "top_vertical_left";
585 case "bottom_vertical_left":
587 case Surface.ROTATION_0:
588 return "bottom_vertical_left";
589 case Surface.ROTATION_90:
590 return "bottom_right";
591 case Surface.ROTATION_180:
592 return "top_vertical_right";
593 case Surface.ROTATION_270:
599 case Surface.ROTATION_0:
600 return "bottom_right";
601 case Surface.ROTATION_90:
602 return "top_vertical_right";
603 case Surface.ROTATION_180:
605 case Surface.ROTATION_270:
606 return "bottom_vertical_left";
609 case "bottom_vertical_right":
611 case Surface.ROTATION_0:
612 return "bottom_vertical_right";
613 case Surface.ROTATION_90:
615 case Surface.ROTATION_180:
616 return "top_vertical_left";
617 case Surface.ROTATION_270:
618 return "bottom_left";
623 case Surface.ROTATION_0:
625 case Surface.ROTATION_90:
626 return "bottom_vertical_left";
627 case Surface.ROTATION_180:
628 return "bottom_right";
629 case Surface.ROTATION_270:
630 return "top_vertical_right";
633 case "top_vertical_left":
635 case Surface.ROTATION_0:
636 return "top_vertical_left";
637 case Surface.ROTATION_90:
638 return "bottom_left";
639 case Surface.ROTATION_180:
640 return "bottom_vertical_right";
641 case Surface.ROTATION_270:
647 case Surface.ROTATION_0:
649 case Surface.ROTATION_90:
650 return "top_vertical_left";
651 case Surface.ROTATION_180:
652 return "bottom_left";
653 case Surface.ROTATION_270:
654 return "bottom_vertical_right";
657 case "top_vertical_right":
659 case Surface.ROTATION_0:
660 return "top_vertical_right";
661 case Surface.ROTATION_90:
663 case Surface.ROTATION_180:
664 return "bottom_vertical_left";
665 case Surface.ROTATION_270:
666 return "bottom_right";
675 private static int getMaxNumOfColumns(Context context) {
676 SharedPreferences pref = getSharedPreferences(context);
677 DisplayMetrics metrics = context.getResources().getDisplayMetrics();
678 float baseTaskbarSize = context.getResources().getDimension(pref.getBoolean("dashboard", false) ? R.dimen.base_taskbar_size_dashboard : R.dimen.base_taskbar_size) / metrics.density;
679 int numOfColumns = 0;
681 float maxScreenSize = getTaskbarPosition(context).contains("vertical")
682 ? (metrics.heightPixels - getStatusBarHeight(context)) / metrics.density
683 : metrics.widthPixels / metrics.density;
685 float iconSize = context.getResources().getDimension(R.dimen.icon_size) / metrics.density;
687 int userMaxNumOfColumns = Integer.valueOf(pref.getString("max_num_of_recents", "10"));
689 while(baseTaskbarSize + iconSize < maxScreenSize
690 && numOfColumns < userMaxNumOfColumns) {
691 baseTaskbarSize = baseTaskbarSize + iconSize;
698 public static int getMaxNumOfEntries(Context context) {
699 SharedPreferences pref = getSharedPreferences(context);
700 return pref.getBoolean("disable_scrolling_list", false)
701 ? getMaxNumOfColumns(context)
702 : Integer.valueOf(pref.getString("max_num_of_recents", "10"));
705 public static int getStatusBarHeight(Context context) {
706 int statusBarHeight = 0;
707 int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
709 statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
711 return statusBarHeight;
714 public static void refreshPinnedIcons(Context context) {
715 IconCache.getInstance(context).clearCache();
717 PinnedBlockedApps pba = PinnedBlockedApps.getInstance(context);
718 List<AppEntry> pinnedAppsList = new ArrayList<>(pba.getPinnedApps());
719 List<AppEntry> blockedAppsList = new ArrayList<>(pba.getBlockedApps());
720 PackageManager pm = context.getPackageManager();
724 for(AppEntry entry : pinnedAppsList) {
725 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
726 LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
728 final List<UserHandle> userHandles = userManager.getUserProfiles();
729 LauncherActivityInfo appInfo = null;
731 for(UserHandle handle : userHandles) {
732 List<LauncherActivityInfo> list = launcherApps.getActivityList(entry.getPackageName(), handle);
733 if(!list.isEmpty()) {
734 // Google App workaround
735 if(!entry.getPackageName().equals("com.google.android.googlequicksearchbox"))
736 appInfo = list.get(0);
738 boolean added = false;
739 for(LauncherActivityInfo info : list) {
740 if(info.getName().equals("com.google.android.googlequicksearchbox.SearchActivity")) {
746 if(!added) appInfo = list.get(0);
753 if(appInfo != null) {
754 AppEntry newEntry = new AppEntry(
755 entry.getPackageName(),
756 entry.getComponentName(),
758 IconCache.getInstance(context).getIcon(context, pm, appInfo),
761 newEntry.setUserId(entry.getUserId(context));
762 pba.addPinnedApp(context, newEntry);
766 for(AppEntry entry : blockedAppsList) {
767 pba.addBlockedApp(context, entry);
771 public static Intent getShortcutIntent(Context context) {
772 Intent shortcutIntent = new Intent(context, ShortcutActivity.class);
773 shortcutIntent.setAction(Intent.ACTION_MAIN);
774 shortcutIntent.putExtra("is_launching_shortcut", true);
776 BitmapDrawable drawable = (BitmapDrawable) context.getDrawable(R.mipmap.ic_freeform_mode);
778 Intent intent = new Intent();
779 intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
780 if(drawable != null) intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, drawable.getBitmap());
781 intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, context.getString(R.string.pref_header_freeform));
786 public static Intent getStartStopIntent(Context context) {
787 Intent shortcutIntent = new Intent(context, StartTaskbarActivity.class);
788 shortcutIntent.setAction(Intent.ACTION_MAIN);
789 shortcutIntent.putExtra("is_launching_shortcut", true);
791 BitmapDrawable drawable = (BitmapDrawable) context.getDrawable(R.mipmap.ic_launcher);
793 Intent intent = new Intent();
794 intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
795 if(drawable != null) intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, drawable.getBitmap());
796 intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, context.getString(R.string.start_taskbar));
801 public static boolean hasFreeformSupport(Context context) {
802 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
803 && (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT)
804 || Settings.Global.getInt(context.getContentResolver(), "enable_freeform_support", -1) == 1
805 || Settings.Global.getInt(context.getContentResolver(), "force_resizable_activities", -1) == 1);
808 public static boolean isServiceRunning(Context context, Class<? extends Service> cls) {
809 ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
810 for(ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
811 if(cls.getName().equals(service.service.getClassName()))
818 public static int getBackgroundTint(Context context) {
819 SharedPreferences pref = getSharedPreferences(context);
821 // Import old background tint preference
822 if(pref.contains("show_background")) {
823 SharedPreferences.Editor editor = pref.edit();
825 if(!pref.getBoolean("show_background", true))
826 editor.putInt("background_tint", 0).apply();
828 editor.remove("show_background");
832 return pref.getInt("background_tint", context.getResources().getInteger(R.integer.translucent_gray));
835 public static int getAccentColor(Context context) {
836 SharedPreferences pref = getSharedPreferences(context);
837 return pref.getInt("accent_color", context.getResources().getInteger(R.integer.translucent_white));
840 @TargetApi(Build.VERSION_CODES.M)
841 public static boolean canDrawOverlays(Context context) {
842 return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(context);