Как программно проверить разрешение автозапуска MIUI?

Мне нужно программно проверить, включено или выключено разрешение на автоматический запуск моего приложения в телефоне MIUI. У Facebook и WhatsApp это разрешение уже включено по умолчанию, как я могу это сделать?


person Ekta Aggarwal    schedule 07.09.2016    source источник


Ответы (8)


Пока это невозможно.

Поскольку это полностью зависит от их 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. Недавно я использовал Mi A1 от XIOMI, на котором установлен стандартный android (не miui), поэтому этот телефон не имеет autostart permission настроек от miui. Так что будьте осторожны при переходе пользователя к настройкам на таких устройствах, потому что здесь это не будет работать.

person Nikhil    schedule 07.09.2016
comment
Но некоторые приложения, такие как facebook messenger, whatsapp и т. Д., По умолчанию имеют функцию автозапуска. Есть идеи, как дела с этим? - person arul; 20.12.2016
comment
@arul Эти приложения внесены в белый список ОС miui, поэтому они автоматически получают разрешение на автозапуск. - person Nikhil; 20.12.2016
comment
да @indramurari. В качестве обходного пути мы можем попросить пользователей перенаправить в приложение безопасности, как упомянуто здесь. stackoverflow.com/questions/40814126/ - person arul; 26.12.2016
comment
На данный момент это кажется единственным обходным решением. Ненавижу, когда кастомные ПЗУ так вмешиваются! - person desidigitalnomad; 27.07.2017
comment
@Nikhil как проверить разрешение автозапуска уже включено или нет - person Akash Singh; 20.06.2018
comment
@AkashSingh Я не думаю, что это возможно - person Nikhil; 22.06.2018
comment
@Nikhil Можно ли теперь проверить, включено ли разрешение? - person Royz; 03.04.2019
comment
@Royz, ты нашел решение? - person Keselme; 11.06.2020

100% работает для oppo, vivo, xiomi, letv huawei и honor

просто вызовите эту функцию

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));
    }
}
person Shubham    schedule 08.03.2018
comment
Это не отвечает, установил ли пользователь разрешение или нет. - person Gaket; 09.07.2018
comment
Это отвечает на мой вопрос. :) - person John T; 25.08.2018
comment
К сожалению, на oppo A77 не работает. Отказ в разрешении: запуск намерения {cmp = com.coloros.safecenter / .startupapp.StartupAppListActivity}. Я также поместил это oppo.permission.OPPO_COMPONENT_SAFE в манифест. - person Jonathan Liono; 03.09.2018
comment
Правильно запускать разрешение на автоматический запуск, но как проверить разрешение на автоматический запуск уже включено или нет. - person Makvin; 26.10.2018
comment
@Shubham, как вы получили эти названия классов? - person Alexander Marochko; 17.01.2019
comment
Подождите, эта проблема существует и на устройствах других компаний? - person android developer; 31.01.2019
comment
Он перенаправляется каждый раз, когда я открываю свое приложение, даже если я уже дал разрешение на автоматический запуск. Как с этим бороться? @Shubham - person Nevil Ghelani; 01.06.2019
comment
Спасибо, у меня работает - person Biplob Das; 12.02.2021

Это ни в коем случае не идеальное решение и требует некоторого тестирования, но с его помощью я смог определить разрешение автозапуска на моем устройстве Xiaomi.

Разрешение автозапуска позволяет запускать приложения, получая неявное широковещательное намерение. Этот метод состоит из планирования неявной трансляции с помощью 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();
    }

    /* ... */
}

Вы также можете остановить все службы на всякий случай.

person SpaceBison    schedule 24.07.2017
comment
я не получаю никакой трансляции у вас есть другой способ или пример? - person Rahul; 04.01.2019
comment
Не могли бы вы сделать это отдельной библиотекой и опубликовать? Я пробовал использовать это, но получаю оба намерения, хотя автозапуск выключен. Также мне неясно, как предполагается воссоздать действие в этом методе. - person FreeBird; 03.04.2019

В дополнение к ответу Никхила:

Прежде всего, некоторые приложения, такие как Facebook, Whatsapp, по умолчанию занесены в белый список Xiomi, что означает, что для этих приложений автоматически будет включено разрешение на автоматический запуск.

Я также не нашел способа проверить разрешение на автоматический запуск, включено оно или нет, и включить его программно. Хотя, как указано выше, мы можем перенаправить пользователя на автоматический запуск разрешений, но когда нам нужно перенаправить пользователя, мы все еще не знаем, и это не будет работать на всех устройствах Xiomi.

Поэтому я использовал альтернативу для работы моего адаптера синхронизации. Я сохранил логическую переменную с именем isSyncAdapterRunning в общих настройках и устанавливал ее значение при каждом запуске адаптера синхронизации. Таким образом я смогу узнать, работает ли мой адаптер синхронизации или нет.

//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 часа.

Надеюсь это поможет.

person Vipul Kumar    schedule 14.12.2017

Пока это невозможно. Поскольку это полностью зависит от их 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();
    }
}
person Ashwini    schedule 11.02.2021

Вы не можете проверить, включено ли разрешение автозапуска или нет, потому что функция автозапуска предоставляется только настраиваемой ОС, а не ОС Android, такой как mi, vivo, oppo, letv и т. Д.

Это обходной путь протестирован на телефонах MI, Honor и vivo.

Чтобы проверить, настроена ли ОС как miui, скопируйте и вставьте этот метод в класс активности, фрагмента или утилиты.

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())
            }
        }
person Quick learner    schedule 04.06.2021

Чтобы проверить, включено ли разрешение, я просто запускаю службу переднего плана и проверяю, работает ли она.

Услуга:

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"/>

person David Cohen    schedule 22.06.2021

Вы должны разрешить и запретить системные разрешения.

ниже код:

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;
    }
}
person Divyang Patel    schedule 07.09.2016
comment
разрешение автозапуска предназначено для уведомления, я думаю, что приведенный выше ответ для LOCATION - person Aman Verma; 05.01.2017