如何通过程序获取MIUI安全应用的自动启动权限?

15

我在我的小米红米2 Prime手机上没有收到BOOT_COMPLETE广播。

我的BroadcastReciever是 ---

public class OnBootReceiver extends BroadcastReceiver {

@Override
public void onReceive(Context context, Intent intent) {
    // Setting singleAlarm
    SingleAlarmHandler.getInstance().setAlarm(context);

    try {
        // Sending System Setting broadcast
        String offDate = SharedPrefrencesHandler.getInstance(context).readString(SharedPrefrencesConstants.SWITCH_OFF_DATE);
        int type = SystemSettingsType.PHONE_SWITCH_ON_OFF.getNumericType();

        if (offDate == null)
            offDate = "";

        SystemSettingsHandler.getSystemSettingsHandler().makeSystemSettingsCall(context, type, offDate);
        SharedPrefrencesHandler.getInstance(context).removePrefrence(SharedPrefrencesConstants.SWITCH_OFF_DATE);
        } catch (Exception e) {
            Log.e(ChaseForceApplication.TAG, e.getMessage());
        }
    }
}

以及清单:

    <receiver
        android:name=".broadcastlisteners.OnBootReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

经过许可:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

现在我的小米红米2 Prime手机没有收到启动完成广播,因为没有设置闹钟。但是在其他安卓手机上,它运行正常。

我搜索并发现这是MIUI固件的问题。在这样的手机中,他们提供了一个内置的安全应用程序,除非您在该安全应用程序中允许自动启动权限,否则无法获得广播(任何通知)。

一旦您在该应用程序中检查了该权限,您就可以开始接收广播。

现在我的问题是:

如何以编程方式获取MIUI安全应用程序的自动启动权限(像红米这样的电话)?


1
你在说什么?展示一下你的代码吧。(Manifest文件和你的接收器) - xdevs23
@xdevs23,感谢您的评论,现在我已经添加了我的代码...如果我只添加一个toast(并删除其他代码)到广播接收器中,那么在我的红米Prime 2手机上仍然无法显示该toast,但是在其他手机上如Moto e,Micromax android1等都可以显示。 - Imran Khan Saifi
嗨@ImranKhanSaifi。这是MIUI Roms中添加的安全功能。使用小米手机(带有MIUI)的任何开发人员都会知道这一点。我也遇到了同样的问题。我搜索了很多,但似乎MIUI的开发人员没有提供任何SDK来访问权限管理器等。如果您找到任何解决方案,请回复我。 - Mazhar
1
嗨@Mazhar,感谢您的回复...是的,您是正确的。 Sequrity应用程序是一个系统应用程序,因此我们无法对其进行任何控制,用户可以随时删除任何权限和通知(AutoStart Check).....还有一件事情在我的应用程序中造成问题,那就是当应用程序未运行时无法获取位置..原因是另一个设置..在电池->管理应用程序电池使用->..默认情况下选择了标准模式,这会阻止您的应用程序在未运行时获取位置并使用网络..因此,您还必须在“选择应用程序”选项中检查您的应用程序。 - Imran Khan Saifi
有人能提供通用解决方案,以使警报在不同制造的设备上正常工作吗?我正在寻求针对不同设备的所有解决方案。谢谢。 - Mostafa Imran
2个回答

14

这个问题已经在两个Stack Overflow线程中有了答案:

线程#1 https://dev59.com/J1kR5IYBdhLWcg3w0AOy#40932178

String xiaomi = "Xiaomi";
final String CALC_PACKAGE_NAME = "com.miui.securitycenter";
final String CALC_PACKAGE_ACITIVITY = "com.miui.permcenter.autostart.AutoStartManagementActivity";
if (deviceManufacturer.equalsIgnoreCase(xiaomi)) {
    DisplayUtils.showDialog(activity, "Ask for permission", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            try {
                Intent intent = new Intent();
                intent.setComponent(new ComponentName(CALC_PACKAGE_NAME, CALC_PACKAGE_ACITIVITY));
                activity.startActivity(intent);
            } catch (ActivityNotFoundException e) {
                Logger.e(TAG, "Failed to launch AutoStart Screen ", e);
            } catch (Exception e) {
                Logger.e(TAG, "Failed to launch AutoStart Screen ", e);
            }
        }
    }, new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {

        }
    });
}

线程#2 https://dev59.com/qVkS5IYBdhLWcg3w25zq#41696993

String manufacturer = "xiaomi";
        if(manufacturer.equalsIgnoreCase(android.os.Build.MANUFACTURER)) {
            //this will open auto start screen where user can enable permission for your app
            Intent intent = new Intent();
            intent.setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity"));
            startActivity(intent);
        }

对于华为设备上类似的问题:

https://dev59.com/WVwZ5IYBdhLWcg3wROmO#35220476

    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
嗨@Dika,感谢您的回复。我正在使用您为小米编写的自启动代码。通过您的代码,我能够到达自启动设置活动,但我无法知道用户是否已经授予自启动权限。我能否以某种方式了解用户的操作,无论用户是否已经授予权限(最终权限状态)? - Imran Khan Saifi
2
据我所知,您无法知道用户是否已经授权。小米不提供此功能。您可以做的最好的事情是向用户显示一个带有复选框的小对话框:“我已经允许此应用程序自动启动”。如果这对您有帮助,请将我的评论标记为答案。 - Dika
@Dika:如果是华硕设备怎么办?我正在使用华硕,它也会阻止自启动,我使用自启动管理器来允许后台服务。 - newbie

1

您需要在内置安全应用中为xiaomi授予权限。

1. open the security app
2. go to permissions
3. go to auto start
4. enable the applications that you want to keep running in the background!

这对我有用..!


1
这些步骤如何通过编程实现?您提到了手动步骤。 - Vineet Kasat
@VineetKasat,你有任何解决方案吗? - Vishal Patoliya ツ
@VineetKasat,你有没有任何解决方案,可以通过编程来完成这些步骤? - karthik
@karthik 这些步骤无法以编程方式完成。在我们的生产应用程序中,我们不得不将某些步骤漂浮到手动执行。 - Vineet Kasat
1
如果所说的是真的,那么给流行应用强大的功能,却拒绝其他应用使用,这不违反公开竞争吗?这意味着新应用处于劣势。这是阻止来自中国以外的新应用变得流行的一种方式。规则应该对所有人都一样,无论大小。 - Sahil Deswal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接