如何以编程方式检查MIUI自动启动权限?

时间:2016-09-07 09:31:59

标签: android autostart background-service

我需要以编程方式检查MIUI手机中我的应用的自动启动权限是打开还是关闭。 Facebook和whatsapp默认已启用此权限,我该怎么办?

8 个答案:

答案 0 :(得分:29)

现在不可能。

因为它完全取决于他们的操作系统API和自定义。甚至开发者也已经在XIOMI的官方论坛上提出要求,但是没有回复。

直到现在我甚至找到了这个问题的答案,但没有任何帮助。

暂时只能使用有根电话。即通过成为超级用户在其固件中进行自定义。 但这根本不可取,因为它可能会损坏用户的手机

编辑1

您可以使用以下代码

将用户重定向到自动启动权限的设置页面以启用您的应用
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 intent1 = new Intent();
    intent1.setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity"));
    startActivity(intent1);
}

编辑2 我最近使用了来自XIOMI的Mi A1,它有现货android(不是miui)所以这款手机没有来自miui的autostart permission设置。因此,在将用户导航到此类设备中的设置时要小心,因为它在此处不起作用。

答案 1 :(得分:16)

100%为oppo,vivo,xiomi,letv huawei和荣誉工作

只需调用此函数

private void addAutoStartup() {

    try {
        Intent intent = new Intent();
        String manufacturer = android.os.Build.MANUFACTURER;
        if ("xiaomi".equalsIgnoreCase(manufacturer)) {
            intent.setComponent(new ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity"));
        } else if ("oppo".equalsIgnoreCase(manufacturer)) {
            intent.setComponent(new ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity"));
        } else if ("vivo".equalsIgnoreCase(manufacturer)) {
            intent.setComponent(new ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity"));
        } else if ("Letv".equalsIgnoreCase(manufacturer)) {
            intent.setComponent(new ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity"));
        } else if ("Honor".equalsIgnoreCase(manufacturer)) {
            intent.setComponent(new ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity"));
        }

        List<ResolveInfo> list = getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        if  (list.size() > 0) {
            startActivity(intent);
        }
    } catch (Exception e) {
        Log.e("exc" , String.valueOf(e));
    }
}

答案 2 :(得分:4)

这不是一个完美的解决方案,它需要一些测试,但我已经能够用它来检测我的小米设备的自动启动权限。

自动启动权限允许通过接收隐式广播意图来启动应用。此方法包括使用AlarmManager调度隐式广播,终止应用并检查广播是否导致重新生成。还计划了第二个显式意图,以确保最终启动应用程序。

public class AutostartDetector extends BroadcastReceiver {

// I've omitted all the constant declaration to keep this snippet concise
// they should match the values used in the Manifest

public static void testAutoStart(Context context) {
    long now = System.currentTimeMillis();
    // this ID is for matching the implicit and explicit intents
    // it might be unnecessary
    String testId = Long.toHexString(now);

    Intent implicitIntent = new Intent(ACTION_IMPLICIT_BROADCAST);
    // the category is set just to make sure that no other receivers handle the broadcast
    implicitIntent.addCategory(CATEGORY_AUTOSTART);
    implicitIntent.putExtra(EXTRA_TEST_ID, testId);

    PendingIntent implicitPendingIntent =
            PendingIntent.getBroadcast(context, REQUEST_CODE_IMPLICIT_BROADCAST, implicitIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    Intent explicitIntent = new Intent(ACTION_EXPLICIT_BROADCAST);
    explicitIntent.addCategory(CATEGORY_AUTOSTART);
    explicitIntent.setComponent(new ComponentName(context, AutostartDetector.class));
    explicitIntent.putExtra(EXTRA_TEST_ID, testId);

    PendingIntent explicitPendingIntent =
            PendingIntent.getBroadcast(context, REQUEST_CODE_EXPLICIT_BROADCAST, explicitIntent, PendingIntent.FLAG_UPDATE_CURRENT);

    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

    // calling commit() makes sure that the data is written before we kill the app
    // again, this might be unnecessary
    getSharedPreferences(context).edit().putInt(testId, TestStatus.STARTED).commit();

    // the explicit intent is set with an additional delay to let the implicit one be received first; might require some fine tuning
    alarmManager.set(AlarmManager.RTC_WAKEUP, now + BASE_DELAY, implicitPendingIntent);
    alarmManager.set(AlarmManager.RTC_WAKEUP, now + BASE_DELAY + EXPLICIT_INTENT_DELAY, explicitPendingIntent);

    // kill the app - actually kind of tricky, see below
    SelfKiller.killSelf(context);
}

@Override
public void onReceive(Context context, Intent intent) {
    SharedPreferences sharedPreferences = getSharedPreferences(context);
    String testId = intent.getStringExtra(EXTRA_TEST_ID);

    if (testId == null) {
        Log.w(TAG, "Null test ID");
        return;
    }

    if (!sharedPreferences.contains(testId)) {
        Log.w(TAG, "Unknown test ID: " + testId);
        return;
    }

    String action = intent.getAction();
    if (ACTION_IMPLICIT_BROADCAST.equals(action)) {
        // we could assume right here that the autostart permission has been granted,
        // but we should receive the explicit intent anyway, so let's use it
        // as a test sanity check
        Log.v(TAG, "Received implicit broadcast");
        sharedPreferences.edit().putInt(testId, TestStatus.IMPLICIT_INTENT_RECEIVED).apply();
    } else if (ACTION_EXPLICIT_BROADCAST.equals(action)) {
        Log.v(TAG, "Received explicit broadcast");
        int testStatus = sharedPreferences.getInt(testId, -1);
        switch (testStatus) {
            case TestStatus.STARTED:
                // the implicit broadcast has NOT been received - autostart permission denied
                Log.d(TAG, "Autostart disabled");
                sharedPreferences.edit().putBoolean(PREF_AUTOSTART_ENABLED, false).apply();
                notifyListener(false);
                break;

            case TestStatus.IMPLICIT_INTENT_RECEIVED:
                // the implicit broadcast has been received - autostart permission granted
                Log.d(TAG, "Autostart enabled");
                sharedPreferences.edit().putBoolean(PREF_AUTOSTART_ENABLED, true).apply();
                notifyListener(true);
                break;

            default:
                Log.w(TAG, "Invalid test status: " + testId + ' ' + testStatus);
                break;
        }
    }
}

private interface TestStatus {
    int STARTED = 1;
    int IMPLICIT_INTENT_RECEIVED = 2;
}

清单中的接收者声明:

<receiver android:name=".autostart.AutostartDetector">
    <intent-filter>
        <category android:name="com.example.autostart.CATEGORY_AUTOSTART"/>
        <action android:name="com.example.autostart.ACTION_IMPLICIT_BROADCAST"/>
        <action android:name="com.example.autostart.ACTION_EXPLICIT_BROADCAST"/>
    </intent-filter>
</receiver>

可靠地杀死应用程序是另一个问题。我一直在使用这个辅助方法:

public static void killSelf(Context context) {
    ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    activityManager.killBackgroundProcesses(context.getPackageName());

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
        // this is all we can do before ICS. luckily Xiaomi phones have newer system versions :)
        System.exit(1);
        return;
    }

    // set up a callback so System.exit() is called as soon as all
    // the activities are finished
    context.registerComponentCallbacks(new ComponentCallbacks2() {
        @Override
        public void onTrimMemory(int i) {
            if (i == TRIM_MEMORY_UI_HIDDEN) {
                Log.v(TAG, "UI Hidden");
                System.exit(1);
            }
        }

        /* ... */
    });

    // see below
    ActivityTracker.getInstance().finishAllActivities();
}

ActivityTracker是另一个跟踪活动生命周期的实用程序。确保在Application子类中注册它。

@RequiresApi(api = Build.VERSION_CODES.ICE_CREAM_SANDWICH)
public final class ActivityTracker implements Application.ActivityLifecycleCallbacks {
    private final ArraySet<Activity> mCreatedActivities = new ArraySet<>();

    public static ActivityTracker getInstance() {
        return Holder.INSTANCE;
    }

    public static void init(Application application) {
        application.registerActivityLifecycleCallbacks(getInstance());
    }

    public static void release(Application application) {
        ActivityTracker activityTracker = getInstance();
        application.unregisterActivityLifecycleCallbacks(activityTracker);
        activityTracker.mCreatedActivities.clear();
    }

    public void finishAllActivities() {
        // iterate over active activities and finish them all
        for (Activity activity : mCreatedActivities) {
            Log.v(TAG, "Finishing " + activity);
            activity.finish();
        }
    }

    public Set<Activity> getCreatedActivities() {
        return Collections.unmodifiableSet(mCreatedActivities);
    }

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        mCreatedActivities.add(activity);
    }    

    @Override
    public void onActivityDestroyed(Activity activity) {
        mCreatedActivities.remove(activity);
    }

    private static final class Holder {
        private static final ActivityTracker INSTANCE = new ActivityTracker();
    }

    /* ... */
}

您可能还想要停止所有服务以确保。

答案 3 :(得分:1)

除了Nikhil's answer

首先,Facebook,Whatsapp等一些应用程序在默认情况下从Xiomi列入白名单,这意味着这些应用程序将自动启动自动启动权限。

如果已启用或未启用自动启动权限,我也找不到任何方法来检查自动启动权限并以编程方式启用它。虽然上面的答案表明我们可以将用户重定向到自动启动权限活动,但是当我们必须重定向用户时,我们仍然不知道,这也不适用于所有的Xiomi设备。

所以我使用了我的同步适配器的替代方案。我存储了一个名为&#34; isSyncAdapterRunning&#34;的布尔变量。在共享首选项中,并在每次运行同步适配器时设置它的值。通过这种方式,我可以知道我的同步适配器是否正常工作。

//in my sync adapter
@Override
public void onPerformSync(Account account, Bundle extras, String authority, ContentProviderClient provider, SyncResult syncResult) {
    Log.e("TAG", "SyncStarted");
    performSync(true);        
}

public static void performSync(boolean fromSyncAdapterClass){
    //write your code for sync operation
    if(fromSyncAdapterClass){
          setValueOfIsSyncAdapterRunningVariable();
    }
}

如果同步适配器不工作,我还提供了其他后台服务来执行相同的任务。

//In my other background service
public class BackgroundSyncService extends IntentService {

public BackgroundSyncService() {
    super("BackgroundSyncService");
}

@Override
protected void onHandleIntent(Intent intent) {
    SyncAdapter.performSync(false);        
}
}

现在启动同步适配器:

// start your sync adapter here

//And after that just start that service with a condition
if(!getValueOfIsSyncAdapterRunningVariable()){
      startService(new Intent(context, BackgroundSyncService.class));
}

所以基本上我运行另一个服务来在后台执行相同的任务,如果我的同步适配器不工作,最好的事情是它们中只有一个会一次运行。 如果用户打开自动启动权限并再次关闭,则上面的代码将失败,因为已经设置了布尔变量的值。为此,您可以在24小时内将布尔变量的值设置为默认值。

希望这有帮助。

答案 4 :(得分:1)

暂时不可能。 因为它完全取决于他们的操作系统 API 和自定义。但是我使用 SharedPreference 实现了修复。它没有解决问题,但它会阻止应用程序在每次打开应用程序时打开设置屏幕。示例:

 if (AppPref.getAutoStart(context).isEmpty() && AppPref.getAutoStart(context).equals("")) {
        enableAutoStart();
    }

private void enableAutoStart() {
    if (Build.BRAND.equalsIgnoreCase("xiaomi")) {

        new AlertDialog.Builder(context)
                .setTitle("Enable AutoStart")
                .setMessage("Please allow this app to always run in the background,else our services can't be accessed.")
                .setNegativeButton("Deny", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        AppPref.setAutoStart(context, "");
                        dialog.dismiss();
                    }
                })
                .setPositiveButton("ALLOW", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        try {
                            AppPref.setAutoStart(context, "1");
                            Intent intent = new Intent();
                            intent.setComponent(new ComponentName("com.miui.securitycenter",
                                    "com.miui.permcenter.autostart.AutoStartManagementActivity"));
                            startActivity(intent);
                        } catch (Exception e) {
                            Toast.makeText(context, "Can't perform action", Toast.LENGTH_SHORT).show();
                        }
                        dialog.dismiss();
                    }
                })
                .create()
                .show();
    }
}

答案 5 :(得分:0)

您无法检查是否启用了自动运行权限,因为自动运行功能是由自定义操作系统提供的,而不是由 mi、vivo、oppo、letv 等 android 操作系统提供的

这是在 MI、Honor 和 vivo 手机上测试的变通方法。

检查os是否像miui一样自定义,荣耀ui复制粘贴这个方法到activity、fragment或者util类中

public static void getAutoStartPermission(final Activity context) {
        final String build_info = Build.BRAND.toLowerCase();
        switch (build_info) {
            case "xiaomi":
                Utilities.Companion.showAutorunDialog(context);
                break;
            case "letv":
                Utilities.Companion.showAutorunDialog(context);
                break;
            case "oppo":
                Utilities.Companion.showAutorunDialog(context);
                break;
            case "vivo":
                Utilities.Companion.showAutorunDialog(context);
                break;
            case "Honor":
                Utilities.Companion.showAutorunDialog(context);
                break;
            default:
                break;

        }

    }

哪里

fun showAutorunDialog(context: Context) {
            val builder = AlertDialog.Builder(context)
            //set title for alert dialog
            builder.setTitle("Alert")
            //set message for alert dialog
            builder.setMessage("Enable Autostart permission for this app if its disabled in app settings in order to run application in background.")
            builder.setCancelable(true)
            //performing positive action
            builder.setPositiveButton("Enable") { _, _ ->
                addAutoStartup(context)
            }

            // Create the AlertDialog
              var  vpnDialog = builder.create()
                // Set other dialog properties
                vpnDialog!!.setCancelable(false)
                vpnDialog!!.show()

        }
        private fun addAutoStartup(context:Context) {
            try {
                val intent = Intent()
                val manufacturer = Build.MANUFACTURER
                if ("xiaomi".equals(manufacturer, ignoreCase = true)) {
                    intent.component = ComponentName("com.miui.securitycenter", "com.miui.permcenter.autostart.AutoStartManagementActivity")
                } else if ("oppo".equals(manufacturer, ignoreCase = true)) {
                    intent.component = ComponentName("com.coloros.safecenter", "com.coloros.safecenter.permission.startup.StartupAppListActivity")
                } else if ("vivo".equals(manufacturer, ignoreCase = true)) {
                    intent.component = ComponentName("com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.BgStartUpManagerActivity")
                } else if ("Letv".equals(manufacturer, ignoreCase = true)) {
                    intent.component = ComponentName("com.letv.android.letvsafe", "com.letv.android.letvsafe.AutobootManageActivity")
                } else if ("Honor".equals(manufacturer, ignoreCase = true)) {
                    intent.component = ComponentName("com.huawei.systemmanager", "com.huawei.systemmanager.optimize.process.ProtectActivity")
                }
                val list: List<ResolveInfo> = context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY)
                if (list.size > 0) {
                    context.startActivity(intent)
                }
            } catch (e: java.lang.Exception) {
                Log.e("exc", e.toString())
            }
        }

答案 6 :(得分:0)

要检查是否启用了权限,我只是启动了一个前台服务并检查是否正在运行。

服务:

class ExtraPermissionStateService: Service() {

    companion object {
        private var instance: ExtraPermissionStateService? = null

        fun isAppCanRunOnBackground(context: Context): Boolean {
            val serviceIntent = Intent(context, ExtraPermissionStateService::class.java)
            context.startService(serviceIntent)
            return instance != null
        }
    }

    override fun onBind(p0: Intent?): IBinder? {
        return null
    }

    override fun onCreate() {
        super.onCreate()
        instance = this
    }

    override fun onDestroy() {
        super.onDestroy()
        instance = null
    }
}

称之为:

ExtraPermissionStateService.isAppCanRunOnBackground(context)

不要忘记在清单上:

<service android:name=".helpers.utils.ExtraPermissionStateService"/>

答案 7 :(得分:-4)

您必须允许和拒绝系统权限。

下面是代码:

private boolean checkPermission(){
    int result = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION);
    if (result == PackageManager.PERMISSION_GRANTED){

        return true;

    } else {

        return false;

    }
}

 @Override
 public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
    switch (requestCode) {
        case PERMISSION_REQUEST_CODE:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                Snackbar.make(view,"Permission Granted, Now you can access location data.",Snackbar.LENGTH_LONG).show();

            } else {

                Snackbar.make(view,"Permission Denied, You cannot access location data.",Snackbar.LENGTH_LONG).show();

            }
            break;
    }
}