web-dev-qa-db-de.com

Wie kann ich die MIUI-Autostart-Berechtigung programmgesteuert überprüfen?

Ich muss programmgesteuert überprüfen, ob die Autostart-Berechtigung für meine App im MIUI-Telefon aktiviert oder deaktiviert ist. Facebook und WhatsApp haben diese Berechtigung bereits standardmäßig aktiviert. Wie kann ich das tun?

29
Ekta Aggarwal

Im Moment ist es nicht möglich.

Da es völlig von den APIs und Anpassungen des Betriebssystems abhängt. Sogar Entwickler haben dies in den offiziellen Foren von XIOMI angefordert, aber es gibt keine Antwort von dort.

Bis jetzt habe ich sogar eine Antwort auf diese Frage gefunden, aber nichts hat mir geholfen.

Derzeit ist dies nur für gerootete Telefone möglich. d.h. Anpassen ihrer Firmware, indem sie Superuser werden. Dies ist jedoch keinesfalls ratsam, da dies das Telefon des Benutzers beschädigen kann..

EDIT 1

Sie können den Benutzer zur Einstellungsseite der Autostart-Berechtigung umleiten, um Ihre App mit folgendem Code zu aktivieren

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

BEARBEITEN 2 Ich habe kürzlich Mi A1 von XIOMI verwendet, die Lagerbestände haben Android (nicht miui), daher hat dieses Telefon kein autostart permission Einstellungen von miui. Seien Sie also vorsichtig, während Sie den Benutzer zu den Einstellungen in solchen Geräten navigieren, da dies hier nicht funktioniert.

31
Nikhil

100% arbeiten für oppo, vivo, xiomi, letv huawei und ehre

rufen Sie einfach diese Funktion auf

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));
    }
}
17
Shubham

Dies ist keineswegs eine perfekte Lösung und erfordert einige Tests, aber ich konnte die Autostart-Berechtigung auf meinem Xiaomi-Gerät damit erkennen.

Mit der Autostart-Berechtigung können Apps durch Empfang einer impliziten Broadcast-Absicht gestartet werden. Diese Methode besteht darin, eine implizite Übertragung mit AlarmManager zu planen, die App zu beenden und zu überprüfen, ob die Übertragung dazu geführt hat, dass sie erneut auftritt. Eine zweite explizite Absicht ist ebenfalls geplant, um sicherzustellen, dass die App schließlich gestartet wird.

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

Empfängererklärung im Manifest:

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

Die App zuverlässig zu beenden, ist ein weiteres Problem. Ich habe diese Hilfsmethode verwendet:

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 ist ein weiteres Dienstprogramm, das die Lebenszyklen von Aktivitäten protokolliert. Stellen Sie sicher, dass Sie es in der Application-Unterklasse registrieren.

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

    /* ... */
}

Möglicherweise möchten Sie auch alle Dienste stoppen, um sicherzugehen.

4
SpaceBison

Zusätzlich zu Nikhils Antwort :

Zunächst werden einige Apps wie Facebook und WhatsApp von Xiomi standardmäßig auf die Whitelist gesetzt. Dies bedeutet, dass für diese Apps die Berechtigung zum automatischen Starten automatisch aktiviert wird.

Ich habe auch keine Möglichkeit gefunden, die Berechtigung zum automatischen Starten zu überprüfen, ob sie aktiviert ist oder nicht, und sie programmgesteuert zu aktivieren. Obwohl die obige Antwort darauf hindeutet, dass wir Benutzer zur automatischen Startberechtigungsaktivität umleiten können, wissen wir immer noch nicht, wann wir Benutzer umleiten müssen, und dies funktioniert auch nicht auf allen Xiomi-Geräten.

Also habe ich eine Alternative verwendet, damit mein Synchronisierungsadapter funktioniert. Ich habe eine boolesche Variable mit dem Namen "isSyncAdapterRunning" in den gemeinsamen Einstellungen gespeichert und den Wert jedes Mal festgelegt, wenn der Synchronisierungsadapter ausgeführt wird. Auf diese Weise kann ich feststellen, ob mein Synchronisierungsadapter funktioniert oder nicht.

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

Ich habe einen anderen Hintergrunddienst eingerichtet, um dieselbe Aufgabe auszuführen, wenn der Synchronisierungsadapter nicht funktioniert.

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

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

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

Starten Sie nun den Synchronisationsadapter:

// start your sync adapter here

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

Im Grunde genommen führe ich einen anderen Dienst aus, um dieselbe Aufgabe im Hintergrund auszuführen, wenn mein Synchronisierungsadapter nicht funktioniert und das Beste ist, dass jeweils nur einer von ihnen ausgeführt wird. Der obige Code schlägt fehl, wenn der Benutzer die Berechtigung zum automatischen Starten aktiviert und wieder deaktiviert, da der Wert der booleschen Variablen bereits festgelegt ist. Dafür können Sie den Wert der booleschen Variablen alle 24 Stunden auf den Standardwert setzen.

Hoffe das hilft.

1
Vipul Kumar