“Protected Apps” setting on Huawei phones, and how to handle it

匿名 (未验证) 提交于 2019-12-03 01:38:01

问题:

I have a Huawei P8 with Android 5.0 that I'm using for testing an app. The app needs to be running in the background, as it tracks BLE regions.

I've discovered that Huawei has built in a "feature" called Protected Apps, that can be accessed from the phone settings (Battery Manager > Protected Apps). This allows elected apps to keep running after the screen is turned off.

Sensibly for Huawei, but unfortunately for me, it looks like it's opt-in, i.e. apps are out by default, and you have to manually put them in. This isn't a showstopper, as I can advise users in an FAQ or printed documentation about the fix, but I recently installed Tinder (for research purposes!), and noticed that it was put in the protected list automatically.

Does anyone know how I can do this for my app? Is it a setting in the manifest? Is it something Huawei has enabled for Tinder because it's a popular app?

回答1:

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();     } 


回答2:

There isn't a setting in the manifest, and Huawei has enabled Tinder because it's a popular app. There isn't a way to know if apps are protected.

Anyway I used "ifHuaweiAlert()" in "onCreate" to show an 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 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 ""; } 


回答3:

i have collected some intent from various post to check all producer:

How to start Power Manager of all android manufactures to enable push notification?



回答4:

I'm using @Aiuspaktyn solution which is missing the part of how to detect when stop show the dialog after the user set the app as protected. I'm use a Service to check if the app was terminated or not, checking if it exists.



回答5:

+1 Aiuspaktyn for the java solution

Xamarin Solution

Usage:

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();         }     } } 

I still want to figure it out for the following (from here):

private static List POWERMANAGER_INTENTS = new List() {     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;         }     } } 

It would be nice to just run the following command, and everything is covered:

MyUtils.StartPowerSaverIntent(this); 

EDIT:

This should do:

public class MyUtils {     private static List POWERMANAGER_INTENTS = new List()     {         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;                 }             }         }     } } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!