Настройка "Защищенных приложений" на телефонах Huawei и как с ней справиться
У меня Huawei P8 с Android 5.0, который я использую для тестирования приложения. Приложение должно работать в фоновом режиме, так как оно отслеживает регионы BLE.
Я обнаружил, что в Huawei встроена "функция" под названием "Защищенные приложения", доступ к которой можно получить из настроек телефона (Battery Manager > Protected Apps). Это позволяет избранным приложениям продолжать работу после выключения экрана.
Целесообразно для Huawei, но, к сожалению для меня, похоже, что он включен, т. Е. Приложения по умолчанию отключены, и их нужно вручную вводить. Это не демонстрация, так как я могу посоветовать пользователям в FAQ или распечатать документация об исправлении, но я недавно установил Tinder (для исследовательских целей!) и заметил, что он был внесен в защищенный список автоматически.
Кто-нибудь знает, как я могу сделать это для моего приложения? Это настройка в манифесте? Это что-то, что Huawei включило в Tinder, потому что это популярное приложение?
7 ответов
if("huawei".equalsIgnoreCase(android.os.Build.MANUFACTURER) && !sp.getBoolean("protected",false)) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.huawei_headline).setMessage(R.string.huawei_text)
.setPositiveButton(R.string.go_to_protected, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity"));
startActivity(intent);
sp.edit().putBoolean("protected",true).commit();
}
}).create().show();
}
В манифесте нет настройки, и Huawei включил Tinder, потому что это популярное приложение. Нет способа узнать, защищены ли приложения.
В любом случае, я использовал ifHuaweiAlert() в onCreate, чтобы показать AlertDialog:
private void ifHuaweiAlert() {
final SharedPreferences settings = getSharedPreferences("ProtectedApps", MODE_PRIVATE);
final String saveIfSkip = "skipProtectedAppsMessage";
boolean skipMessage = settings.getBoolean(saveIfSkip, false);
if (!skipMessage) {
final SharedPreferences.Editor editor = settings.edit();
Intent intent = new Intent();
intent.setClassName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity");
if (isCallable(intent)) {
final AppCompatCheckBox dontShowAgain = new AppCompatCheckBox(this);
dontShowAgain.setText("Do not show again");
dontShowAgain.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
editor.putBoolean(saveIfSkip, isChecked);
editor.apply();
}
});
new AlertDialog.Builder(this)
.setIcon(android.R.drawable.ic_dialog_alert)
.setTitle("Huawei Protected Apps")
.setMessage(String.format("%s requires to be enabled in 'Protected Apps' to function properly.%n", getString(R.string.app_name)))
.setView(dontShowAgain)
.setPositiveButton("Protected Apps", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
huaweiProtectedApps();
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
} else {
editor.putBoolean(saveIfSkip, true);
editor.apply();
}
}
}
private boolean isCallable(Intent intent) {
List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}
private void huaweiProtectedApps() {
try {
String cmd = "am start -n com.huawei.systemmanager/.optimize.process.ProtectActivity";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
cmd += " --user " + getUserSerial();
}
Runtime.getRuntime().exec(cmd);
} catch (IOException ignored) {
}
}
private String getUserSerial() {
//noinspection ResourceType
Object userManager = getSystemService("user");
if (null == userManager) return "";
try {
Method myUserHandleMethod = android.os.Process.class.getMethod("myUserHandle", (Class<?>[]) null);
Object myUserHandle = myUserHandleMethod.invoke(android.os.Process.class, (Object[]) null);
Method getSerialNumberForUser = userManager.getClass().getMethod("getSerialNumberForUser", myUserHandle.getClass());
Long userSerial = (Long) getSerialNumberForUser.invoke(userManager, myUserHandle);
if (userSerial != null) {
return String.valueOf(userSerial);
} else {
return "";
}
} catch (NoSuchMethodException | IllegalArgumentException | InvocationTargetException | IllegalAccessException ignored) {
}
return "";
}
+1 за Pierre за его отличное решение, которое работает для нескольких производителей устройств (Huawei, asus, oppo ...).
Я хотел использовать его код в своем приложении для Android на Java. Я вдохновил свой код из ответов Pierre и Aiuspaktyn.
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Build;
import android.support.v7.widget.AppCompatCheckBox;
import android.widget.CompoundButton;
import java.util.List;
public class Utils {
public static void startPowerSaverIntent(Context context) {
SharedPreferences settings = context.getSharedPreferences("ProtectedApps", Context.MODE_PRIVATE);
boolean skipMessage = settings.getBoolean("skipProtectedAppCheck", false);
if (!skipMessage) {
final SharedPreferences.Editor editor = settings.edit();
boolean foundCorrectIntent = false;
for (Intent intent : Constants.POWERMANAGER_INTENTS) {
if (isCallable(context, intent)) {
foundCorrectIntent = true;
final AppCompatCheckBox dontShowAgain = new AppCompatCheckBox(context);
dontShowAgain.setText("Do not show again");
dontShowAgain.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
editor.putBoolean("skipProtectedAppCheck", isChecked);
editor.apply();
}
});
new AlertDialog.Builder(context)
.setTitle(Build.MANUFACTURER + " Protected Apps")
.setMessage(String.format("%s requires to be enabled in 'Protected Apps' to function properly.%n", context.getString(R.string.app_name)))
.setView(dontShowAgain)
.setPositiveButton("Go to settings", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
context.startActivity(intent);
}
})
.setNegativeButton(android.R.string.cancel, null)
.show();
break;
}
}
if (!foundCorrectIntent) {
editor.putBoolean("skipProtectedAppCheck", true);
editor.apply();
}
}
}
private static boolean isCallable(Context context, Intent intent) {
List<ResolveInfo> list = context.getPackageManager().queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
}
}
}
import android.content.ComponentName;
import android.content.Intent;
import java.util.Arrays;
import java.util.List;
public class Constants {
public static List<Intent> POWERMANAGER_INTENTS = Arrays.asList(
new Intent().setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity")),
new Intent().setComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity")),
new Intent().setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity")),
new Intent().setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity")),
new Intent().setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.startupapp.StartupAppListActivity")),
new Intent().setComponent(new ComponentName("com.oppo.safe", "com.oppo.safe.permission.startup.StartupAppListActivity")),
new Intent().setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity")),
new Intent().setComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.BgStartUpManager")),
new Intent().setComponent(new ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity")),
new Intent().setComponent(new ComponentName("com.asus.mobilemanager", "com.asus.mobilemanager.entry.FunctionActivity")).setData(android.net.Uri.parse("mobilemanager://function/entry/AutoStart"))
);
}
}
Я надеюсь, что это помогает кому-то.
+1 Aiuspaktyn для решения Java
Ксамарин раствор
Использование:
MainActivity =>
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
MyUtils.IfHuaweiAlert(this);
}
public static void IfHuaweiAlert(Context context)
{
ISharedPreferences settings = context.GetSharedPreferences("ProtectedApps", FileCreationMode.Private);
string saveIfSkip = "skipProtectedAppsMessage";
bool skipMessage = settings.GetBoolean(saveIfSkip, false);
if (!skipMessage)
{
ISharedPreferencesEditor editor = settings.Edit();
Intent intent = new Intent();
intent.SetClassName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity");
if (context.PackageManager.QueryIntentActivities(intent, PackageInfoFlags.MatchDefaultOnly).Count > 0)
{
var dontShowAgain = new Android.Support.V7.Widget.AppCompatCheckBox(context);
dontShowAgain.Text = "Do not show again";
dontShowAgain.CheckedChange += (object sender, CompoundButton.CheckedChangeEventArgs e) =>
{
editor.PutBoolean(saveIfSkip, e.IsChecked);
editor.Apply();
};
new AlertDialog.Builder(context)
.SetIcon(Android.Resource.Drawable.IcDialogAlert)
.SetTitle("Huawei Protected Apps")
.SetMessage(string.Format("{0} requires to be enabled in 'Protected Apps' to function properly.\n", context.GetString(Resource.String.app_name)))
.SetView(dontShowAgain)
.SetPositiveButton("Protected Apps", (o, d) =>
{
try
{
string cmd = "am start -n com.huawei.systemmanager/.optimize.process.ProtectActivity";
if (Build.VERSION.SdkInt >= BuildVersionCodes.JellyBeanMr1)
{
try
{
UserManager um = (UserManager)context.GetSystemService(Context.UserService);
cmd += " --user " + um.GetSerialNumberForUser(Process.MyUserHandle());
}
catch { }
}
Java.Lang.Runtime.GetRuntime().Exec(cmd);
}
catch (Exception ignored)
{
}
})
.SetNegativeButton(Android.Resource.String.Cancel, (o, d) => { })
.Show();
}
else
{
editor.PutBoolean(saveIfSkip, true);
editor.Apply();
}
}
}
Я все еще хочу выяснить это для следующего ( отсюда):
private static List<Intent> POWERMANAGER_INTENTS = new List<Intent>()
{
new Intent().SetComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity")),
new Intent().SetComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity")),
new Intent().SetComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity")),
new Intent().SetComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity")),
new Intent().SetComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.startupapp.StartupAppListActivity")),
new Intent().SetComponent(new ComponentName("com.oppo.safe", "com.oppo.safe.permission.startup.StartupAppListActivity")),
new Intent().SetComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity")),
new Intent().SetComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.BgStartUpManager")),
new Intent().SetComponent(new ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity")),
new Intent().SetComponent(new ComponentName("com.asus.mobilemanager", "com.asus.mobilemanager.entry.FunctionActivity")).SetData(Android.Net.Uri.Parse("mobilemanager://function/entry/AutoStart"))
};
/*
Should this method also run the command for the listed devices?
I do not have devices to test it with.
*/
public static void StartPowerSaverIntent(Context context)
{
foreach (Intent intent in POWERMANAGER_INTENTS)
{
if (context.PackageManager.ResolveActivity(intent, PackageInfoFlags.MatchDefaultOnly) != null)
{
context.StartActivity(intent);
break;
}
}
}
Было бы неплохо просто запустить следующую команду, и все это покрыто:
MyUtils.StartPowerSaverIntent(this);
РЕДАКТИРОВАТЬ:
Это должно сделать:
public class MyUtils
{
private static List<Intent> POWERMANAGER_INTENTS = new List<Intent>()
{
new Intent().SetComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity")),
new Intent().SetComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity")),
new Intent().SetComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity")),
new Intent().SetComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity")),
new Intent().SetComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.startupapp.StartupAppListActivity")),
new Intent().SetComponent(new ComponentName("com.oppo.safe", "com.oppo.safe.permission.startup.StartupAppListActivity")),
new Intent().SetComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.AddWhiteListActivity")),
new Intent().SetComponent(new ComponentName("com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.BgStartUpManager")),
new Intent().SetComponent(new ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity")),
new Intent().SetComponent(new ComponentName("com.asus.mobilemanager", "com.asus.mobilemanager.entry.FunctionActivity")).SetData(Android.Net.Uri.Parse("mobilemanager://function/entry/AutoStart"))
};
public static void StartPowerSaverIntent(Context context)
{
ISharedPreferences settings = context.GetSharedPreferences("ProtectedApps", FileCreationMode.Private);
bool skipMessage = settings.GetBoolean("skipAppListMessage", false);
if (!skipMessage)
{
ISharedPreferencesEditor editor = settings.Edit();
foreach (Intent intent in POWERMANAGER_INTENTS)
{
if (context.PackageManager.ResolveActivity(intent, PackageInfoFlags.MatchDefaultOnly) != null)
{
var dontShowAgain = new Android.Support.V7.Widget.AppCompatCheckBox(context);
dontShowAgain.Text = "Do not show again";
dontShowAgain.CheckedChange += (object sender, CompoundButton.CheckedChangeEventArgs e) =>
{
editor.PutBoolean("skipAppListMessage", e.IsChecked);
editor.Apply();
};
new AlertDialog.Builder(context)
.SetIcon(Android.Resource.Drawable.IcDialogAlert)
.SetTitle(string.Format("Add {0} to list", context.GetString(Resource.String.app_name)))
.SetMessage(string.Format("{0} requires to be enabled/added in the list to function properly.\n", context.GetString(Resource.String.app_name)))
.SetView(dontShowAgain)
.SetPositiveButton("Go to settings", (o, d) => context.StartActivity(intent))
.SetNegativeButton(Android.Resource.String.Cancel, (o, d) => { })
.Show();
break;
}
}
}
}
}
Я собрал некоторые намерения из различных постов, чтобы проверить всех производителей:
Как запустить Power Manager всех производителей Android для включения push-уведомлений?
Вы можете использовать эту библиотеку для перехода пользователя к защищенным приложениям или автозапуска:
Если телефон поддерживает функцию автозапуска, вы можете показать пользователю подсказку, чтобы включить ваше приложение в этих приложениях.
Вы можете проверить этим методом:
AutoStartPermissionHelper.getInstance().isAutoStartPermissionAvailable(context)
А для перехода пользователя на эту страницу просто вызовите это:
AutoStartPermissionHelper.getInstance().getAutoStartPermission(context)
Я использую решение @Aiuspaktyn, в котором отсутствует часть того, как определять, когда прекращается показ диалога после того, как пользователь установил приложение как защищенное. Я использую Сервис, чтобы проверить, было ли приложение прекращено или нет, проверяя, существует ли оно.
PowerMaster -> AutoStart -> Найти приложение в заблокированном разделе и разрешить