Android - How to Enable Autostart option programmatically in Xiaomi devices?
Asked Answered
C

5

15

I am developing an android application in which I want to display the Push notification.

It has displayed well in most of the devices except Xiaomi phones (I am using Redmi Note 4). The problem that I found is, it is because of Autostart option provided by Xiomi which will be disabled by default and the user need to enable it manually.

But I wonder that some of the Android Apps I could see enabling this option without any user interaction Ex: WhatsApp. If I try reinstalling WhatsApp and see the Autostart option , it is enabled!

I am unable to convince our client by telling it is the feature of Xiomi like devices as he is pointing out some apps which is working fine like the example I have mentioned above.

This question has been asked by some other people

Add my app to AutoStart apps list in android programmatically

How to check AutoStart is enabled for our App in Xiaomi manufacturer mobile device Programmatically

But I could not see any answers for them and Posting here with the hope that someone will have an answer for this.

Chrysarobin answered 25/3, 2018 at 6:45 Comment(1)
Any solutions? plsIatry
G
7

The autostart feature will get enabled automatically when you will download the app from playstore if xiaomi OS wants it as apps like amazon ,google IO etc are also not allowed to autostart ,In this case you have to go to Security permissions -> autostart -> then enable autostart from there.You cannot make the app autostart by code all you can do is you can show a dialog to enable auto start and take the user to the autostart activity but this is not a good option as you cannot check whether autostart is enabled or not. This is done by Mi in MIUI8 for saving battery .This issue wasted my 2 days XD

You can refer to this article.

Geosyncline answered 25/3, 2018 at 7:18 Comment(11)
Thanks for your response. But this does not solve my problem :-(. I have tried installing my app from play store and still face the same issueChrysarobin
Maybe you havnt uninstalled the previous version of that app which is installed in your phone Thats why Because I was facing the same issue found a lot of things nothing worked but when I downloaded the same app from playstore it did the work for meGeosyncline
Can I know the app which is on play store so that I can do some Research on it as in Manifest There is an attribute of allowing back up due to which the app data retains some times It can happen due to that alsoGeosyncline
Sure. Please check this link play.google.com/store/apps/details?id=digital.engineers.clubChrysarobin
Which dependencies have you used for firebase push notifications .Geosyncline
Here are the Firebase dependencies I use ... compile 'com.google.firebase:firebase-messaging:11.8.0' compile 'com.google.firebase:firebase-crash:11.8.0'Chrysarobin
you should use the compile 'com.google.firebase:firebase-core:11.8.0' and then tryGeosyncline
I will try this but what this dependency does specifically on Xiaomi device .Chrysarobin
It says "We recommend starting with com.google.firebase:firebase-core, which provides Google Analytics for Firebase functionality" but nothing about this issue I hopeChrysarobin
Yes you are right if I will found any solution I will get back to youGeosyncline
Sure, Please :-)Chrysarobin
A
6

For xiaomi, oppo, vivo, etc. devices to Enable Autostart option programmatically

String manufacturer = android.os.Build.MANUFACTURER;
try {
      Intent intent = new Intent();
      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) {
      e.printStackTrace();
}
Acquaint answered 23/12, 2018 at 14:54 Comment(2)
else if ("meizu".equals(manufacturer, ignoreCase = true)) { intent = Intent("com.meizu.safe.security.SHOW_APPSEC") intent.addCategory(Intent.CATEGORY_DEFAULT) intent.putExtra("packageName", BuildConfig.APPLICATION_ID) }Sequence
please some check this on Meizu device. i have no meizu device. if some one want thisSequence
F
4

Few popular apps run in background without being killed during memory cleanup cycle (many of the popular OEMs customize the stock ROM for battery/memory optimization), because they are "White listed" by these manufactures. For your app you can whitelist it either manually (via corresponding "settings" for the devices) or programmatically by redirecting users to the corresponding settings page to white list the app. programmatically you can do like below:

  1. Add below permissions in the App's manifest file:`

    <uses-permission android:name="oppo.permission.OPPO_COMPONENT_SAFE"/> 
    <uses-permission android:name="com.huawei.permission.external_app_settings.USE_COMPONENT"/>`
    
  2. Redirect your to the Auto Start setting:

    if (Build.BRAND.equalsIgnoreCase("xiaomi")) {
                    Intent intent = new Intent();
                    intent.setComponent(new 
    
    ComponentName("com.miui.securitycenter",
                                "com.miui.permcenter.autostart.AutoStartManagementActivity"));
                        startActivity(intent);
                } else if (Build.MANUFACTURER.equalsIgnoreCase("oppo")) {
                    try {
                        Intent intent = new Intent();
                        intent.setClassName("com.coloros.safecenter",
                                "com.coloros.safecenter.permission.startup.StartupAppListActivity");
                        startActivity(intent);
                    } catch (Exception e) {
                        try {
                            Intent intent = new Intent();
                            intent.setClassName("com.oppo.safe",
                                    "com.oppo.safe.permission.startup.StartupAppListActivity");
                            startActivity(intent);
                        } catch (Exception ex) {
                            try {
                                Intent intent = new Intent();
                                intent.setClassName("com.coloros.safecenter",
                                        "com.coloros.safecenter.startupapp.StartupAppListActivity");
                                startActivity(intent);
                            } catch (Exception exx) {
    
                            }
                        }
                    }
                }
    

AutoStart Reference For other OEMs

I have tested this method and it worked but the reliability is still a question as system taking time (approx 2 Min on PoccoF1 & Xiaomi devices) to restart the killed service.

But as an user we can prevent the app's background services to get killed all together as below :

  1. Press Recent apps physical key (left side button).
  2. Drag down the app once (select, hold & slide it down) tap on the lock icon (if the lock is in open state) to lock the app.
  3. The app will be put in lock condition (even if you clear the background app processes by clearing, the app will keep on running).
  4. Same way, if you want to remove it from the lock condition, just drag down again once and the lock symbol will disappear (clearing the background process will clear the app from running too).

But, With this way App's locking status will be reset on reboot on most of the devices.

EDIT: After observing the behavior (on Xiaomi's RedmiS3, Android V6.0) of Foreground service here is the analysis:

  1. Even after enabling the "AutoStart" programatically (via user intervention, as explained above) the service didn't restarts always (Service restarted only on few occasions, but most of the time it didn't).
    Also, if I search for "AutoStart" in device settings I can't see my app there in the AutoStart list. It seems above method only providing Autostart permission but not enabling it, NOT SURE!. And, if I add my app into "AutoStart" list via device setting, my service gets restarted (though it takes some time).

  2. Restarting the killed service in onTaskRemoved() callback could be another option but this callback gets called in surprising way when service gets killed. This callback gets executed only when app is been closed properly by back key press. If we minimized the app (Pause state) this callback never gets called on service kill. (Looking for the reason)

Recently I found another way, the killed service could be restarted via GCM notification event. I doubt that weather the GCM works when App's gets killed on the devices or not (I need to check this and verify the behavior). But one this is for sure "These OEMs has made the programmer life hell!).

Footboard answered 28/5, 2019 at 5:57 Comment(1)
Reference of other OEM link not workingZhukov
A
4

I know it is too late to share the answer but I will put my two cents here because it is very very important. I wasted my 2 days in digging this problem out. I tried all the suggested solutions as provided here but nothings seemed to be working. Below is the solution I implemented in following steps:

Step # 01 Create your foreground service as you are doing and register it accordingly in manifest. For sample purposes, I am sharing sample of service.

class MyService : Service() {

private var wakeLock: PowerManager.WakeLock? = null

override fun onBind(intent: Intent): IBinder? {
    Log.d(tag!!, "Some component want to bind with the service")
    // We don't provide binding, so return null
    return null
}

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    Log.d(tag!!, "onStartCommand executed with startId: $startId")
    // by returning this we make sure the service is restarted if the system kills the service
    return START_STICKY
}

override fun onCreate() {
    super.onCreate()
    Log.d(tag!!, "The service has been created".toUpperCase(Locale.ROOT))
    startForeground(1, NotificationUtils.createNotification(this))
    acquireLock()
}

override fun onDestroy() {
    super.onDestroy()
    Log.d(tag!!, "The service has been destroyed".toUpperCase(Locale.ROOT))
    Toast.makeText(this, "Service destroyed", Toast.LENGTH_SHORT).show()
}

override fun onTaskRemoved(rootIntent: Intent?) {
    Log.d(tag!!, "onTaskRemoved")
    val restartServiceIntent = Intent(applicationContext, this.javaClass)
    restartServiceIntent.setPackage(packageName)
    val restartServicePendingIntent = PendingIntent.getService(applicationContext, 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT)
    val alarmService = applicationContext.getSystemService(ALARM_SERVICE) as AlarmManager
    alarmService[AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + 1000] = restartServicePendingIntent
    super.onTaskRemoved(rootIntent)
}

@SuppressLint("WakelockTimeout")
private fun acquireLock() {
    // we need this lock so our service gets not affected by Doze Mode
    wakeLock =
            (getSystemService(Context.POWER_SERVICE) as PowerManager).run {
                newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "MyService::lock").apply {
                    acquire()
                }
            }
}

}

NOTE: I have covered all the possible use cases to restart the Service in case it gets killed by OS. There is one thing left if user restarts cell phone. This case can be found via other stackoverflow answers very easy. In Broadcast one just needs to start Service.

Step # 02 Make an application and register in manifest. And add below line of code in your application class.

class MyApplication : Application() {

override fun onCreate() {
    super.onCreate()
    val receiver = ComponentName(this, MyService::class.java)
    val pm = packageManager

    pm.setComponentEnabledSetting(
        receiver,
        PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
        PackageManager.DONT_KILL_APP
    )
     }
}

Here, MyService is the component name and this can be Service or Broad cast Receiver you are already using in you app. In my case I trie with Android service

Now, this is the time to register this Application class in Manifest file. Open the manifest file and in application tag use property name and place your application class name which was just created MyApplication.

Step # 03 There is no third step. You are done. You just install the apk and by this way Service will not killed even the app is killed. I tested the above solution on Vivo device and it worked

NOTE: In case, above solution does not work, please check the manifest file for allowBackup property if you find out this property in manifest file just remove it and uninstall the app and then install the app it will work for sure and then you can set that property again.

Attach answered 21/1, 2021 at 12:5 Comment(1)
Excellent approach. But I have Xiaomi device. If I clear apps from recent apps, it will clear all data from stack then service is not starting automatically. How to restart service again?Ing
F
2

As far as I know, WhatsApp is whitelisted on the Xiaomi device autostart. There is nothing you can do about it. Of course your application will be whitelisted by Xiaomi if it eventually garnered as much as WhatsApp popularity. Until that happens, you can only asking for user to activate it manually by showing the Auto-start feature with something like this:

try {
  Intent intent = new Intent();
  if ("xiaomi".equalsIgnoreCase(android.os.Build.MANUFACTURER)) {
    intent.setComponent(new ComponentName("com.miui.securitycenter", 
          "com.miui.permcenter.autostart.AutoStartManagementActivity"));
  }

  // context is your Context
  List<ResolveInfo> list = context.getPackageManager()
                                  .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);

  if  (list.size() > 0) {
    context.startActivity(intent);
  } 

} catch (Exception e) {
  Log.d("PERMISSION", e.toString());
}

Please note, that I haven't test the code for current Xiaomi device.

Fries answered 26/3, 2018 at 1:58 Comment(5)
Thank you. But how to identify if user is already enabled manually.Chrysarobin
I didn't find the solution for it yet.Submultiple
Ok. Please let me know if you could find any solutionChrysarobin
Hi, Do you found solution if its enabled or not?Elisaelisabet
Ok Thanks for reply. But once you got solution let me know.Elisaelisabet

© 2022 - 2024 — McMap. All rights reserved.