AppListFragment: implement unfreeze & launch shortcut
This commit is contained in:
parent
5c7e4b3b26
commit
97a46d3dab
|
@ -40,6 +40,8 @@
|
||||||
<action android:name="net.typeblog.shelter.action.TRY_START_SERVICE" />
|
<action android:name="net.typeblog.shelter.action.TRY_START_SERVICE" />
|
||||||
<action android:name="net.typeblog.shelter.action.INSTALL_PACKAGE" />
|
<action android:name="net.typeblog.shelter.action.INSTALL_PACKAGE" />
|
||||||
<action android:name="net.typeblog.shelter.action.UNINSTALL_PACKAGE" />
|
<action android:name="net.typeblog.shelter.action.UNINSTALL_PACKAGE" />
|
||||||
|
<action android:name="net.typeblog.shelter.action.UNFREEZE_AND_LAUNCH" />
|
||||||
|
<action android:name="net.typeblog.shelter.action.PUBLIC_UNFREEZE_AND_LAUNCH" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
package net.typeblog.shelter.ui;
|
package net.typeblog.shelter.ui;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.app.PendingIntent;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.content.pm.ShortcutInfo;
|
||||||
|
import android.content.pm.ShortcutManager;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.graphics.drawable.Icon;
|
||||||
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
@ -26,10 +33,13 @@ import android.widget.Toast;
|
||||||
|
|
||||||
import net.typeblog.shelter.R;
|
import net.typeblog.shelter.R;
|
||||||
import net.typeblog.shelter.services.IAppInstallCallback;
|
import net.typeblog.shelter.services.IAppInstallCallback;
|
||||||
|
import net.typeblog.shelter.services.ILoadIconCallback;
|
||||||
import net.typeblog.shelter.services.IShelterService;
|
import net.typeblog.shelter.services.IShelterService;
|
||||||
import net.typeblog.shelter.services.ShelterService;
|
import net.typeblog.shelter.services.ShelterService;
|
||||||
import net.typeblog.shelter.util.ApplicationInfoWrapper;
|
import net.typeblog.shelter.util.ApplicationInfoWrapper;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
public class AppListFragment extends Fragment {
|
public class AppListFragment extends Fragment {
|
||||||
private static final String BROADCAST_REFRESH = "net.typeblog.shelter.broadcast.REFRESH";
|
private static final String BROADCAST_REFRESH = "net.typeblog.shelter.broadcast.REFRESH";
|
||||||
|
|
||||||
|
@ -38,6 +48,8 @@ public class AppListFragment extends Fragment {
|
||||||
private static final int MENU_ITEM_UNINSTALL = 10002;
|
private static final int MENU_ITEM_UNINSTALL = 10002;
|
||||||
private static final int MENU_ITEM_FREEZE = 10003;
|
private static final int MENU_ITEM_FREEZE = 10003;
|
||||||
private static final int MENU_ITEM_UNFREEZE = 10004;
|
private static final int MENU_ITEM_UNFREEZE = 10004;
|
||||||
|
private static final int MENU_ITEM_LAUNCH = 10005;
|
||||||
|
private static final int MENU_ITEM_CREATE_UNFREEZE_SHORTCUT = 10006;
|
||||||
|
|
||||||
private IShelterService mService = null;
|
private IShelterService mService = null;
|
||||||
private boolean mIsRemote = false;
|
private boolean mIsRemote = false;
|
||||||
|
@ -143,9 +155,12 @@ public class AppListFragment extends Fragment {
|
||||||
// Freezing / Unfreezing is only available in profiles that we can control
|
// Freezing / Unfreezing is only available in profiles that we can control
|
||||||
if (mSelectedApp.isHidden()) {
|
if (mSelectedApp.isHidden()) {
|
||||||
menu.add(Menu.NONE, MENU_ITEM_UNFREEZE, Menu.NONE, R.string.unfreeze_app);
|
menu.add(Menu.NONE, MENU_ITEM_UNFREEZE, Menu.NONE, R.string.unfreeze_app);
|
||||||
|
menu.add(Menu.NONE, MENU_ITEM_LAUNCH, Menu.NONE, R.string.unfreeze_and_launch);
|
||||||
} else {
|
} else {
|
||||||
menu.add(Menu.NONE, MENU_ITEM_FREEZE, Menu.NONE, R.string.freeze_app);
|
menu.add(Menu.NONE, MENU_ITEM_FREEZE, Menu.NONE, R.string.freeze_app);
|
||||||
|
menu.add(Menu.NONE, MENU_ITEM_LAUNCH, Menu.NONE, R.string.launch);
|
||||||
}
|
}
|
||||||
|
menu.add(Menu.NONE, MENU_ITEM_CREATE_UNFREEZE_SHORTCUT, Menu.NONE, R.string.create_unfreeze_shortcut);
|
||||||
} else {
|
} else {
|
||||||
menu.add(Menu.NONE, MENU_ITEM_CLONE, Menu.NONE, R.string.clone_to_work_profile);
|
menu.add(Menu.NONE, MENU_ITEM_CLONE, Menu.NONE, R.string.clone_to_work_profile);
|
||||||
}
|
}
|
||||||
|
@ -196,6 +211,30 @@ public class AppListFragment extends Fragment {
|
||||||
getString(R.string.unfreeze_success, mSelectedApp.getLabel()), Toast.LENGTH_SHORT).show();
|
getString(R.string.unfreeze_success, mSelectedApp.getLabel()), Toast.LENGTH_SHORT).show();
|
||||||
mAdapter.refresh();
|
mAdapter.refresh();
|
||||||
return true;
|
return true;
|
||||||
|
case MENU_ITEM_LAUNCH:
|
||||||
|
// LAUNCH and UNFREEZE_AND_LAUNCH share the same ID
|
||||||
|
// because the implementation of UNFREEZE_AND_LAUNCH in DummyActivity
|
||||||
|
// will work for both
|
||||||
|
Intent intent = new Intent(DummyActivity.UNFREEZE_AND_LAUNCH);
|
||||||
|
intent.setComponent(new ComponentName(getContext(), DummyActivity.class));
|
||||||
|
intent.putExtra("packageName", mSelectedApp.getPackageName());
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
startActivity(intent);
|
||||||
|
return true;
|
||||||
|
case MENU_ITEM_CREATE_UNFREEZE_SHORTCUT:
|
||||||
|
final ApplicationInfoWrapper app = mSelectedApp;
|
||||||
|
try {
|
||||||
|
// Call the service to load the latest icon
|
||||||
|
mService.loadIcon(app, new ILoadIconCallback.Stub() {
|
||||||
|
@Override
|
||||||
|
public void callback(Bitmap icon) {
|
||||||
|
addUnfreezeShortcut(app, icon);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.onContextItemSelected(item);
|
return super.onContextItemSelected(item);
|
||||||
|
@ -236,4 +275,36 @@ public class AppListFragment extends Fragment {
|
||||||
R.string.uninstall_fail_system_app), Toast.LENGTH_SHORT).show();
|
R.string.uninstall_fail_system_app), Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addUnfreezeShortcut(ApplicationInfoWrapper app, Bitmap icon) {
|
||||||
|
// First, create an Intent to be sent when clicking on the shortcut
|
||||||
|
Intent launchIntent = new Intent(DummyActivity.PUBLIC_UNFREEZE_AND_LAUNCH);
|
||||||
|
launchIntent.setComponent(new ComponentName(getContext(), DummyActivity.class));
|
||||||
|
launchIntent.putExtra("packageName", app.getPackageName());
|
||||||
|
launchIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
|
||||||
|
// Then tell the launcher to add the shortcut
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
ShortcutManager shortcutManager = getContext().getSystemService(ShortcutManager.class);
|
||||||
|
|
||||||
|
if (shortcutManager.isRequestPinShortcutSupported()) {
|
||||||
|
ShortcutInfo info = new ShortcutInfo.Builder(getContext(), "shelter-" + app.getPackageName())
|
||||||
|
.setIntent(launchIntent)
|
||||||
|
.setIcon(Icon.createWithBitmap(icon))
|
||||||
|
.setShortLabel(app.getLabel())
|
||||||
|
.setLongLabel(app.getLabel())
|
||||||
|
.build();
|
||||||
|
Intent addIntent = shortcutManager.createShortcutResultIntent(info);
|
||||||
|
shortcutManager.requestPinShortcut(info,
|
||||||
|
PendingIntent.getBroadcast(getContext(), 0, addIntent, 0).getIntentSender());
|
||||||
|
} else {
|
||||||
|
// TODO: Maybe implement this for launchers without pin shortcut support?
|
||||||
|
// TODO: Should be the same with the fallback for Android < O
|
||||||
|
throw new RuntimeException("unimplemented");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// TODO: Maybe backport for Android < O?
|
||||||
|
throw new RuntimeException("unimplemented");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import android.widget.Toast;
|
||||||
|
|
||||||
import net.typeblog.shelter.R;
|
import net.typeblog.shelter.R;
|
||||||
import net.typeblog.shelter.ShelterApplication;
|
import net.typeblog.shelter.ShelterApplication;
|
||||||
|
import net.typeblog.shelter.receivers.ShelterDeviceAdminReceiver;
|
||||||
import net.typeblog.shelter.services.IAppInstallCallback;
|
import net.typeblog.shelter.services.IAppInstallCallback;
|
||||||
import net.typeblog.shelter.util.Utility;
|
import net.typeblog.shelter.util.Utility;
|
||||||
|
|
||||||
|
@ -32,16 +33,20 @@ public class DummyActivity extends Activity {
|
||||||
public static final String TRY_START_SERVICE = "net.typeblog.shelter.action.TRY_START_SERVICE";
|
public static final String TRY_START_SERVICE = "net.typeblog.shelter.action.TRY_START_SERVICE";
|
||||||
public static final String INSTALL_PACKAGE = "net.typeblog.shelter.action.INSTALL_PACKAGE";
|
public static final String INSTALL_PACKAGE = "net.typeblog.shelter.action.INSTALL_PACKAGE";
|
||||||
public static final String UNINSTALL_PACKAGE = "net.typeblog.shelter.action.UNINSTALL_PACKAGE";
|
public static final String UNINSTALL_PACKAGE = "net.typeblog.shelter.action.UNINSTALL_PACKAGE";
|
||||||
|
public static final String UNFREEZE_AND_LAUNCH = "net.typeblog.shelter.action.UNFREEZE_AND_LAUNCH";
|
||||||
|
public static final String PUBLIC_UNFREEZE_AND_LAUNCH = "net.typeblog.shelter.action.PUBLIC_UNFREEZE_AND_LAUNCH";
|
||||||
|
|
||||||
private static final int REQUEST_INSTALL_PACKAGE = 1;
|
private static final int REQUEST_INSTALL_PACKAGE = 1;
|
||||||
|
|
||||||
private boolean mIsProfileOwner = false;
|
private boolean mIsProfileOwner = false;
|
||||||
|
private DevicePolicyManager mPolicyManager = null;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
mIsProfileOwner = getSystemService(DevicePolicyManager.class).isProfileOwnerApp(getPackageName());
|
mPolicyManager = getSystemService(DevicePolicyManager.class);
|
||||||
|
mIsProfileOwner = mPolicyManager.isProfileOwnerApp(getPackageName());
|
||||||
if (mIsProfileOwner) {
|
if (mIsProfileOwner) {
|
||||||
// If we are the profile owner, we enforce all our policies
|
// If we are the profile owner, we enforce all our policies
|
||||||
// so that we can make sure those are updated with our app
|
// so that we can make sure those are updated with our app
|
||||||
|
@ -63,6 +68,8 @@ public class DummyActivity extends Activity {
|
||||||
actionUninstallPackage();
|
actionUninstallPackage();
|
||||||
} else if (FINALIZE_PROVISION.equals(intent.getAction())) {
|
} else if (FINALIZE_PROVISION.equals(intent.getAction())) {
|
||||||
actionFinalizeProvision();
|
actionFinalizeProvision();
|
||||||
|
} else if (UNFREEZE_AND_LAUNCH.equals(intent.getAction()) || PUBLIC_UNFREEZE_AND_LAUNCH.equals(intent.getAction())) {
|
||||||
|
actionUnfreezeAndLaunch();
|
||||||
} else {
|
} else {
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
@ -158,4 +165,36 @@ public class DummyActivity extends Activity {
|
||||||
|
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void actionUnfreezeAndLaunch() {
|
||||||
|
// Unfreeze and launch an app
|
||||||
|
// (actually this also works if the app is not frozen at all)
|
||||||
|
// For now we only support apps in Work profile,
|
||||||
|
// so we just check if we are profile owner here
|
||||||
|
if (!mIsProfileOwner) {
|
||||||
|
// Forward it to work profile
|
||||||
|
Intent intent = new Intent(UNFREEZE_AND_LAUNCH);
|
||||||
|
Utility.transferIntentToProfile(this, intent);
|
||||||
|
intent.putExtra("packageName", getIntent().getStringExtra("packageName"));
|
||||||
|
startActivity(intent);
|
||||||
|
finish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String packageName = getIntent().getStringExtra("packageName");
|
||||||
|
|
||||||
|
// Unfreeze the app first
|
||||||
|
mPolicyManager.setApplicationHidden(
|
||||||
|
new ComponentName(this, ShelterDeviceAdminReceiver.class),
|
||||||
|
packageName, false);
|
||||||
|
|
||||||
|
// Query the start intent
|
||||||
|
Intent launchIntent = getPackageManager().getLaunchIntentForPackage(packageName);
|
||||||
|
|
||||||
|
if (launchIntent != null) {
|
||||||
|
startActivity(launchIntent);
|
||||||
|
}
|
||||||
|
|
||||||
|
finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,6 +57,11 @@ public class Utility {
|
||||||
new IntentFilter(DummyActivity.TRY_START_SERVICE),
|
new IntentFilter(DummyActivity.TRY_START_SERVICE),
|
||||||
DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT);
|
DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT);
|
||||||
|
|
||||||
|
manager.addCrossProfileIntentFilter(
|
||||||
|
adminComponent,
|
||||||
|
new IntentFilter(DummyActivity.UNFREEZE_AND_LAUNCH),
|
||||||
|
DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT);
|
||||||
|
|
||||||
manager.setProfileEnabled(adminComponent);
|
manager.setProfileEnabled(adminComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,9 @@
|
||||||
<string name="uninstall_app">Uninstall</string>
|
<string name="uninstall_app">Uninstall</string>
|
||||||
<string name="freeze_app">Freeze</string>
|
<string name="freeze_app">Freeze</string>
|
||||||
<string name="unfreeze_app">Unfreeze</string>
|
<string name="unfreeze_app">Unfreeze</string>
|
||||||
|
<string name="launch">Launch</string>
|
||||||
|
<string name="create_unfreeze_shortcut">Create Unfreeze and/or Launch Shortcut</string>
|
||||||
|
<string name="unfreeze_and_launch">Unfreeze and Launch</string>
|
||||||
<string name="clone_success">Application "%s" cloned successfully</string>
|
<string name="clone_success">Application "%s" cloned successfully</string>
|
||||||
<string name="uninstall_success">Application "%s" uninstalled successfully</string>
|
<string name="uninstall_success">Application "%s" uninstalled successfully</string>
|
||||||
<string name="freeze_success">Application "%s" frozen successfully</string>
|
<string name="freeze_success">Application "%s" frozen successfully</string>
|
||||||
|
|
Loading…
Reference in a new issue