华为手机上的“受保护的应用程序”设置,以及如何处理
Posted
技术标签:
【中文标题】华为手机上的“受保护的应用程序”设置,以及如何处理【英文标题】:"Protected Apps" setting on Huawei phones, and how to handle it 【发布时间】:2015-10-16 19:20:36 【问题描述】:我有一台搭载 android 5.0 的华为 P8,用于测试应用程序。该应用程序需要在后台运行,因为它跟踪 BLE 区域。
我发现华为内置了一个名为“受保护的应用程序”的“功能”,可以从手机设置(电池管理器>受保护的应用程序)中访问。这允许选定的应用程序在屏幕关闭后继续运行。
对华为来说是明智的,但对我来说不幸的是,它看起来像是选择加入的,即默认情况下应用程序处于关闭状态,您必须手动将它们放入。 这不是什么大问题,因为我可以在常见问题解答或印刷文档中为用户提供有关修复的建议,但我最近安装了 Tinder(出于研究目的!),并注意到它被自动放入受保护的列表中。
有谁知道我可以如何为我的应用程序做到这一点?它是清单中的设置吗?是因为 Tinder 是一款受欢迎的应用,华为才为它启用的吗?
【问题讨论】:
@agamov,不,我找不到更多信息。我只是在 Play 商店的说明中添加了一行关于打开受保护应用程序的说明。 @TejasPatel,不,我停止尝试解决它,只是在描述中通知用户 【参考方案1】:清单中没有设置,华为启用了 Tinder,因为它是一个流行的应用程序。无法知道应用是否受到保护。
无论如何,我在onCreate()
中使用了ifHuaweiAlert()
来显示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 "";
【讨论】:
类名“com.huawei.systemmanager.optimize.process.ProtectActivity”是怎么找到的?我想在 Sony 上为 Stamina 模式实现类似的东西,但不知道 Stamina 的包名和 Stamina 设置中“除应用程序”屏幕的类名。 如果包名和类名是已知的,你可以很容易地打开屏幕。代码如下。意图意图 = new Intent(); intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity"));开始活动(意图); 大卫,你最好的选择是 logCat。只需移动到设置页面并保持 logCat 处于打开状态。 我可以为我的应用程序设置电源密集型吗? 华为P20正确包名:com.huawei.systemmanager.appcontrol.activity.StartupAppControlActivity【参考方案2】:我正在使用@Aiuspaktyn 解决方案,该解决方案缺少在用户将应用设置为受保护后如何检测何时停止显示对话框的部分。我正在使用服务来检查应用程序是否被终止,检查它是否存在。
【讨论】:
您能否发布您的服务示例。【参考方案3】: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();
【讨论】:
直到有办法知道应用程序是否受到保护,这是最好的事情,但为了避免每次都显示它,我有一个“不再显示”并且消息是a “如果您不保护,您可能会被收取更多费用”并且操作是“忽略,我会冒险”,或“转到设置” 华硕自动启动管理器有类似的东西吗? 是的,@Xan。只需创建组件名称如下:ComponentName("com.asus.mobilemanager","com.asus.mobilemanager.autostart.AutoStartActivity"));
你能解释一下“sp”对象是从哪里来的吗?在这里使用? sp.edit().putBoolean("protected",true).commit();
因为我知道这就是您将值更改为受保护的地方吗?
@LeonardoG。 : 很确定 "sp" 代表 SharedPreferences, final SharedPreferences sp = getSharedPreferences("ProtectedApps", Context.MODE_PRIVATE);【参考方案4】:
适用于所有设备的解决方案 (Xamarin.Android)
用法:
MainActivity =>
protected override void OnCreate(Bundle savedInstanceState)
base.OnCreate(savedInstanceState);
MyUtils.StartPowerSaverIntent(this);
public class MyUtils
private const string SKIP_INTENT_CHECK = "skipAppListMessage";
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.appcontrol.activity.StartupAppControlActivity")),
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.samsung.android.lool", "com.samsung.android.sm.ui.battery.BatteryActivity")),
new Intent().SetComponent(new ComponentName("com.htc.pitroad", "com.htc.pitroad.landingpage.activity.LandingPageActivity")),
new Intent().SetComponent(new ComponentName("com.asus.mobilemanager", "com.asus.mobilemanager.autostart.AutoStartActivity")),
new Intent().SetComponent(new ComponentName("com.asus.mobilemanager", "com.asus.mobilemanager.entry.FunctionActivity")).SetData(Android.Net.Uri.Parse("mobilemanager://function/entry/AutoStart")),
new Intent().SetComponent(new ComponentName("com.dewav.dwappmanager", "com.dewav.dwappmanager.memory.SmartClearupWhiteList"))
;
public static void StartPowerSaverIntent(Context context)
ISharedPreferences settings = context.GetSharedPreferences("ProtectedApps", FileCreationMode.Private);
bool skipMessage = settings.GetBoolean(SKIP_INTENT_CHECK, false);
if (!skipMessage)
bool HasIntent = false;
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(SKIP_INTENT_CHECK, 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();
HasIntent = true;
break;
if (!HasIntent)
editor.PutBoolean(SKIP_INTENT_CHECK, true);
editor.Apply();
在您的Android.Manifest
中添加以下权限
<uses-permission android:name="oppo.permission.OPPO_COMPONENT_SAFE"/>
<uses-permission android:name="com.huawei.permission.external_app_settings.USE_COMPONENT"/>
为了帮助找到此处未列出的设备的活动,只需使用以下方法帮助找到为用户打开的正确活动
C#
public static void LogDeviceBrandActivities(Context context)
var Brand = Android.OS.Build.Brand?.ToLower()?.Trim() ?? "";
var Manufacturer = Android.OS.Build.Manufacturer?.ToLower()?.Trim() ?? "";
var apps = context.PackageManager.GetInstalledPackages(PackageInfoFlags.Activities);
foreach (PackageInfo pi in apps.OrderBy(n => n.PackageName))
if (pi.PackageName.ToLower().Contains(Brand) || pi.PackageName.ToLower().Contains(Manufacturer))
var print = false;
var activityInfo = "";
if (pi.Activities != null)
foreach (var activity in pi.Activities.OrderBy(n => n.Name))
if (activity.Name.ToLower().Contains(Brand) || activity.Name.ToLower().Contains(Manufacturer))
activityInfo += " Activity: " + activity.Name + (string.IsNullOrEmpty(activity.Permission) ? "" : " - Permission: " + activity.Permission) + "\n";
print = true;
if (print)
Android.Util.Log.Error("brand.activities", "PackageName: " + pi.PackageName);
Android.Util.Log.Warn("brand.activities", activityInfo);
Java
public static void logDeviceBrandActivities(Context context)
String brand = Build.BRAND.toLowerCase();
String manufacturer = Build.MANUFACTURER.toLowerCase();
List<PackageInfo> apps = context.getPackageManager().getInstalledPackages(PackageManager.GET_ACTIVITIES);
Collections.sort(apps, (a, b) -> a.packageName.compareTo(b.packageName));
for (PackageInfo pi : apps)
if (pi.packageName.toLowerCase().contains(brand) || pi.packageName.toLowerCase().contains(manufacturer))
boolean print = false;
StringBuilder activityInfo = new StringBuilder();
if (pi.activities != null && pi.activities.length > 0)
List<ActivityInfo> activities = Arrays.asList(pi.activities);
Collections.sort(activities, (a, b) -> a.name.compareTo(b.name));
for (ActivityInfo ai : activities)
if (ai.name.toLowerCase().contains(brand) || ai.name.toLowerCase().contains(manufacturer))
activityInfo.append(" Activity: ").append(ai.name)
.append(ai.permission == null || ai.permission.length() == 0 ? "" : " - Permission: " + ai.permission)
.append("\n");
print = true;
if (print)
Log.e("brand.activities", "PackageName: " + pi.packageName);
Log.w("brand.activities", activityInfo.toString());
在启动时执行并搜索日志文件,在TAG
的brand.activities
上添加一个logcat 过滤器
MainActivity =>
protected override void OnCreate(Bundle savedInstanceState)
base.OnCreate(savedInstanceState);
MyUtils.LogDeviceBrandActivities(this);
样本输出:
E/brand.activities: PackageName: com.samsung.android.lool
W/brand.activities: ...
W/brand.activities: Activity: com.samsung.android.sm.ui.battery.AppSleepSettingActivity
W/brand.activities: Activity: com.samsung.android.sm.ui.battery.BatteryActivity <-- This is the one...
W/brand.activities: Activity: com.samsung.android.sm.ui.battery.BatteryActivityForCard
W/brand.activities: ...
所以组件名称将是:
new ComponentName("<PackageName>", "<Activity>")
new ComponentName("com.samsung.android.lool", "com.samsung.android.sm.ui.battery.BatteryActivity")
如果活动旁边有权限,则需要Android.Manifest
中的以下条目才能打开活动:
<uses-permission android:name="<permission>" />
在此答案中评论或编辑新组件。我将不胜感激所有帮助。
【讨论】:
类名“com.huawei.systemmanager.optimize.process.ProtectActivity”是怎么找到的?我想为 Qmobile 实现类似的东西,但不知道 Qmobile 的包名和“除了应用程序”屏幕的类名 您可以在您的回答中编辑 Qmobile .. new Intent().setComponent(new ComponentName( "com.dewav.dwappmanager", "com.dewav.dwappmanager.memory.SmartClearupWhiteList")), 我已经使用了这个代码,但它在三星 J6 手机上不起作用。 @Pierre 你有没有考虑把它变成 GitHub 上的一个库,以便其他项目可以直接包含它?其他开发人员也可以通过拉取请求贡献新组件。想法?【参考方案5】:PowerMaster -> AutoStart ->在阻止部分找到您的应用并允许
【讨论】:
【参考方案6】:为Pierre+1,因为他的出色解决方案适用于多个设备制造商(华为、华硕、oppo ...)。
我想在我用 Java 编写的 Android 应用中使用他的代码。 我的代码灵感来自 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)
try
if (intent == null || context == null)
return false;
else
List<ResolveInfo> list = context.getPackageManager().queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
return list.size() > 0;
catch (Exception ignored)
return false;
import android.content.ComponentName;
import android.content.Intent;
import java.util.Arrays;
import java.util.List;
public class Constants
//updated the POWERMANAGER_INTENTS 26/06/2019
static final 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.huawei.systemmanager", Build.VERSION.SDK_INT >= Build.VERSION_CODES.P? "com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity": "com.huawei.systemmanager.appcontrol.activity.StartupAppControlActivity")),
new Intent().setComponent(new ComponentName("com.coloros.oppoguardelf", "com.coloros.powermanager.fuelgaue.PowerUsageModelActivity")),
new Intent().setComponent(new ComponentName("com.coloros.oppoguardelf", "com.coloros.powermanager.fuelgaue.PowerSaverModeActivity")),
new Intent().setComponent(new ComponentName("com.coloros.oppoguardelf", "com.coloros.powermanager.fuelgaue.PowerConsumptionActivity")),
new Intent().setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity")),
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ? new Intent().setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.startupapp.StartupAppListActivity")).setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS).setData(Uri.parse("package:"+ MyApplication.getContext().getPackageName())) : null,
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")),
new Intent().setComponent(new ComponentName("com.asus.mobilemanager", "com.asus.mobilemanager.autostart.AutoStartActivity")),
new Intent().setComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity"))
.setData(android.net.Uri.parse("mobilemanager://function/entry/AutoStart")),
new Intent().setComponent(new ComponentName("com.meizu.safe", "com.meizu.safe.security.SHOW_APPSEC")).addCategory(Intent.CATEGORY_DEFAULT).putExtra("packageName", BuildConfig.APPLICATION_ID)
);
在你的Android.Manifest
中添加以下权限
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission android:name="oppo.permission.OPPO_COMPONENT_SAFE"/>
<uses-permission android:name="com.huawei.permission.external_app_settings.USE_COMPONENT"/>
我在使用 OPPO 设备时仍然遇到一些问题
我希望这对某人有所帮助。
【讨论】:
效果很好。现在,华为似乎不再使用 PretectedApp 设置了。看起来它正在使用一个名为“启动 - 管理应用程序启动和后台运行以节省电量”的选项,您必须允许应用程序“自动启动”、“二次启动”和“在后台运行”。知道这是什么意图吗? 我很高兴它对你有用 :)。对不起,我不知道你提到的华为新功能。我应该搜索一下,否则我的应用程序会出现问题。 @Ton 使用这个:com.huawei.systemmanager.appcontrol.activity.StartupAppControlActivity 将华硕更改为 ComponentName("com.asus.mobilemanager","com.asus.mobilemanager.autostart.AutoStartActivity") EMUI+5以上改华为手机:new Intent().setComponent(new ComponentName("com.huawei.systemmanager", Build.VERSION.SDK_INT >= Build.VERSION_CODES.P? "com. huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity": "com.huawei.systemmanager.appcontrol.activity.StartupAppControlActivity")),【参考方案7】:您可以使用此库将用户导航到受保护的应用程序或自动启动:
AutoStarter
如果手机支持自动启动功能,您可以向用户显示在这些应用中启用您的应用的提示
您可以通过这种方法检查:
AutoStartPermissionHelper.getInstance().isAutoStartPermissionAvailable(context)
为了将用户导航到该页面,只需调用以下代码:
AutoStartPermissionHelper.getInstance().getAutoStartPermission(context)
【讨论】:
适用于华为 Mate 20 Pro。得到以下崩溃。 android.os.RemoteException:远程堆栈跟踪:在 com.android.server.wm.ActivityStarter.startActivity(ActivityStarter.java:904) 在 com.android.server.wm.ActivityStackSupervisor.checkStartAnyActivityPermission(ActivityStackSupervisor.java:1194) 在 com .android.server.wm.ActivityStarter.startActivity(ActivityStarter.java:652) 在 com.android.server.wm.HwActivityStarter.startActivity(HwActivityStarter.java:292) 在 com.android.server.wm.ActivityStarter.startActivityMayWait(ActivityStarter .java:1647)以上是关于华为手机上的“受保护的应用程序”设置,以及如何处理的主要内容,如果未能解决你的问题,请参考以下文章