backport to Android 7.0 and 7.1
This commit is contained in:
parent
276e53cab9
commit
cf014d7978
|
@ -5,7 +5,7 @@ android {
|
|||
buildToolsVersion '28.0.2'
|
||||
defaultConfig {
|
||||
applicationId "net.typeblog.shelter"
|
||||
minSdkVersion 26
|
||||
minSdkVersion 24
|
||||
targetSdkVersion 28
|
||||
versionCode 3
|
||||
versionName "1.0"
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:maxSdkVersion="25"
|
||||
android:name="com.android.launcher.permission.INSTALL_SHORTCUT" />
|
||||
|
||||
<application
|
||||
android:name=".ShelterApplication"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package net.typeblog.shelter.services;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
|
@ -11,6 +12,7 @@ import android.content.Intent;
|
|||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
@ -23,6 +25,7 @@ import net.typeblog.shelter.ui.DummyActivity;
|
|||
import net.typeblog.shelter.util.ApplicationInfoWrapper;
|
||||
import net.typeblog.shelter.util.Utility;
|
||||
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -217,8 +220,27 @@ public class ShelterService extends Service {
|
|||
}
|
||||
|
||||
private void setForeground() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
setForegroundOreo();
|
||||
} else {
|
||||
setForegroundLollipop();
|
||||
}
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private void setForegroundLollipop() {
|
||||
Notification notification = new Notification.Builder(this)
|
||||
.setTicker(getString(R.string.app_name))
|
||||
.setContentTitle(getString(R.string.service_title))
|
||||
.setContentText(getString(R.string.service_desc))
|
||||
.setSmallIcon(R.drawable.ic_notification_white_24dp)
|
||||
.build();
|
||||
startForeground(1, notification);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
private void setForegroundOreo() {
|
||||
// Android O and later: Notification Channel
|
||||
// TODO: Maybe backport to pre-O?
|
||||
NotificationManager nm = getSystemService(NotificationManager.class);
|
||||
if (nm.getNotificationChannel(NOTIFICATION_CHANNEL_ID) == null) {
|
||||
NotificationChannel chan = new NotificationChannel(
|
||||
|
|
|
@ -260,7 +260,7 @@ public class AppListFragment extends Fragment {
|
|||
mService.loadIcon(app, new ILoadIconCallback.Stub() {
|
||||
@Override
|
||||
public void callback(Bitmap icon) {
|
||||
addUnfreezeShortcut(app, icon);
|
||||
getActivity().runOnUiThread(() -> addUnfreezeShortcut(app, icon));
|
||||
}
|
||||
});
|
||||
} catch (RemoteException e) {
|
||||
|
|
|
@ -8,6 +8,7 @@ import android.content.ServiceConnection;
|
|||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.StrictMode;
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.content.ComponentName;
|
|||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.graphics.drawable.Icon;
|
||||
import android.os.Build;
|
||||
import android.os.IBinder;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.TabLayout;
|
||||
|
@ -315,6 +316,12 @@ public class MainActivity extends AppCompatActivity {
|
|||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
if (requestCode == REQUEST_PROVISION_PROFILE) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
// For pre-Oreo, by the time this is received, the whole process
|
||||
// should have completed.
|
||||
recreate();
|
||||
return;
|
||||
}
|
||||
// The sync part of the setup process is completed
|
||||
// Wait for the provisioning to complete
|
||||
mStorage.setBoolean(LocalStorageManager.PREF_IS_SETTING_UP, true);
|
||||
|
|
|
@ -48,7 +48,7 @@ public class LocalStorageManager {
|
|||
}
|
||||
|
||||
public void setStringList(String pref, String[] list) {
|
||||
mPrefs.edit().putString(pref, String.join(LIST_DIVIDER, list)).apply();
|
||||
mPrefs.edit().putString(pref, Utility.stringJoin(LIST_DIVIDER, list)).apply();
|
||||
}
|
||||
|
||||
public boolean stringListContains(String pref, String item) {
|
||||
|
|
|
@ -17,6 +17,7 @@ import android.graphics.drawable.Drawable;
|
|||
import android.graphics.drawable.Icon;
|
||||
import android.os.Build;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.widget.Toast;
|
||||
|
||||
import net.typeblog.shelter.R;
|
||||
|
@ -31,6 +32,21 @@ import java.util.List;
|
|||
import java.util.Optional;
|
||||
|
||||
public class Utility {
|
||||
// Polyfill for String.join
|
||||
public static String stringJoin(String delimiter, String[] list) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
return String.join(delimiter, list);
|
||||
} else {
|
||||
if (list.length == 0) return "";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < list.length - 1; i++) {
|
||||
sb.append(list[i]).append(delimiter);
|
||||
}
|
||||
sb.append(list[list.length - 1]);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
// Affiliate an Intent to another profile (i.e. the Work profile that we manage)
|
||||
// This method cares nothing about if the other profile even exists.
|
||||
// When there is no other profile, this method would just simply throw
|
||||
|
@ -109,6 +125,12 @@ public class Utility {
|
|||
manager.clearUserRestriction(adminComponent, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);
|
||||
manager.clearUserRestriction(adminComponent, UserManager.DISALLOW_UNINSTALL_APPS);
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
// Polyfill for UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES
|
||||
// Don't use this on Android Oreo and later, it will crash
|
||||
manager.setSecureSetting(adminComponent, Settings.Secure.INSTALL_NON_MARKET_APPS, "1");
|
||||
}
|
||||
|
||||
// TODO: This should be configured by the user, instead of being enforced each time Shelter starts
|
||||
// TODO: But we should also have some default restrictions that are set the first time Shelter starts
|
||||
manager.addUserRestriction(adminComponent, UserManager.ALLOW_PARENT_PROFILE_APP_LINKING);
|
||||
|
@ -177,8 +199,12 @@ public class Utility {
|
|||
Toast.makeText(context, context.getString(R.string.unsupported_launcher), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else {
|
||||
// TODO: Maybe backport for Android < O?
|
||||
throw new RuntimeException("unimplemented");
|
||||
Intent shortcutIntent = new Intent("com.android.launcher.action.INSTALL_SHORTCUT");
|
||||
shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, launchIntent);
|
||||
shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_NAME, label);
|
||||
shortcutIntent.putExtra(Intent.EXTRA_SHORTCUT_ICON, drawableToBitmap(icon.loadDrawable(context)));
|
||||
context.sendBroadcast(shortcutIntent);
|
||||
Toast.makeText(context, R.string.shortcut_create_success, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
<string name="unsupported_launcher">Cannot add shortcuts to your launcher. Please contact the developer for more information.</string>
|
||||
<string name="app_context_menu_title">Operations for %s</string>
|
||||
<string name="freeze_all_success">All apps in \"Auto Freeze\" list have been frozen successfully.</string>
|
||||
<string name="shortcut_create_success">Shortcut created on your launcher.</string>
|
||||
<string name="settings">Settings</string>
|
||||
<string name="settings_about">About</string>
|
||||
<string name="settings_version">Version</string>
|
||||
|
|
Loading…
Reference in a new issue