Android - 如何在小米设备中以编程方式启用自动启动选项?

时间:2018-03-25 06:45:36

标签: android push-notification autostart

我正在开发一个Android应用程序,我想在其中显示Push通知。

除了小米手机(我正在使用Redmi Note 4)以外,它在大多数设备中都表现良好。我发现的问题是,由于Xiomi提供的自动启动选项,默认情况下会禁用,用户需要手动启用它。

但我想知道我可以看到一些Android应用程序在没有任何用户交互的情况下启用此选项Ex:WhatsApp。如果我尝试重新安装WhatsApp并查看自动启动选项,则会启用它!

我无法通过告诉我们的客户说服Xiomi喜欢设备的功能,因为他指出一些工作正常,就像我上面提到的例子。

其他人也提出了这个问题

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

但是我找不到他们的任何答案,并在这里发帖,希望有人会对此有答案。

5 个答案:

答案 0 :(得分:2)

当你从playstore下载应用程序时,自动启动功能将自动启用,如果xiaomi OS需要它,因为像amazon,google IO等应用程序也不允许自动启动,在这种情况下你必须转到安全权限 - &gt ;自动启动 - >然后从那里启用自动启动。您无法通过代码使应用程序自动启动您可以执行的是您可以显示一个对话框以启用自动启动并将用户带到自动启动活动但这不是一个好的选项,因为您无法检查自动启动是否是启用与否。 这是由MI在MIUI8中完成的,用于节省电池。这个问题浪费了我的2天XD

您可以参考this article

答案 1 :(得分:2)

  

对于小米,oppo,vivo等设备,以编程方式启用自动启动选项

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

答案 2 :(得分:2)

我知道现在分享答案为时已晚,但我会把我的两分钱放在这里,因为它非常非常重要。我浪费了 2 天的时间来挖掘这个问题。我尝试了此处提供的所有建议解决方案,但似乎没有任何效果。以下是我按以下步骤实施的解决方案:

第 1 步 创建您的前台服务,并在清单中相应地注册它。出于示例目的,我正在分享服务示例。

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

}

注意:我已经介绍了所有可能的用例来重新启动服务,以防它被操作系统杀死。如果用户重新启动手机,还剩下一件事。这种情况可以很容易地通过其他 stackoverflow 答案找到。在广播中,只需启动服务。

步骤#02 提出申请并在清单中注册。并在您的应用程序类中添加以下代码行。

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

此处,MyService 是组件名称,可以是您已在应用中使用的Service 或 Broadcast Receiver。就我而言,我尝试使用 Android 服务

现在,是时候在 Manifest 文件中注册这个 Application 类了。打开清单文件并在应用程序标记中使用属性 name 并放置您刚刚创建的应用程序类名 MyApplication

第 3 步 没有第三步。你完成了。您只需安装 apk,这样即使应用程序被杀死,服务也不会被杀死。我在 Vivo 设备上测试了上述解决方案,并且有效

注意:如果上述解决方案不起作用,请检查allowBackup属性的清单文件,如果您在清单文件中发现此属性,只需将其删除并卸载应用程序,然后安装应用程序它肯定会起作用,然后您可以再次设置该属性。

答案 3 :(得分:1)

据我所知,WhatsApp在小米设备自动启动中列入白名单。你无能为力。当然,如果小米最终获得WhatsApp的声望,那么你的应用程序将被列入白名单。在此之前,您只能通过以下内容显示自动启动功能,要求用户手动激活它:

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

请注意,我还没有测试当前小米设备的代码。

答案 4 :(得分:1)

很少有流行的应用程序在后台运行,而不会在内存清理周期中被杀死(许多流行的OEM定制堆栈ROM来优化电池/内存),因为这些制造商将它们列入“白名单”。 对于您的应用程序,您可以手动将其列入白名单(通过设备的相应“设置”),也可以通过将用户重定向到相应的设置页面以将其列入白名单而实用地列入白名单。实用上,您可以像下面这样:

  1. 在应用的清单文件中添加以下权限:`

    <uses-permission android:name="oppo.permission.OPPO_COMPONENT_SAFE"/> 
    <uses-permission android:name="com.huawei.permission.external_app_settings.USE_COMPONENT"/>`
    
  2. 将您重定向到“自动启动”设置:

    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

我已经测试了这种方法,但是它仍然可以工作,但是可靠性仍然是一个问题,因为系统需要花费一些时间(在PoccoF9和Xiomi设备上大约需要2分钟)来重新启动被终止的服务。

但是作为用户,我们可以防止该应用的后台服务被杀死,如下所示:

  1. 按“最近使用的应用”物理键(左侧按钮)。
  2. 拖动应用一次(选择,按住并向下滑动),然后点击锁定图标(如果锁定处于打开状态)以锁定应用。
  3. 该应用程序将处于锁定状态(即使您通过清除清除了后台应用程序进程,该应用程序也将继续运行)。
  4. 以同样的方式,如果要从锁定状态中删除它,只需再次向下拖动一次,锁定符号就会消失(清除后台进程也将清除应用程序的运行)。

但是,通过这种方式,在大多数设备上重启后,应用的锁定状态将被重置。

编辑: 在观察到Foreground服务的行为(在Xiomi的RedmiS3,Android V6.0上)后,下面是分析:

  1. 即使以编程方式启用了“自动启动”(通过用户干预,如上所述)之后,该服务也并非总是重启(该服务仅在少数情况下重启,但大多数情况下并未重启)。 br /> 另外,如果我在设备设置中搜索“自动启动”,则在“自动启动”列表中看不到我的应用。似乎上述方法仅提供自动启动权限,但未启用它,不确定! 而且,如果我通过设备设置将应用添加到“自动启动”列表中,我的服务将重新启动(尽管需要一些时间)。

  2. 在onTaskRemoved()回调中重新启动被终止的服务可能是另一种选择,但是当服务被终止时,该回调以令人惊讶的方式被调用。仅当通过后退键正确关闭应用程序时,才会执行此回调。如果我们最小化应用程序(暂停状态),则在服务终止时永远不会调用此回调。 (寻找原因)

最近我发现了另一种方法,可以通过GCM通知事件重新启动被终止的服务。我怀疑无论App是否在设备上被杀死,GCM是否都能正常工作(我需要检查并验证行为)。但这可以肯定是“ 这些OEM使程序员的生活变得地狱!)。