android app后台运行

Android app后台运行可行方案

需求由来

最近一个项目由于特殊原因,好几个不懂技术的人来当甲方,人人都是产品经理,没有项目经理,功能和实现细节要自己想自己定,再加上个比较无语的**(代码逻辑和实现方案让你吃惊),具体就不吐槽了。把自己得事情做好,把心态放平稳些。

我的印象里让应用后台保持运行这个功能一直都被提过。。。这个功能真的让人心烦,也让用户心烦,反正我得手机上如果我发现有这样得没有必要得应用,我都会干掉他。

方案

应用后台保活,后台运行,长时间后台任务这些说法,目前我接触到最靠谱得还是通过系统提供的方式,那些启动各种服务等等的都不行;如果要是设备上的系统应用的话(使用mtk或者其他厂商的原生android系统),那只通过启动服务,广播这些就可以帮你完成大部分需求,适量添加接下来的功能;如果要是安装到手机的普通应用的话,还是需要系统和厂家提供的方式最靠谱,但也有一些弊端,需要引导用户去设置。

代码实现

1: 忽略电池优化:
有些手机设置这一项就可以达到系统不清理当前应用的效果,例如我这个三星测试机;调用后会有系统的弹窗,api在23及以上,提供查询api和弹窗设置;代码如下
// 权限
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />

// 查询是否允许
@RequiresApi(api = Build.VERSION_CODES.M)
fun isIgnoringBatteryOptimizations(context: Context): Boolean {
    var isIgnoring = false
    val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager?
    if (powerManager != null) {
        isIgnoring = powerManager.isIgnoringBatteryOptimizations(context.packageName)
    }
    return isIgnoring
}

// 通过系统弹窗让用户设置
@RequiresApi(api = Build.VERSION_CODES.M)
fun requestIgnoreBatteryOptimizations(context: Context) {
    try {
        val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
        intent.data = Uri.parse("package:" + context.packageName)
        context.startActivity(intent)  // 此处如需要回调的话那就使用另一种方式开启
    } catch (e: java.lang.Exception) {
        e.printStackTrace()
    }
}
2:通过各自手机厂商的系统应用去管理当前应用可后台运行;引导用户去设置时需要提示用户如何操作,不管是弹窗也好,开启页面图文说明也好总是是要提示用户的;我这里就简单通过弹窗来提示操作;我分为两部分,前部分为统一的,就是为啥需要开启这些,给用户说明一下;另一部分就是针对不同厂家的手机做不同的提示说明了。如下代码
/**
* 相关的描述看里面注释,自己照着可以做适当修改
*/
fun getDesc(context: Context): String {
	// 这个描述简单说明下为什么需要开启这些设置;后面再加个换行符
    val baseDesc = context.resources.getString(R.string.permissionsutil_getdesc_desc_top)
    if (RomUtils.isHuawei()) {
    	//关闭应用的自动管理,设置允许后台活动和自启动
        return baseDesc + context.resources.getString(R.string.permissionsutil_getdesc_desc_huawei)
    } else if (RomUtils.isXiaomi()) {
    	//授权管理 -> 自启动管理 -> 允许应用自启动和后台活动
        return baseDesc + context.resources.getString(R.string.permissionsutil_getdesc_desc_xiaomi)
    } else if (RomUtils.isOppo()) {
    	//授权管理 -> 自启动管理 -> 允许应用自启动和后台活动
        return baseDesc + context.resources.getString(R.string.permissionsutil_getdesc_desc_oppo)
    } else if (RomUtils.isVivo()) {
    	//权限管理 -> 自启动 -> 允许应用自启动和后台活动
        return baseDesc + context.resources.getString(R.string.permissionsutil_getdesc_desc_vivo)
    } else if (RomUtils.isMeizu()) {
    	//权限管理 -> 后台管理 -> 允许应用后台运行
        return baseDesc + context.resources.getString(R.string.permissionsutil_getdesc_desc_meizu)
    } else if (RomUtils.isSamsung()) {
    	//自动运行应用程序 -> 打开应用开关;设置应用可后台运行相关选项
        return baseDesc + context.resources.getString(R.string.permissionsutil_getdesc_desc_samsung)
    } else if (RomUtils.isLeeco()) {
    	//自启动管理 -> 允许应用自启动
        return baseDesc + context.resources.getString(R.string.permissionsutil_getdesc_desc_leeco)
    } else if (RomUtils.isSmartisan()) {
    	//权限管理 -> 自启动权限管理;设置应用可后台运行相关选项
        return baseDesc + context.resources.getString(R.string.permissionsutil_getdesc_desc_smartisan)
    } else {
        return baseDesc
    }
}

在弹窗里引导用户去设置后代码如下:

fun showActivity(context: Context, packageName: String) {
    val launchIntentForPackage = context.packageManager.getLaunchIntentForPackage(packageName)
    context.startActivity(launchIntentForPackage)
}

fun showActivity(context: Context, packageName: String, activityDir: String) {
    val intent = Intent().apply {
        component = ComponentName(packageName, activityDir)
        addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    }
    context.startActivity(intent)
}

fun showActivityForMeizu(context: Context){
    val intent = Intent()
    val unflattenFromString = ComponentName.unflattenFromString("com.meizu.safe.permission.PermissionMainActivity")
    intent.setComponent(unflattenFromString)
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
    context.startActivity(intent)
}


fun showDetailActivity(context: Context){
    val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
        setData(Uri.fromParts("package",context.packageName,null))
    }
    context.startActivity(intent)
}

下面代码里有很多打印和异常处理,根据自己需要修改,可以试试自己的测试机跳的页面对不对,如果不对通过adb找对应的路径。 做下异常处理 下面的代码有些机型没有测试,最后出异常直接跳到应用详情里去

fun checkBackgroundPermission(context: Context) {
    if (isHuawei()) { // 应用启动管理 -> 关闭应用开关 -> 打开允许自启动
        LogUtil.e("checkBackgroundPermission", "isHuawei")
        try {
            showActivity(context,
                    "com.huawei.systemmanager",
                    "com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity")
        } catch (e: Exception) {
            LogUtil.e("checkBackgroundPermission", "isHuawei e: " + e.message)
            try {
                showActivity(context,
                        "com.huawei.systemmanager",
                        "com.huawei.systemmanager.optimize.bootstart.BootStartActivity")
            } catch (e: Exception) {
                showDetailActivity(context)
            }
        }
    } else if (isXiaomi()) { // 授权管理 -> 自启动管理 -> 允许应用自启动
        LogUtil.e("checkBackgroundPermission", "isXiaomi")
        try {
            showActivity(context,
                    "com.miui.securitycenter",
                    "com.miui.permcenter.autostart.AutoStartManagementActivity")
        } catch (e: Exception) {
            LogUtil.e("checkBackgroundPermission", "isXiaomi e: " + e.message)
            showDetailActivity(context)
        }
    } else if (isOppo()) { // 权限隐私 -> 自启动管理 -> 允许应用自启动
        LogUtil.e("checkBackgroundPermission", "isOppo")
        try {
            showActivity(context, "com.coloros.phonemanager")
        } catch (e: Exception) {
            LogUtil.e("checkBackgroundPermission", "isOppo e: " + e.message)
            try {
                showActivity(context, "com.coloros.oppoguardelf")
            } catch (e: Exception) {
                try {
                    showActivity(context, "com.coloros.safecenter")
                } catch (e: Exception) {
                    showDetailActivity(context)
                }
            }
        }
    } else if (isVivo()) { // 权限管理 -> 自启动 -> 允许应用自启动
        try {
            if (Build.VERSION.SDK_INT >= 26) {
                showActivity(context, "com.vivo.permissionmanager", "com.vivo.permissionmanager.activity.PurviewTabActivity")
            } else {
                showActivity(context, "com.iqoo.secure", "com.iqoo.secure.ui.phoneoptimize.SoftwareManagerActivity")
            }
        } catch (e: Exception) {
            LogUtil.e("checkBackgroundPermission", "isVivo e: " + e.message)
            try {
                showActivity(context, "com.iqoo.secure")
            } catch (e: Exception) {
                showDetailActivity(context)
            }
        }

    } else if (isMeizu()) { // 权限管理 -> 后台管理 -> 点击应用 -> 允许后台运行
        LogUtil.e("checkBackgroundPermission", "isMeizu")
        try {
            showActivity(context, "com.meizu.safe")
        } catch (e: Exception) {
            LogUtil.e("checkBackgroundPermission", "isMeizu e: " + e.message)
            try {
                showActivityForMeizu(context)
            } catch (e: Exception) {
                showDetailActivity(context)
            }
        }
    } else if (isSamsung()) { // 自动运行应用程序 -> 打开应用开关 -> 电池管理 -> 未监视的应用程序 -> 添加应用
        LogUtil.e("checkBackgroundPermission", "isSamsung")
        try {
            showActivity(context, "com.samsung.android.sm_cn")
        } catch (e: Exception) {
            LogUtil.e("checkBackgroundPermission", "isSamsung e: " + e.message)
            try {
                showActivity(context, "com.samsung.android.sm")
            } catch (e: Exception) {
                showDetailActivity(context)
            }
        }
    } else if (isLeeco()) { // 自启动管理 -> 允许应用自启动
        LogUtil.e("checkBackgroundPermission", "isLeeco")
        try {
            showActivity(context,
                    "com.letv.android.letvsafe",
                    "com.letv.android.letvsafe.AutobootManageActivity")
        } catch (e: Exception) {
            LogUtil.e("checkBackgroundPermission", "isLeeco e: " + e.message)
            showDetailActivity(context)
        }
    } else if (isSmartisan()) { // 权限管理 -> 自启动权限管理 -> 点击应用 -> 允许被系统启动
        LogUtil.e("checkBackgroundPermission", "isSmartisan")
        try {
            showActivity(context, "com.smartisanos.security")
        } catch (e: Exception) {
            LogUtil.e("checkBackgroundPermission", "isSmartisan e: " + e.message)
            showDetailActivity(context)
        }
    }
}

基本就这些了,各位可以自己copy下来调试调试。可以参考下下面这篇文章,当时特意下了悦跑圈来看这个应用怎么实现的,也感谢作者的开源精神。添加链接描述
https://juejin.im/post/6844904023955341319

  • 2
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Android系统为了优化功耗和资源管理,会在一定条件下限制后台运行应用。但是,如果我们开发的应用需要在后台长时间运行,可以通过以下几种方法来实现: 1. 前台服务(Foreground Service):前台服务是一种优先级较高的服务,可以将应用置于可见状态,使其在后台长时间运行。通过在service的onCreate方法调用startForeground方法,将服务设置为前台服务,同时在通知栏显示一个通知,以提醒用户该服务正在运行。 2. jobScheduler:JobScheduler是一种用于调度后台任务执行的系统服务。通过创建一个JobScheduler任务,指定任务的执行条件和周期,系统会在合适的时间执行任务。可以使用setPersisted方法来设置任务在设备重启后继续执行。 3. WorkManager:WorkManager是一个用于管理后台任务调度的库。可以使用WorkManager来执行需要在后台长时间运行的任务,并且提供了灵活的任务调度和管理功能。WorkManager利用了JobScheduler或AlarmManager来实现后台任务的调度,并且可以保证任务的持久性。 4. AlarmManager:AlarmManager是一种能够在指定时间触发特定操作的系统服务。我们可以使用AlarmManager来设置一个定时的任务,利用setRepeating方法来指定任务的循环周期。 需要说明的是,为了提高用户体验和遵守系统限制,我们在使用这些方法时,需要合理设置任务的优先级,避免对系统资源的滥用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值