android - restringido - ¿Cómo verificar el permiso de inicio automático de MIUI programáticamente?
notificaciones miui 9 (5)
100% trabajando para oppo, vivo, xiomi, letv huawei y honor
solo llama a esta función
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));
}
}
Necesito verificar mediante programación si el permiso de inicio automático para mi aplicación en el teléfono MIUI está activado o desactivado. Facebook y WhatsApp ya tienen este permiso habilitado de forma predeterminada, ¿cómo puedo hacerlo?
Además de la respuesta de Nikhil :
En primer lugar, algunas aplicaciones como Facebook, Whatsapp están en la lista blanca de Xiomi de manera predeterminada, lo que significa que el permiso de inicio automático estará automáticamente activado para estas aplicaciones.
Tampoco encontré ninguna forma de verificar el permiso de inicio automático si está habilitado o no y habilitarlo mediante programación. Aunque como se indica en la respuesta anterior, podemos redirigir al usuario a la actividad de permisos de inicio automático, pero cuando tenemos que redirigir al usuario, todavía no lo sabemos y tampoco funcionará en todos los dispositivos Xiomi.
Así que utilicé una alternativa para que mi adaptador de sincronización funcionara. Almacené una variable booleana llamada "isSyncAdapterRunning" en las preferencias compartidas y configuré su valor cada vez que se ejecuta el adaptador de sincronización. De esta manera podré saber si mi adaptador de sincronización está funcionando o no.
//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();
}
}
Hice otro servicio en segundo plano para realizar la misma tarea si el adaptador de sincronización no funciona.
//In my other background service
public class BackgroundSyncService extends IntentService {
public BackgroundSyncService() {
super("BackgroundSyncService");
}
@Override
protected void onHandleIntent(Intent intent) {
SyncAdapter.performSync(false);
}
}
Ahora inicie el adaptador de sincronización:
// start your sync adapter here
//And after that just start that service with a condition
if(!getValueOfIsSyncAdapterRunningVariable()){
startService(new Intent(context, BackgroundSyncService.class));
}
Básicamente, estoy ejecutando otro servicio para realizar la misma tarea en segundo plano si mi adaptador de sincronización no funciona y lo mejor es que solo uno de ellos se ejecutará a la vez. El código anterior fallará si el usuario activa el permiso de inicio automático y lo desactiva nuevamente porque el valor de la variable booleana ya está establecido. Para eso, puede establecer el valor de la variable booleana como predeterminado una vez cada 24 horas.
Espero que esto ayude.
Debe permitir y denegar los permisos del sistema.
A continuación se muestra el código:
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;
}
}
Esta no es una solución perfecta de ninguna manera y requiere algunas pruebas, pero he podido detectar el permiso de inicio automático en mi dispositivo Xiaomi con ella.
El permiso de inicio automático permite que las aplicaciones se inicien al recibir un intento de transmisión implícito. Este método consiste en programar una transmisión implícita con AlarmManager, matar la aplicación y verificar si la transmisión hizo que reaparezca. Una segunda intención explícita también está programada solo para asegurarse de que la aplicación se inicie eventualmente.
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;
}
Declaración del receptor en el manifiesto:
<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>
Matar la aplicación de manera confiable es otro problema. He estado usando este método de ayuda:
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 es otra utilidad que realiza un seguimiento de los ciclos de vida de la actividad. Asegúrese de registrarlo en la subclase de aplicación.
@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();
}
/* ... */
}
También es posible que desee detener todos los servicios solo para estar seguro.
Por ahora no es posible.
Como depende completamente de su API de sistema operativo y personalización. Incluso los desarrolladores han solicitado esto en los foros oficiales de XIOMI, pero no hay respuesta por parte de ese lado.
Hasta ahora, incluso estoy encontrando una respuesta a esta pregunta, pero nada me ayudó.
Por el momento solo será posible para teléfonos rooteados. es decir, hacer la personalización en su firmware convirtiéndose en superusuario. Pero esto no es en absoluto recomendable, ya que puede dañar los teléfonos de los usuarios .
EDITAR 1
Puede redirigir al usuario a la página de configuración de permisos de inicio automático para habilitar su aplicación usando el siguiente código
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);
}
EDITAR 2 Hace poco usé Mi A1 de XIOMI que tiene Android (no miui), por lo que este teléfono no tiene configuraciones de autostart permission
de inicio autostart permission
de miui. Por lo tanto, tenga cuidado al navegar por el usuario a la configuración en dichos dispositivos porque no funcionará aquí.