package com.farmerbb.taskbar.util;
import android.annotation.TargetApi;
+import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.AlertDialog;
+import android.app.Service;
import android.app.admin.DevicePolicyManager;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.pm.ShortcutInfo;
import android.content.res.Configuration;
+import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
-import android.hardware.display.DisplayManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import com.farmerbb.taskbar.activity.DummyActivity;
import com.farmerbb.taskbar.activity.InvisibleActivityFreeform;
import com.farmerbb.taskbar.activity.ShortcutActivity;
+import com.farmerbb.taskbar.activity.StartTaskbarActivity;
import com.farmerbb.taskbar.receiver.LockDeviceReceiver;
+import com.farmerbb.taskbar.service.DashboardService;
+import com.farmerbb.taskbar.service.NotificationService;
+import com.farmerbb.taskbar.service.PowerMenuService;
+import com.farmerbb.taskbar.service.StartMenuService;
+import com.farmerbb.taskbar.service.TaskbarService;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
private U() {}
private static SharedPreferences pref;
- private static Toast toast;
private static Integer cachedRotation;
- private static final int FULLSCREEN = 0;
+ private static final int MAXIMIZED = 0;
private static final int LEFT = -1;
private static final int RIGHT = 1;
public static final int HIDDEN = 0;
public static final int TOP_APPS = 1;
+ // From android.app.ActivityManager.StackId
+ private static final int FULLSCREEN_WORKSPACE_STACK_ID = 1;
+ private static final int FREEFORM_WORKSPACE_STACK_ID = 2;
+
public static SharedPreferences getSharedPreferences(Context context) {
if(pref == null) pref = context.getSharedPreferences(BuildConfig.APPLICATION_ID + "_preferences", Context.MODE_PRIVATE);
return pref;
}
@TargetApi(Build.VERSION_CODES.M)
- public static void showPermissionDialog(final Context context) {
+ public static AlertDialog showPermissionDialog(final Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(R.string.permission_dialog_title)
.setMessage(R.string.permission_dialog_message)
- .setPositiveButton(R.string.action_grant_permission, new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- try {
- context.startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION));
- } catch (ActivityNotFoundException e) {
- showErrorDialog(context, "SYSTEM_ALERT_WINDOW");
- }
+ .setPositiveButton(R.string.action_grant_permission, (dialog, which) -> {
+ try {
+ context.startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
+ Uri.parse("package:" + BuildConfig.APPLICATION_ID)));
+ } catch (ActivityNotFoundException e) {
+ showErrorDialog(context, "SYSTEM_ALERT_WINDOW");
}
});
AlertDialog dialog = builder.create();
dialog.show();
dialog.setCancelable(false);
+
+ return dialog;
}
public static void showErrorDialog(final Context context, String appopCmd) {
}
public static void lockDevice(Context context) {
- ComponentName component = new ComponentName(BuildConfig.APPLICATION_ID, LockDeviceReceiver.class.getName());
+ ComponentName component = new ComponentName(context, LockDeviceReceiver.class);
context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
if(mDevicePolicyManager.isAdminActive(component))
mDevicePolicyManager.lockNow();
else {
- Intent intent = new Intent(context, DummyActivity.class);
- intent.putExtra("device_admin", true);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(intent);
+ launchApp(context, () -> {
+ Intent intent = new Intent(context, DummyActivity.class);
+ intent.putExtra("device_admin", true);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ });
}
}
+ public static void sendAccessibilityAction(Context context, int action) {
+ ComponentName component = new ComponentName(context, PowerMenuService.class);
+ context.getPackageManager().setComponentEnabledSetting(component, PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
+ PackageManager.DONT_KILL_APP);
+
+ if(isAccessibilityServiceEnabled(context)) {
+ Intent intent = new Intent("com.farmerbb.taskbar.ACCESSIBILITY_ACTION");
+ intent.putExtra("action", action);
+ LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
+ } else {
+ launchApp(context, () -> {
+ Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ try {
+ context.startActivity(intent);
+ showToastLong(context, R.string.enable_accessibility);
+ } catch (ActivityNotFoundException e) {
+ showToast(context, R.string.lock_device_not_supported);
+ }
+ });
+ }
+ }
+
+ private static boolean isAccessibilityServiceEnabled(Context context) {
+ String accessibilityServices = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
+ ComponentName component = new ComponentName(context, PowerMenuService.class);
+
+ return accessibilityServices != null
+ && (accessibilityServices.contains(component.flattenToString())
+ || accessibilityServices.contains(component.flattenToShortString()));
+ }
+
public static void showToast(Context context, int message) {
showToast(context, context.getString(message), Toast.LENGTH_SHORT);
}
}
public static void showToast(Context context, String message, int length) {
- if(toast != null) toast.cancel();
+ cancelToast();
+
+ ToastInterface toast;
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1
+ || BuildConfig.APPLICATION_ID.equals(BuildConfig.ANDROIDX86_APPLICATION_ID))
+ toast = new ToastFrameworkImpl(context, message, length);
+ else
+ toast = new ToastCompatImpl(context, message, length);
- toast = Toast.makeText(context, message, length);
toast.show();
+
+ ToastHelper.getInstance().setLastToast(toast);
+ }
+
+ private static void cancelToast() {
+ ToastInterface toast = ToastHelper.getInstance().getLastToast();
+ if(toast != null) toast.cancel();
+ }
+
+ public static void startShortcut(Context context, String packageName, String componentName, ShortcutInfo shortcut) {
+ launchApp(context,
+ packageName,
+ componentName,
+ 0,
+ null,
+ false,
+ false,
+ shortcut);
}
public static void launchApp(final Context context,
final String componentName,
final long userId, final String windowSize,
final boolean launchedFromTaskbar,
- final boolean padStatusBar,
final boolean openInNewWindow) {
- boolean shouldDelay = false;
+ launchApp(context,
+ packageName,
+ componentName,
+ userId,
+ windowSize,
+ launchedFromTaskbar,
+ openInNewWindow,
+ null);
+ }
+ private static void launchApp(final Context context,
+ final String packageName,
+ final String componentName,
+ final long userId, final String windowSize,
+ final boolean launchedFromTaskbar,
+ final boolean openInNewWindow,
+ final ShortcutInfo shortcut) {
+ launchApp(context, launchedFromTaskbar, () -> continueLaunchingApp(context, packageName, componentName, userId,
+ windowSize, launchedFromTaskbar, openInNewWindow, shortcut));
+ }
+
+ public static void launchApp(Context context, Runnable runnable) {
+ launchApp(context, true, runnable);
+ }
+
+ private static void launchApp(Context context, boolean launchedFromTaskbar, Runnable runnable) {
SharedPreferences pref = getSharedPreferences(context);
- boolean openInFullscreen = pref.getBoolean("open_in_fullscreen", true);
- boolean freeformHackActive = openInNewWindow
- ? FreeformHackHelper.getInstance().isInFreeformWorkspace()
- : (openInFullscreen
- ? FreeformHackHelper.getInstance().isInFreeformWorkspace()
- : FreeformHackHelper.getInstance().isFreeformHackActive());
+ FreeformHackHelper helper = FreeformHackHelper.getInstance();
+
+ boolean specialLaunch = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
+ && FreeformHackHelper.getInstance().isInFreeformWorkspace()
+ && MenuHelper.getInstance().isContextMenuOpen();
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
&& pref.getBoolean("freeform_hack", false)
- && !freeformHackActive) {
- shouldDelay = true;
-
- new Handler().postDelayed(new Runnable() {
- @Override
- public void run() {
- startFreeformHack(context, launchedFromTaskbar);
-
- new Handler().postDelayed(new Runnable() {
- @Override
- public void run() {
- continueLaunchingApp(context, packageName, componentName, userId,
- windowSize, launchedFromTaskbar, padStatusBar, openInNewWindow);
- }
- }, 100);
- }
- }, launchedFromTaskbar ? 0 : 100);
- }
+ && (!helper.isInFreeformWorkspace() || specialLaunch)) {
+ new Handler().postDelayed(() -> {
+ startFreeformHack(context, true, launchedFromTaskbar);
- if(!FreeformHackHelper.getInstance().isFreeformHackActive()) {
- if(!shouldDelay)
- continueLaunchingApp(context, packageName, componentName, userId,
- windowSize, launchedFromTaskbar, padStatusBar, openInNewWindow);
- } else if(FreeformHackHelper.getInstance().isInFreeformWorkspace() || !openInFullscreen)
- continueLaunchingApp(context, packageName, componentName, userId,
- windowSize, launchedFromTaskbar, padStatusBar, openInNewWindow);
+ new Handler().postDelayed(runnable, helper.isFreeformHackActive() ? 0 : 100);
+ }, launchedFromTaskbar ? 0 : 100);
+ } else
+ runnable.run();
}
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.N)
- public static void startFreeformHack(Context context, boolean launchedFromTaskbar) {
+ public static void startFreeformHack(Context context, boolean checkMultiWindow, boolean launchedFromTaskbar) {
Intent freeformHackIntent = new Intent(context, InvisibleActivityFreeform.class);
- freeformHackIntent.putExtra("check_multiwindow", true);
freeformHackIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
+ if(checkMultiWindow)
+ freeformHackIntent.putExtra("check_multiwindow", true);
+
if(launchedFromTaskbar) {
SharedPreferences pref = getSharedPreferences(context);
if(pref.getBoolean("disable_animations", false))
freeformHackIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
}
- DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
- Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
- try {
- context.startActivity(freeformHackIntent, ActivityOptions.makeBasic().setLaunchBounds(new Rect(
- display.getWidth(),
- display.getHeight(),
- display.getWidth() + 1,
- display.getHeight() + 1
- )).toBundle());
- } catch (IllegalArgumentException e) { /* Gracefully fail */ }
+ if(canDrawOverlays(context))
+ launchAppLowerRight(context, freeformHackIntent);
}
@TargetApi(Build.VERSION_CODES.N)
long userId,
String windowSize,
boolean launchedFromTaskbar,
- boolean padStatusBar,
- boolean openInNewWindow) {
+ boolean openInNewWindow,
+ ShortcutInfo shortcut) {
SharedPreferences pref = getSharedPreferences(context);
Intent intent = new Intent();
intent.setComponent(ComponentName.unflattenFromString(componentName));
+ intent.setAction(Intent.ACTION_MAIN);
+ intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
+ if(FreeformHackHelper.getInstance().isInFreeformWorkspace()
+ && Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1)
+ intent.addFlags(Intent.FLAG_ACTIVITY_TASK_ON_HOME);
+
if(launchedFromTaskbar) {
if(pref.getBoolean("disable_animations", false))
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
}
- if(openInNewWindow) {
+ if(openInNewWindow || pref.getBoolean("force_new_window", false)) {
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
ActivityInfo activityInfo = intent.resolveActivityInfo(context.getPackageManager(), 0);
}
}
- if(windowSize == null) {
- if(pref.getBoolean("save_window_sizes", true))
- windowSize = SavedWindowSizes.getInstance(context).getWindowSize(context, packageName);
- else
- windowSize = pref.getString("window_size", "standard");
- }
+ ApplicationType type = getApplicationType(context, packageName);
- if(Build.VERSION.SDK_INT < Build.VERSION_CODES.N || !pref.getBoolean("freeform_hack", false)) {
- UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
- try {
- context.startActivity(intent, null);
- } catch (ActivityNotFoundException e) {
- launchAndroidForWork(context, intent.getComponent(), null, userId);
- } catch (IllegalArgumentException e) { /* Gracefully fail */ }
- } else
- launchAndroidForWork(context, intent.getComponent(), null, userId);
+ if(windowSize == null)
+ windowSize = SavedWindowSizes.getInstance(context).getWindowSize(context, packageName);
+
+ if(Build.VERSION.SDK_INT < Build.VERSION_CODES.N
+ || !pref.getBoolean("freeform_hack", false)
+ || windowSize.equals("standard")) {
+ launchStandard(context, intent, userId, shortcut, type);
} else switch(windowSize) {
- case "standard":
- if(FreeformHackHelper.getInstance().isInFreeformWorkspace()) {
- UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
- try {
- context.startActivity(intent);
- } catch (ActivityNotFoundException e) {
- launchAndroidForWork(context, intent.getComponent(), null, userId);
- } catch (IllegalArgumentException e) { /* Gracefully fail */ }
- } else
- launchAndroidForWork(context, intent.getComponent(), null, userId);
- } else
- launchMode1(context, intent, 1, userId);
- break;
case "large":
- launchMode1(context, intent, 2, userId);
+ launchMode1(context, intent, userId, shortcut, type);
break;
case "fullscreen":
- launchMode2(context, intent, padStatusBar, FULLSCREEN, userId);
+ launchMode2(context, intent, MAXIMIZED, userId, shortcut, type);
break;
case "half_left":
- launchMode2(context, intent, padStatusBar, LEFT, userId);
+ launchMode2(context, intent, LEFT, userId, shortcut, type);
break;
case "half_right":
- launchMode2(context, intent, padStatusBar, RIGHT, userId);
+ launchMode2(context, intent, RIGHT, userId, shortcut, type);
break;
case "phone_size":
- launchMode3(context, intent, userId);
+ launchMode3(context, intent, userId, shortcut, type);
break;
}
LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.HIDE_START_MENU"));
}
+ private static void launchStandard(Context context, Intent intent, long userId, ShortcutInfo shortcut, ApplicationType type) {
+ Bundle bundle = Build.VERSION.SDK_INT < Build.VERSION_CODES.N ? null : getActivityOptions(type).toBundle();
+ if(shortcut == null) {
+ UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
+ try {
+ context.startActivity(intent, bundle);
+ } catch (ActivityNotFoundException e) {
+ launchAndroidForWork(context, intent.getComponent(), bundle, userId);
+ } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ }
+ } else
+ launchAndroidForWork(context, intent.getComponent(), bundle, userId);
+ } else
+ launchShortcut(context, shortcut, bundle);
+ }
+
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.N)
- private static void launchMode1(Context context, Intent intent, int factor, long userId) {
- DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
- Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
+ private static void launchMode1(Context context, Intent intent, long userId, ShortcutInfo shortcut, ApplicationType type) {
+ DisplayMetrics metrics = getRealDisplayMetrics(context);
- int width1 = display.getWidth() / (4 * factor);
- int width2 = display.getWidth() - width1;
- int height1 = display.getHeight() / (4 * factor);
- int height2 = display.getHeight() - height1;
+ int width1 = metrics.widthPixels / 8;
+ int width2 = metrics.widthPixels - width1;
+ int height1 = metrics.heightPixels / 8;
+ int height2 = metrics.heightPixels - height1;
- Bundle bundle = ActivityOptions.makeBasic().setLaunchBounds(new Rect(
+ Bundle bundle = getActivityOptions(type).setLaunchBounds(new Rect(
width1,
height1,
width2,
height2
)).toBundle();
- UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
- try {
- context.startActivity(intent, bundle);
- } catch (ActivityNotFoundException e) {
+ if(shortcut == null) {
+ UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
+ try {
+ context.startActivity(intent, bundle);
+ } catch (ActivityNotFoundException e) {
+ launchAndroidForWork(context, intent.getComponent(), bundle, userId);
+ } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ }
+ } else
launchAndroidForWork(context, intent.getComponent(), bundle, userId);
- } catch (IllegalArgumentException e) { /* Gracefully fail */ }
} else
- launchAndroidForWork(context, intent.getComponent(), bundle, userId);
+ launchShortcut(context, shortcut, bundle);
}
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.N)
- private static void launchMode2(Context context, Intent intent, boolean padStatusBar, int launchType, long userId) {
- DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
- Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
-
+ private static void launchMode2(Context context, Intent intent, int launchType, long userId, ShortcutInfo shortcut, ApplicationType type) {
+ DisplayMetrics metrics = getRealDisplayMetrics(context);
+
int statusBarHeight = getStatusBarHeight(context);
-
String position = getTaskbarPosition(context);
- boolean overridePad = position.equals("top_left") || position.equals("top_right");
boolean isPortrait = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
boolean isLandscape = context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
int left = launchType == RIGHT && isLandscape
- ? display.getWidth() / 2
+ ? metrics.widthPixels / 2
: 0;
- int top;
- if(launchType == RIGHT && isPortrait) {
- top = (display.getHeight() / 2)
- + (!padStatusBar && overridePad ? statusBarHeight / 2 : 0)
- + (!padStatusBar && !overridePad ? statusBarHeight / 2 : 0);
- } else {
- top = padStatusBar || overridePad ? statusBarHeight : 0;
- }
+ int top = launchType == RIGHT && isPortrait
+ ? metrics.heightPixels / 2
+ : statusBarHeight;
int right = launchType == LEFT && isLandscape
- ? display.getWidth() / 2
- : display.getWidth();
-
- int bottom;
- if(launchType == LEFT && isPortrait) {
- bottom = display.getHeight() / 2
- + (!padStatusBar && overridePad ? statusBarHeight / 2 : 0)
- - (!padStatusBar && !overridePad ? statusBarHeight / 2 : 0);
- } else {
- bottom = display.getHeight()
- + ((!padStatusBar && overridePad) || (!padStatusBar && launchType == RIGHT && isPortrait)
- ? statusBarHeight
- : 0);
- }
+ ? metrics.widthPixels / 2
+ : metrics.widthPixels;
+
+ int bottom = launchType == LEFT && isPortrait
+ ? metrics.heightPixels / 2
+ : metrics.heightPixels;
int iconSize = context.getResources().getDimensionPixelSize(R.dimen.icon_size);
} else if(isLandscape || (launchType != RIGHT && isPortrait))
top = top + iconSize;
- Bundle bundle = ActivityOptions.makeBasic().setLaunchBounds(new Rect(
+ Bundle bundle = getActivityOptions(type).setLaunchBounds(new Rect(
left,
top,
right,
bottom
)).toBundle();
- UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
- try {
- context.startActivity(intent, bundle);
- } catch (ActivityNotFoundException e) {
+ if(shortcut == null) {
+ UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
+ try {
+ context.startActivity(intent, bundle);
+ } catch (ActivityNotFoundException e) {
+ launchAndroidForWork(context, intent.getComponent(), bundle, userId);
+ } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ }
+ } else
launchAndroidForWork(context, intent.getComponent(), bundle, userId);
- } catch (IllegalArgumentException e) { /* Gracefully fail */ }
} else
- launchAndroidForWork(context, intent.getComponent(), bundle, userId);
+ launchShortcut(context, shortcut, bundle);
}
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.N)
- private static void launchMode3(Context context, Intent intent, long userId) {
- DisplayManager dm = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
- Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
+ private static void launchMode3(Context context, Intent intent, long userId, ShortcutInfo shortcut, ApplicationType type) {
+ DisplayMetrics metrics = getRealDisplayMetrics(context);
- int width1 = display.getWidth() / 2;
+ int width1 = metrics.widthPixels / 2;
int width2 = context.getResources().getDimensionPixelSize(R.dimen.phone_size_width) / 2;
- int height1 = display.getHeight() / 2;
+ int height1 = metrics.heightPixels / 2;
int height2 = context.getResources().getDimensionPixelSize(R.dimen.phone_size_height) / 2;
- Bundle bundle = ActivityOptions.makeBasic().setLaunchBounds(new Rect(
+ Bundle bundle = getActivityOptions(type).setLaunchBounds(new Rect(
width1 - width2,
height1 - height2,
width1 + width2,
height1 + height2
)).toBundle();
- UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
- try {
- context.startActivity(intent, bundle);
- } catch (ActivityNotFoundException e) {
+ if(shortcut == null) {
+ UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ if(userId == userManager.getSerialNumberForUser(Process.myUserHandle())) {
+ try {
+ context.startActivity(intent, bundle);
+ } catch (ActivityNotFoundException e) {
+ launchAndroidForWork(context, intent.getComponent(), bundle, userId);
+ } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ }
+ } else
launchAndroidForWork(context, intent.getComponent(), bundle, userId);
- } catch (IllegalArgumentException e) { /* Gracefully fail */ }
} else
- launchAndroidForWork(context, intent.getComponent(), bundle, userId);
+ launchShortcut(context, shortcut, bundle);
}
private static void launchAndroidForWork(Context context, ComponentName componentName, Bundle bundle, long userId) {
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
- launcherApps.startMainActivity(componentName, userManager.getUserForSerialNumber(userId), null, bundle);
+ try {
+ launcherApps.startMainActivity(componentName, userManager.getUserForSerialNumber(userId), null, bundle);
+ } catch (ActivityNotFoundException | NullPointerException e) { /* Gracefully fail */ }
}
- public static void checkForUpdates(Context context) {
- String url;
- try {
- context.getPackageManager().getPackageInfo("com.android.vending", 0);
- url = "https://play.google.com/store/apps/details?id=" + BuildConfig.APPLICATION_ID;
- } catch (PackageManager.NameNotFoundException e) {
- url = "https://f-droid.org/repository/browse/?fdid=" + BuildConfig.BASE_APPLICATION_ID;
+ @TargetApi(Build.VERSION_CODES.N_MR1)
+ private static void launchShortcut(Context context, ShortcutInfo shortcut, Bundle bundle) {
+ LauncherApps launcherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
+
+ if(launcherApps.hasShortcutHostPermission()) {
+ try {
+ launcherApps.startShortcut(shortcut, null, bundle);
+ } catch (ActivityNotFoundException | NullPointerException e) { /* Gracefully fail */ }
}
+ }
- Intent intent = new Intent(Intent.ACTION_VIEW);
- intent.setData(Uri.parse(url));
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ public static void launchAppMaximized(Context context, Intent intent) {
+ UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+ long userId = userManager.getSerialNumberForUser(Process.myUserHandle());
+ launchMode2(context, intent, MAXIMIZED, userId, null, ApplicationType.CONTEXT_MENU);
+ }
+
+ @SuppressWarnings("deprecation")
+ @TargetApi(Build.VERSION_CODES.N)
+ public static void launchAppLowerRight(Context context, Intent intent) {
+ DisplayMetrics metrics = getRealDisplayMetrics(context);
try {
- context.startActivity(intent);
- } catch (ActivityNotFoundException e) { /* Gracefully fail */ }
+ context.startActivity(intent, getActivityOptions(ApplicationType.FREEFORM_HACK).setLaunchBounds(new Rect(
+ metrics.widthPixels,
+ metrics.heightPixels,
+ metrics.widthPixels + 1,
+ metrics.heightPixels + 1
+ )).toBundle());
+ } catch (IllegalArgumentException | SecurityException e) { /* Gracefully fail */ }
+ }
+
+ public static void checkForUpdates(Context context) {
+ if(!BuildConfig.APPLICATION_ID.equals(BuildConfig.ANDROIDX86_APPLICATION_ID)) {
+ if(!BuildConfig.DEBUG) {
+ String url;
+ try {
+ context.getPackageManager().getPackageInfo("com.android.vending", 0);
+ url = "https://play.google.com/store/apps/details?id=" + BuildConfig.APPLICATION_ID;
+ } catch (PackageManager.NameNotFoundException e) {
+ url = "https://f-droid.org/repository/browse/?fdid=" + BuildConfig.BASE_APPLICATION_ID;
+ }
+
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setData(Uri.parse(url));
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ try {
+ context.startActivity(intent);
+ } catch (ActivityNotFoundException e) { /* Gracefully fail */ }
+ } else
+ showToast(context, R.string.debug_build);
+ }
}
public static boolean launcherIsDefault(Context context) {
return position;
}
- public static int getMaxNumOfColumns(Context context) {
- // The base Taskbar size without any recent apps added.
- // Someday this might be automatically calculated, but today is not that day.
- float baseTaskbarSize = 92;
+ private static int getMaxNumOfColumns(Context context) {
+ SharedPreferences pref = getSharedPreferences(context);
+ DisplayMetrics metrics = getRealDisplayMetrics(context);
+ float baseTaskbarSize = getBaseTaskbarSizeFloat(context) / metrics.density;
int numOfColumns = 0;
- DisplayMetrics metrics = context.getResources().getDisplayMetrics();
float maxScreenSize = getTaskbarPosition(context).contains("vertical")
? (metrics.heightPixels - getStatusBarHeight(context)) / metrics.density
: metrics.widthPixels / metrics.density;
float iconSize = context.getResources().getDimension(R.dimen.icon_size) / metrics.density;
- SharedPreferences pref = getSharedPreferences(context);
int userMaxNumOfColumns = Integer.valueOf(pref.getString("max_num_of_recents", "10"));
while(baseTaskbarSize + iconSize < maxScreenSize
for(UserHandle handle : userHandles) {
List<LauncherActivityInfo> list = launcherApps.getActivityList(entry.getPackageName(), handle);
if(!list.isEmpty()) {
- appInfo = list.get(0);
+ // Google App workaround
+ if(!entry.getPackageName().equals("com.google.android.googlequicksearchbox"))
+ appInfo = list.get(0);
+ else {
+ boolean added = false;
+ for(LauncherActivityInfo info : list) {
+ if(info.getName().equals("com.google.android.googlequicksearchbox.SearchActivity")) {
+ appInfo = info;
+ added = true;
+ }
+ }
+
+ if(!added) appInfo = list.get(0);
+ }
+
break;
}
}
return intent;
}
+ public static Intent getStartStopIntent(Context context) {
+ Intent shortcutIntent = new Intent(context, StartTaskbarActivity.class);
+ shortcutIntent.setAction(Intent.ACTION_MAIN);
+ shortcutIntent.putExtra("is_launching_shortcut", true);
+
+ BitmapDrawable drawable = (BitmapDrawable) context.getDrawable(R.mipmap.ic_launcher);
+
+ Intent intent = new Intent();
+ intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
+ if(drawable != null) intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, drawable.getBitmap());
+ intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, context.getString(R.string.start_taskbar));
+
+ return intent;
+ }
+
public static boolean hasFreeformSupport(Context context) {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N
&& (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT)
|| Settings.Global.getInt(context.getContentResolver(), "enable_freeform_support", -1) == 1
- || Settings.Global.getInt(context.getContentResolver(), "force_resizable_activities", -1) == 1);
+ || (Build.VERSION.SDK_INT <= Build.VERSION_CODES.N_MR1
+ && Settings.Global.getInt(context.getContentResolver(), "force_resizable_activities", -1) == 1));
+ }
+
+ public static boolean hasPartialFreeformSupport() {
+ return Build.MANUFACTURER.equalsIgnoreCase("Samsung");
+ }
+
+ public static boolean isServiceRunning(Context context, Class<? extends Service> cls) {
+ return isServiceRunning(context, cls.getName());
+ }
+
+ public static boolean isServiceRunning(Context context, String className) {
+ ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+ for(ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
+ if(className.equals(service.service.getClassName()))
+ return true;
+ }
+
+ return false;
+ }
+
+ public static int getBackgroundTint(Context context) {
+ SharedPreferences pref = getSharedPreferences(context);
+
+ // Import old background tint preference
+ if(pref.contains("show_background")) {
+ SharedPreferences.Editor editor = pref.edit();
+
+ if(!pref.getBoolean("show_background", true))
+ editor.putInt("background_tint", Color.TRANSPARENT).apply();
+
+ editor.remove("show_background");
+ editor.apply();
+ }
+
+ return pref.getInt("background_tint", context.getResources().getInteger(R.integer.translucent_gray));
+ }
+
+ public static int getAccentColor(Context context) {
+ SharedPreferences pref = getSharedPreferences(context);
+ return pref.getInt("accent_color", context.getResources().getInteger(R.integer.translucent_white));
+ }
+
+ @TargetApi(Build.VERSION_CODES.M)
+ public static boolean canDrawOverlays(Context context) {
+ return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || Settings.canDrawOverlays(context);
+ }
+
+ public static boolean isGame(Context context, String packageName) {
+ SharedPreferences pref = getSharedPreferences(context);
+ if(pref.getBoolean("launch_games_fullscreen", true)) {
+ PackageManager pm = context.getPackageManager();
+
+ try {
+ ApplicationInfo info = pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA);
+ return (info.flags & ApplicationInfo.FLAG_IS_GAME) != 0 || (info.metaData != null && info.metaData.getBoolean("isGame", false));
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ } else
+ return false;
+ }
+
+ @TargetApi(Build.VERSION_CODES.M)
+ public static ActivityOptions getActivityOptions(ApplicationType applicationType) {
+ ActivityOptions options = ActivityOptions.makeBasic();
+ Integer stackId = null;
+
+ switch(applicationType) {
+ case APPLICATION:
+ if(!FreeformHackHelper.getInstance().isFreeformHackActive())
+ stackId = FULLSCREEN_WORKSPACE_STACK_ID;
+ break;
+ case GAME:
+ stackId = FULLSCREEN_WORKSPACE_STACK_ID;
+ break;
+ case FREEFORM_HACK:
+ stackId = FREEFORM_WORKSPACE_STACK_ID;
+ break;
+ case CONTEXT_MENU:
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
+ stackId = FULLSCREEN_WORKSPACE_STACK_ID;
+ }
+
+ if(stackId != null) {
+ try {
+ Method method = ActivityOptions.class.getMethod("setLaunchStackId", int.class);
+ method.invoke(options, stackId);
+ } catch (Exception e) { /* Gracefully fail */ }
+ }
+
+ return options;
+ }
+
+ private static ApplicationType getApplicationType(Context context, String packageName) {
+ return isGame(context, packageName) ? ApplicationType.GAME : ApplicationType.APPLICATION;
+ }
+
+ public static boolean isSystemApp(Context context) {
+ try {
+ ApplicationInfo info = context.getPackageManager().getApplicationInfo(BuildConfig.APPLICATION_ID, 0);
+ int mask = ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
+ return (info.flags & mask) != 0;
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ public static boolean isChromeOs(Context context) {
+ return context.getPackageManager().hasSystemFeature("org.chromium.arc");
+ }
+
+ public static boolean hasSupportLibrary(Context context) {
+ PackageManager pm = context.getPackageManager();
+ try {
+ pm.getPackageInfo(BuildConfig.SUPPORT_APPLICATION_ID, 0);
+ return pm.checkSignatures(BuildConfig.SUPPORT_APPLICATION_ID, BuildConfig.APPLICATION_ID) == PackageManager.SIGNATURE_MATCH
+ && BuildConfig.APPLICATION_ID.equals(BuildConfig.BASE_APPLICATION_ID)
+ && isSystemApp(context);
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ public static int getBaseTaskbarSize(Context context) {
+ return Math.round(getBaseTaskbarSizeFloat(context));
+ }
+
+ private static float getBaseTaskbarSizeFloat(Context context) {
+ SharedPreferences pref = getSharedPreferences(context);
+ float baseTaskbarSize = context.getResources().getDimension(R.dimen.base_taskbar_size);
+ boolean navbarButtonsEnabled = false;
+
+ if(pref.getBoolean("dashboard", false))
+ baseTaskbarSize += context.getResources().getDimension(R.dimen.dashboard_button_size);
+
+ if(pref.getBoolean("button_back", false)) {
+ navbarButtonsEnabled = true;
+ baseTaskbarSize += context.getResources().getDimension(R.dimen.icon_size);
+ }
+
+ if(pref.getBoolean("button_home", false)) {
+ navbarButtonsEnabled = true;
+ baseTaskbarSize += context.getResources().getDimension(R.dimen.icon_size);
+ }
+
+ if(pref.getBoolean("button_recents", false)) {
+ navbarButtonsEnabled = true;
+ baseTaskbarSize += context.getResources().getDimension(R.dimen.icon_size);
+ }
+
+ if(navbarButtonsEnabled)
+ baseTaskbarSize += context.getResources().getDimension(R.dimen.navbar_buttons_margin);
+
+ return baseTaskbarSize;
+ }
+
+ private static void startTaskbarService(Context context, boolean fullRestart) {
+ context.startService(new Intent(context, TaskbarService.class));
+ context.startService(new Intent(context, StartMenuService.class));
+ context.startService(new Intent(context, DashboardService.class));
+ if(fullRestart) context.startService(new Intent(context, NotificationService.class));
+ }
+
+ private static void stopTaskbarService(Context context, boolean fullRestart) {
+ context.stopService(new Intent(context, TaskbarService.class));
+ context.stopService(new Intent(context, StartMenuService.class));
+ context.stopService(new Intent(context, DashboardService.class));
+ if(fullRestart) context.stopService(new Intent(context, NotificationService.class));
+ }
+
+ public static void restartTaskbar(Context context) {
+ SharedPreferences pref = getSharedPreferences(context);
+ if(pref.getBoolean("taskbar_active", false) && !pref.getBoolean("is_hidden", false)) {
+ pref.edit()
+ .putBoolean("is_restarting", true)
+ .putBoolean("skip_auto_hide_navbar", true)
+ .apply();
+
+ stopTaskbarService(context, true);
+ startTaskbarService(context, true);
+ } else if(isServiceRunning(context, StartMenuService.class)) {
+ pref.edit().putBoolean("skip_auto_hide_navbar", true).apply();
+
+ stopTaskbarService(context, false);
+ startTaskbarService(context, false);
+ }
+ }
+
+ public static void restartNotificationService(Context context) {
+ if(isServiceRunning(context, NotificationService.class)) {
+ SharedPreferences pref = getSharedPreferences(context);
+ pref.edit().putBoolean("is_restarting", true).apply();
+
+ Intent intent = new Intent(context, NotificationService.class);
+ context.stopService(intent);
+ context.startService(intent);
+ }
+ }
+
+ public static void showHideNavigationBar(Context context, boolean show) {
+ // Show or hide the system navigation bar on Bliss-x86
+ try {
+ Settings.System.putInt(context.getContentResolver(), "navigation_bar_show", show ? 1 : 0);
+ } catch (Exception e) { /* Gracefully fail */ }
+ }
+
+ public static void initPrefs(Context context) {
+ // On smaller-screened devices, set "Grid" as the default start menu layout
+ SharedPreferences pref = getSharedPreferences(context);
+ if(context.getApplicationContext().getResources().getConfiguration().smallestScreenWidthDp < 600
+ && pref.getString("start_menu_layout", "null").equals("null")) {
+ pref.edit().putString("start_menu_layout", "grid").apply();
+ }
+
+ // Enable freeform hack automatically on supported devices
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ if(!pref.getBoolean("freeform_hack_override", false)) {
+ pref.edit()
+ .putBoolean("freeform_hack", hasFreeformSupport(context) && !hasPartialFreeformSupport())
+ .putBoolean("save_window_sizes", false)
+ .putBoolean("freeform_hack_override", true)
+ .apply();
+ } else if(!hasFreeformSupport(context)) {
+ pref.edit().putBoolean("freeform_hack", false).apply();
+
+ LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent("com.farmerbb.taskbar.FINISH_FREEFORM_ACTIVITY"));
+ }
+ }
+
+ // Customizations for Android-x86 devices (non-Bliss)
+ if(BuildConfig.APPLICATION_ID.equals(BuildConfig.ANDROIDX86_APPLICATION_ID)
+ && isSystemApp(context)
+ && !pref.getBoolean("android_x86_prefs", false)) {
+ pref.edit()
+ .putString("recents_amount", "running_apps_only")
+ .putString("refresh_frequency", "0")
+ .putString("max_num_of_recents", "2147483647")
+ .putBoolean("full_length", true)
+ .putBoolean("dashboard", true)
+ .putBoolean("android_x86_prefs", true)
+ .apply();
+ }
+ }
+
+ public static DisplayMetrics getRealDisplayMetrics(Context context) {
+ DisplayMetrics metrics = new DisplayMetrics();
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ Display disp = wm.getDefaultDisplay();
+
+ SharedPreferences pref = getSharedPreferences(context);
+ if(isChromeOs(context) && !pref.getBoolean("chrome_os_context_menu_fix", false))
+ disp.getRealMetrics(metrics);
+ else
+ disp.getMetrics(metrics);
+
+ return metrics;
+ }
+
+ public static int getOverlayType() {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
+ ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
+ : WindowManager.LayoutParams.TYPE_PHONE;
}
}