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.DialogInterface;
28 import android.content.Intent;
29 import android.content.SharedPreferences;
30 import android.content.pm.ActivityInfo;
31 import android.content.pm.LauncherActivityInfo;
32 import android.content.pm.LauncherApps;
33 import android.content.pm.PackageManager;
34 import android.content.pm.ResolveInfo;
35 import android.content.pm.ShortcutInfo;
36 import android.content.res.Configuration;
37 import android.graphics.Rect;
38 import android.graphics.drawable.BitmapDrawable;
39 import android.hardware.display.DisplayManager;
40 import android.net.Uri;
41 import android.os.Build;
42 import android.os.Bundle;
43 import android.os.Handler;
44 import android.os.Process;
45 import android.os.UserHandle;
46 import android.os.UserManager;
47 import android.provider.Settings;
48 import android.support.v4.content.LocalBroadcastManager;
49 import android.util.DisplayMetrics;
50 import android.view.Display;
51 import android.view.Surface;
52 import android.view.WindowManager;
53 import android.widget.Toast;
55 import com.farmerbb.taskbar.BuildConfig;
56 import com.farmerbb.taskbar.R;
57 import com.farmerbb.taskbar.activity.DummyActivity;
58 import com.farmerbb.taskbar.activity.InvisibleActivityFreeform;
59 import com.farmerbb.taskbar.activity.ShortcutActivity;
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;
75 private static final int FULLSCREEN = 0;
76 private static final int LEFT = -1;
77 private static final int RIGHT = 1;
79 public static final int HIDDEN = 0;
80 public static final int TOP_APPS = 1;
82 public static SharedPreferences getSharedPreferences(Context context) {
83 if(pref == null) pref = context.getSharedPreferences(BuildConfig.APPLICATION_ID + "_preferences", Context.MODE_PRIVATE);
87 @TargetApi(Build.VERSION_CODES.M)
88 public static void showPermissionDialog(final Context context) {
89 AlertDialog.Builder builder = new AlertDialog.Builder(context);
90 builder.setTitle(R.string.permission_dialog_title)
91 .setMessage(R.string.permission_dialog_message)
92 .setPositiveButton(R.string.action_grant_permission, new DialogInterface.OnClickListener() {
94 public void onClick(DialogInterface dialog, int which) {
96 context.startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
97 Uri.parse("package:" + BuildConfig.APPLICATION_ID)));
98 } catch (ActivityNotFoundException e) {
99 showErrorDialog(context, "SYSTEM_ALERT_WINDOW");
104 AlertDialog dialog = builder.create();
106 dialog.setCancelable(false);
109 public static void showErrorDialog(final Context context, String appopCmd) {
110 AlertDialog.Builder builder = new AlertDialog.Builder(context);
111 builder.setTitle(R.string.error_dialog_title)
112 .setMessage(context.getString(R.string.error_dialog_message, BuildConfig.APPLICATION_ID, appopCmd))
113 .setPositiveButton(R.string.action_ok, null);
115 AlertDialog dialog = builder.create();
119 public static void lockDevice(Context context) {
120 ComponentName component = new ComponentName(context, LockDeviceReceiver.class);
121 context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
122 PackageManager.DONT_KILL_APP);
124 DevicePolicyManager mDevicePolicyManager = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
125 if(mDevicePolicyManager.isAdminActive(component))
126 mDevicePolicyManager.lockNow();
128 Intent intent = new Intent(context, DummyActivity.class);
129 intent.putExtra("device_admin", true);
130 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
131 context.startActivity(intent);
135 public static void showPowerMenu(Context context) {
136 ComponentName component = new ComponentName(context, PowerMenuService.class);
137 context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
138 PackageManager.DONT_KILL_APP);
140 if(isAccessibilityServiceEnabled(context))
141 LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.SHOW_POWER_MENU"));
143 Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
144 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
147 context.startActivity(intent);
148 showToastLong(context, R.string.enable_accessibility);
149 } catch (ActivityNotFoundException e) {
150 showToast(context, R.string.lock_device_not_supported);
155 private static boolean isAccessibilityServiceEnabled(Context context) {
156 String accessibilityServices = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
157 ComponentName component = new ComponentName(context, PowerMenuService.class);
159 return accessibilityServices != null
160 && (accessibilityServices.contains(component.flattenToString())
161 || accessibilityServices.contains(component.flattenToShortString()));
164 public static void showToast(Context context, int message) {
165 showToast(context, context.getString(message), Toast.LENGTH_SHORT);
168 public static void showToastLong(Context context, int message) {
169 showToast(context, context.getString(message), Toast.LENGTH_LONG);
172 public static void showToast(Context context, String message, int length) {
173 ToastCompat.makeText(context, message, length).show();
176 public static void startShortcut(Context context, String packageName, String componentName, ShortcutInfo shortcut) {
187 public static void launchApp(final Context context,
188 final String packageName,
189 final String componentName,
190 final long userId, final String windowSize,
191 final boolean launchedFromTaskbar,
192 final boolean openInNewWindow) {
203 private static void launchApp(final Context context,
204 final String packageName,
205 final String componentName,
206 final long userId, final String windowSize,
207 final boolean launchedFromTaskbar,
208 final boolean openInNewWindow,
209 final ShortcutInfo shortcut) {
210 boolean shouldDelay = false;
212 SharedPreferences pref = getSharedPreferences(context);
213 boolean openInFullscreen = pref.getBoolean("open_in_fullscreen", true);
214 boolean freeformHackActive = openInNewWindow
215 ? FreeformHackHelper.getInstance().isInFreeformWorkspace()
217 ? FreeformHackHelper.getInstance().isInFreeformWorkspace()
218 : FreeformHackHelper.getInstance().isFreeformHackActive());
220 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
221 && pref.getBoolean("freeform_hack", false)
222 && !freeformHackActive) {
225 new Handler().postDelayed(new Runnable() {
228 startFreeformHack(context, true, launchedFromTaskbar);
230 new Handler().postDelayed(new Runnable() {
233 continueLaunchingApp(context, packageName, componentName, userId,
234 windowSize, launchedFromTaskbar, openInNewWindow, shortcut);
238 }, launchedFromTaskbar ? 0 : 100);
241 if(!FreeformHackHelper.getInstance().isFreeformHackActive()) {
243 continueLaunchingApp(context, packageName, componentName, userId,
244 windowSize, launchedFromTaskbar, openInNewWindow, shortcut);
245 } else if(FreeformHackHelper.getInstance().isInFreeformWorkspace() || !openInFullscreen)
246 continueLaunchingApp(context, packageName, componentName, userId,
247 windowSize, launchedFromTaskbar, openInNewWindow, shortcut);
250 @SuppressWarnings("deprecation")
251 @TargetApi(Build.VERSION_CODES.N)
252 public static void startFreeformHack(Context context, boolean checkMultiWindow, boolean launchedFromTaskbar) {
253 Intent freeformHackIntent = new Intent(context, InvisibleActivityFreeform.class);
254 freeformHackIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
257 freeformHackIntent.putExtra("check_multiwindow", true);
259 if(launchedFromTaskbar) {
260 SharedPreferences pref = getSharedPreferences(context);
261 if(pref.getBoolean("disable_animations", false))
262 freeformHackIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
265 DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
266 Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
268 context.startActivity(freeformHackIntent, ActivityOptions.makeBasic().setLaunchBounds(new Rect(
271 display.getWidth() + 1,
272 display.getHeight() + 1
274 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
277 @TargetApi(Build.VERSION_CODES.N)
278 private static void continueLaunchingApp(Context context,
280 String componentName,
283 boolean launchedFromTaskbar,
284 boolean openInNewWindow,
285 ShortcutInfo shortcut) {
286 SharedPreferences pref = getSharedPreferences(context);
287 Intent intent = new Intent();
288 intent.setComponent(ComponentName.unflattenFromString(componentName));
289 intent.setAction(Intent.ACTION_MAIN);
290 intent.addCategory(Intent.CATEGORY_LAUNCHER);
291 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
292 intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
294 if(FreeformHackHelper.getInstance().isInFreeformWorkspace())
295 intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
297 if(launchedFromTaskbar) {
298 if(pref.getBoolean("disable_animations", false))
299 intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
302 if(openInNewWindow || pref.getBoolean("force_new_window", false)) {
303 intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
305 ActivityInfo activityInfo = intent.resolveActivityInfo(context.getPackageManager(), 0);
306 if(activityInfo != null) {
307 switch(activityInfo.launchMode) {
308 case ActivityInfo.LAUNCH_SINGLE_TASK:
309 case ActivityInfo.LAUNCH_SINGLE_INSTANCE:
310 intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
316 if(windowSize == null) {
317 if(pref.getBoolean("save_window_sizes", true))
318 windowSize = SavedWindowSizes.getInstance(context).getWindowSize(context, packageName);
320 windowSize = pref.getString("window_size", "standard");
323 if(Build.VERSION.SDK_INT < Build.VERSION_CODES.N || !pref.getBoolean("freeform_hack", false)) {
324 if(shortcut == null) {
325 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
326 if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
328 context.startActivity(intent, null);
329 } catch (ActivityNotFoundException e) {
330 launchAndroidForWork(context, intent.getComponent(), null, userId);
331 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
333 launchAndroidForWork(context, intent.getComponent(), null, userId);
335 launchShortcut(context, shortcut, null);
336 } else switch(windowSize) {
338 if(FreeformHackHelper.getInstance().isInFreeformWorkspace()) {
339 if(shortcut == null) {
340 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
341 if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
343 context.startActivity(intent);
344 } catch (ActivityNotFoundException e) {
345 launchAndroidForWork(context, intent.getComponent(), null, userId);
346 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
348 launchAndroidForWork(context, intent.getComponent(), null, userId);
350 launchShortcut(context, shortcut, null);
352 launchMode1(context, intent, 1, userId, shortcut);
355 launchMode1(context, intent, 2, userId, shortcut);
358 launchMode2(context, intent, FULLSCREEN, userId, shortcut);
361 launchMode2(context, intent, LEFT, userId, shortcut);
364 launchMode2(context, intent, RIGHT, userId, shortcut);
367 launchMode3(context, intent, userId, shortcut);
371 if(pref.getBoolean("hide_taskbar", true) && !FreeformHackHelper.getInstance().isInFreeformWorkspace())
372 LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_TASKBAR"));
374 LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_START_MENU"));
377 @SuppressWarnings("deprecation")
378 @TargetApi(Build.VERSION_CODES.N)
379 private static void launchMode1(Context context, Intent intent, int factor, long userId, ShortcutInfo shortcut) {
380 DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
381 Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
383 int width1 = display.getWidth() / (4 * factor);
384 int width2 = display.getWidth() - width1;
385 int height1 = display.getHeight() / (4 * factor);
386 int height2 = display.getHeight() - height1;
388 Bundle bundle = ActivityOptions.makeBasic().setLaunchBounds(new Rect(
395 if(shortcut == null) {
396 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
397 if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
399 context.startActivity(intent, bundle);
400 } catch (ActivityNotFoundException e) {
401 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
402 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
404 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
406 launchShortcut(context, shortcut, bundle);
409 @SuppressWarnings("deprecation")
410 @TargetApi(Build.VERSION_CODES.N)
411 private static void launchMode2(Context context, Intent intent, int launchType, long userId, ShortcutInfo shortcut) {
412 DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
413 Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
415 int statusBarHeight = getStatusBarHeight(context);
416 String position = getTaskbarPosition(context);
418 boolean isPortrait = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
419 boolean isLandscape = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
421 int left = launchType == RIGHT && isLandscape
422 ? display.getWidth() / 2
425 int top = launchType == RIGHT && isPortrait
426 ? display.getHeight() / 2
429 int right = launchType == LEFT && isLandscape
430 ? display.getWidth() / 2
431 : display.getWidth();
433 int bottom = launchType == LEFT && isPortrait
434 ? display.getHeight() / 2
435 : display.getHeight();
437 int iconSize = context.getResources().getDimensionPixelSize(R.dimen.icon_size);
439 if(position.contains("vertical_left")) {
440 if(launchType != RIGHT || isPortrait) left = left + iconSize;
441 } else if(position.contains("vertical_right")) {
442 if(launchType != LEFT || isPortrait) right = right - iconSize;
443 } else if(position.contains("bottom")) {
444 if(isLandscape || (launchType != LEFT && isPortrait))
445 bottom = bottom - iconSize;
446 } else if(isLandscape || (launchType != RIGHT && isPortrait))
447 top = top + iconSize;
449 Bundle bundle = ActivityOptions.makeBasic().setLaunchBounds(new Rect(
456 if(shortcut == null) {
457 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
458 if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
460 context.startActivity(intent, bundle);
461 } catch (ActivityNotFoundException e) {
462 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
463 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
465 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
467 launchShortcut(context, shortcut, bundle);
470 @SuppressWarnings("deprecation")
471 @TargetApi(Build.VERSION_CODES.N)
472 private static void launchMode3(Context context, Intent intent, long userId, ShortcutInfo shortcut) {
473 DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
474 Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
476 int width1 = display.getWidth() / 2;
477 int width2 = context.getResources().getDimensionPixelSize(R.dimen.phone_size_width) / 2;
478 int height1 = display.getHeight() / 2;
479 int height2 = context.getResources().getDimensionPixelSize(R.dimen.phone_size_height) / 2;
481 Bundle bundle = ActivityOptions.makeBasic().setLaunchBounds(new Rect(
488 if(shortcut == null) {
489 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
490 if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
492 context.startActivity(intent, bundle);
493 } catch (ActivityNotFoundException e) {
494 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
495 } catch (IllegalArgumentException e) { /* Gracefully fail */ }
497 launchAndroidForWork(context, intent.getComponent(), bundle, userId);
499 launchShortcut(context, shortcut, bundle);
502 private static void launchAndroidForWork(Context context, ComponentName componentName, Bundle bundle, long userId) {
503 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
504 LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
507 launcherApps.startMainActivity(componentName, userManager.getUserForSerialNumber(userId), null, bundle);
508 } catch (ActivityNotFoundException | NullPointerException e) { /* Gracefully fail */ }
511 @TargetApi(Build.VERSION_CODES.N_MR1)
512 private static void launchShortcut(Context context, ShortcutInfo shortcut, Bundle bundle) {
513 LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
516 launcherApps.startShortcut(shortcut, null, bundle);
517 } catch (ActivityNotFoundException | NullPointerException e) { /* Gracefully fail */ }
520 public static void launchAppFullscreen(Context context, Intent intent) {
521 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
522 long userId = userManager.getSerialNumberForUser(Process.myUserHandle());
524 launchMode2(context, intent, FULLSCREEN, userId, null);
527 public static void checkForUpdates(Context context) {
530 context.getPackageManager().getPackageInfo("com.android.vending", 0);
531 url = "https://play.google.com/store/apps/details?id=" + BuildConfig.APPLICATION_ID;
532 } catch (PackageManager.NameNotFoundException e) {
533 url = "https://f-droid.org/repository/browse/?fdid=" + BuildConfig.BASE_APPLICATION_ID;
536 Intent intent = new Intent(Intent.ACTION_VIEW);
537 intent.setData(Uri.parse(url));
538 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
541 context.startActivity(intent);
542 } catch (ActivityNotFoundException e) { /* Gracefully fail */ }
545 public static boolean launcherIsDefault(Context context) {
546 Intent homeIntent = new Intent(Intent.ACTION_MAIN);
547 homeIntent.addCategory(Intent.CATEGORY_HOME);
548 ResolveInfo defaultLauncher = context.getPackageManager().resolveActivity(homeIntent, PackageManager.MATCH_DEFAULT_ONLY);
550 return defaultLauncher.activityInfo.packageName.equals(BuildConfig.APPLICATION_ID);
553 public static void setCachedRotation(int cachedRotation) {
554 U.cachedRotation = cachedRotation;
557 public static String getTaskbarPosition(Context context) {
558 SharedPreferences pref = getSharedPreferences(context);
559 String position = pref.getString("position", "bottom_left");
561 if(pref.getBoolean("anchor", false)) {
562 WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
563 int rotation = cachedRotation != null ? cachedRotation : windowManager.getDefaultDisplay().getRotation();
568 case Surface.ROTATION_0:
569 return "bottom_left";
570 case Surface.ROTATION_90:
571 return "bottom_vertical_right";
572 case Surface.ROTATION_180:
574 case Surface.ROTATION_270:
575 return "top_vertical_left";
578 case "bottom_vertical_left":
580 case Surface.ROTATION_0:
581 return "bottom_vertical_left";
582 case Surface.ROTATION_90:
583 return "bottom_right";
584 case Surface.ROTATION_180:
585 return "top_vertical_right";
586 case Surface.ROTATION_270:
592 case Surface.ROTATION_0:
593 return "bottom_right";
594 case Surface.ROTATION_90:
595 return "top_vertical_right";
596 case Surface.ROTATION_180:
598 case Surface.ROTATION_270:
599 return "bottom_vertical_left";
602 case "bottom_vertical_right":
604 case Surface.ROTATION_0:
605 return "bottom_vertical_right";
606 case Surface.ROTATION_90:
608 case Surface.ROTATION_180:
609 return "top_vertical_left";
610 case Surface.ROTATION_270:
611 return "bottom_left";
616 case Surface.ROTATION_0:
618 case Surface.ROTATION_90:
619 return "bottom_vertical_left";
620 case Surface.ROTATION_180:
621 return "bottom_right";
622 case Surface.ROTATION_270:
623 return "top_vertical_right";
626 case "top_vertical_left":
628 case Surface.ROTATION_0:
629 return "top_vertical_left";
630 case Surface.ROTATION_90:
631 return "bottom_left";
632 case Surface.ROTATION_180:
633 return "bottom_vertical_right";
634 case Surface.ROTATION_270:
640 case Surface.ROTATION_0:
642 case Surface.ROTATION_90:
643 return "top_vertical_left";
644 case Surface.ROTATION_180:
645 return "bottom_left";
646 case Surface.ROTATION_270:
647 return "bottom_vertical_right";
650 case "top_vertical_right":
652 case Surface.ROTATION_0:
653 return "top_vertical_right";
654 case Surface.ROTATION_90:
656 case Surface.ROTATION_180:
657 return "bottom_vertical_left";
658 case Surface.ROTATION_270:
659 return "bottom_right";
668 private static int getMaxNumOfColumns(Context context) {
669 SharedPreferences pref = getSharedPreferences(context);
670 DisplayMetrics metrics = context.getResources().getDisplayMetrics();
671 float baseTaskbarSize = context.getResources().getDimension(pref.getBoolean("dashboard", false) ? R.dimen.base_taskbar_size_dashboard : R.dimen.base_taskbar_size) / metrics.density;
672 int numOfColumns = 0;
674 float maxScreenSize = getTaskbarPosition(context).contains("vertical")
675 ? (metrics.heightPixels - getStatusBarHeight(context)) / metrics.density
676 : metrics.widthPixels / metrics.density;
678 float iconSize = context.getResources().getDimension(R.dimen.icon_size) / metrics.density;
680 int userMaxNumOfColumns = Integer.valueOf(pref.getString("max_num_of_recents", "10"));
682 while(baseTaskbarSize + iconSize < maxScreenSize
683 && numOfColumns < userMaxNumOfColumns) {
684 baseTaskbarSize = baseTaskbarSize + iconSize;
691 public static int getMaxNumOfEntries(Context context) {
692 SharedPreferences pref = getSharedPreferences(context);
693 return pref.getBoolean("disable_scrolling_list", false)
694 ? getMaxNumOfColumns(context)
695 : Integer.valueOf(pref.getString("max_num_of_recents", "10"));
698 public static int getStatusBarHeight(Context context) {
699 int statusBarHeight = 0;
700 int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
702 statusBarHeight = context.getResources().getDimensionPixelSize(resourceId);
704 return statusBarHeight;
707 public static void refreshPinnedIcons(Context context) {
708 IconCache.getInstance(context).clearCache();
710 PinnedBlockedApps pba = PinnedBlockedApps.getInstance(context);
711 List<AppEntry> pinnedAppsList = new ArrayList<>(pba.getPinnedApps());
712 List<AppEntry> blockedAppsList = new ArrayList<>(pba.getBlockedApps());
713 PackageManager pm = context.getPackageManager();
717 for(AppEntry entry : pinnedAppsList) {
718 UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
719 LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
721 final List<UserHandle> userHandles = userManager.getUserProfiles();
722 LauncherActivityInfo appInfo = null;
724 for(UserHandle handle : userHandles) {
725 List<LauncherActivityInfo> list = launcherApps.getActivityList(entry.getPackageName(), handle);
726 if(!list.isEmpty()) {
727 // Google App workaround
728 if(!entry.getPackageName().equals("com.google.android.googlequicksearchbox"))
729 appInfo = list.get(0);
731 boolean added = false;
732 for(LauncherActivityInfo info : list) {
733 if(info.getName().equals("com.google.android.googlequicksearchbox.SearchActivity")) {
739 if(!added) appInfo = list.get(0);
746 if(appInfo != null) {
747 AppEntry newEntry = new AppEntry(
748 entry.getPackageName(),
749 entry.getComponentName(),
751 IconCache.getInstance(context).getIcon(context, pm, appInfo),
754 newEntry.setUserId(entry.getUserId(context));
755 pba.addPinnedApp(context, newEntry);
759 for(AppEntry entry : blockedAppsList) {
760 pba.addBlockedApp(context, entry);
764 public static Intent getShortcutIntent(Context context) {
765 Intent shortcutIntent = new Intent(context, ShortcutActivity.class);
766 shortcutIntent.setAction(Intent.ACTION_MAIN);
767 shortcutIntent.putExtra("is_launching_shortcut", true);
769 BitmapDrawable drawable = (BitmapDrawable) context.getDrawable(R.mipmap.ic_freeform_mode);
771 Intent intent = new Intent();
772 intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
773 if(drawable != null) intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, drawable.getBitmap());
774 intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, context.getString(R.string.pref_header_freeform));
779 public static boolean hasFreeformSupport(Context context) {
780 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
781 && (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT)
782 || Settings.Global.getInt(context.getContentResolver(), "enable_freeform_support", -1) == 1
783 || Settings.Global.getInt(context.getContentResolver(), "force_resizable_activities", -1) == 1);
786 public static boolean isServiceRunning(Context context, Class<? extends Service> cls) {
787 ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
788 for(ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
789 if(cls.getName().equals(service.service.getClassName()))
796 public static int getBackgroundTint(Context context) {
797 SharedPreferences pref = getSharedPreferences(context);
799 // Import old background tint preference
800 if(pref.contains("show_background")) {
801 SharedPreferences.Editor editor = pref.edit();
803 if(!pref.getBoolean("show_background", true))
804 editor.putInt("background_tint", 0).apply();
806 editor.remove("show_background");
810 return pref.getInt("background_tint", context.getResources().getInteger(R.integer.translucent_gray));
813 public static int getAccentColor(Context context) {
814 SharedPreferences pref = getSharedPreferences(context);
815 return pref.getInt("accent_color", context.getResources().getInteger(R.integer.translucent_white));