2021-06-18

android 息屏后被挂起停止运行解决

android app有很多应用场景需要在后台开启服务, 比如后台实时上传位置数据, 不停发送心跳包等等, 但是在息屏休眠后, app往往没有按照我们设想的运行. 我网上查了很多资料才总结出了一套可以运行在后台方案

  1. 设置前台服务
  2. 获取电源锁
  3. 设置service清理后自动重启
  4. 提高app优先级
  5. 设置电池优化白名单
  6. 播放无声音乐(上面都设置了但是华为android10还是不行, 加上这个才可以了. 加上这个耗电比较凶)

1. 设置前台服务

1.1 启动服务

fun startService(context: Context) {
            val intent = Intent(context, MyService::class.java)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                context.startForegroundService(intent)
            } else {
                context.startService(intent)
            }
        }

1.2 在onStartCommand中将服务设置在前台

    /**创建前台通知**/
    private fun creatNotification() {
        val channelName = "通信服务"
        val builder: Notification.Builder?
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            if (null == notificationManager) {
                notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            }
            val importance = NotificationManager.IMPORTANCE_HIGH
            val notificationChannel = NotificationChannel(CHANNEL_ID, channelName, importance)
            notificationChannel.description = channelName
            notificationChannel.enableLights(true)
            notificationChannel.lightColor = Color.BLUE
            notificationChannel.setShowBadge(true)
            notificationChannel.enableLights(true)
            notificationManager?.createNotificationChannel(notificationChannel)
            builder = Notification.Builder(applicationContext, CHANNEL_ID)
        } else {
            builder = Notification.Builder(applicationContext)
        }
        builder.setSmallIcon(AppUtils.getAppIconId()) //设置通知图标
                .setContentTitle(channelName) //设置通知标题
                .setContentText("正在后台运行") //设置通知内容
                .setAutoCancel(false) //用户触摸时,自动关闭
                .setOngoing(true) //设置处于运行状态
                .setWhen(System.currentTimeMillis())
        mNotification = builder.build()

        mNotification?.flags = Notification.FLAG_ONGOING_EVENT
        mNotification?.flags = Notification.FLAG_NO_CLEAR
        mNotification?.flags = Notification.FLAG_FOREGROUND_SERVICE
    }
//将服务设置在前台
startForeground(1, mNotification)

1.3 在onDestroy中退出前台服务

stopForeground(true)

2 获取电源锁

2.1 使用电源锁的注意事项

电源锁必须成对使用, 手机息屏那么你先获取的电源锁也会被释放, 所以我们必须监听手机的亮屏息屏广播来控制电源锁的使用

2.2 注册屏幕亮屏息屏广播

/** 注册息屏亮屏监听 start**/
private fun registReceiver() {
        val mIntentFilter = IntentFilter()
        mIntentFilter.addAction(Intent.ACTION_SCREEN_ON)
        mIntentFilter.addAction(Intent.ACTION_SCREEN_OFF)
        registerReceiver(mScreenStatusReceiver, mIntentFilter)
    }

private fun unregistReceiver() {
        unregisterReceiver(mScreenStatusReceiver)
    }

private var mScreenStatusReceiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            when (intent?.action) {
                Intent.ACTION_SCREEN_ON -> {
                    LogUtils.dTag(TAG, "亮屏")
                    stopAcquire()
                }
                Intent.ACTION_SCREEN_OFF -> {
                    LogUtils.dTag(TAG, "息屏")
                    acquire()
                }
                else -> {}
            }
        }
    }

2.3 电源锁获取和释放

/* 保持屏幕熄灭后  cpu 还一直运行 */
private var wl: PowerManager.WakeLock? = null
@SuppressLint("InvalidWakeLockTag")
private fun acquire() {
    try {
        val pm = getSystemService(Context.POWER_SERVICE) as PowerManager
        if (wl == null)
            wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, SipManagerService::class.java.name)
        wl?.acquire(10 * 60 * 60 * 1000L /*10 minutes*/)
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

//清除唤醒
private fun stopAcquire() {
    try {
        if (wl?.isHeld == true)
            wl?.release()
        wl = null
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

3 设置service清理后自动重启

在onStartCommand中返回START_STICKY

 override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
 
        return START_STICKY
    }

4 提高app优先级

在application中提高app优先级, 申请大内存, 防止内存不足时候被清理

// android:largeHeap="true" ,  android:priority="1000"
<application
        android:name=".app.App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:largeHeap="true"
        android:persistent="true"
        android:priority="1000"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

5 设置电池优化白名单

    /**
     * 忽略电池优化
     */
    @RequiresApi(Build.VERSION_CODES.M)
    fun ignoreBatteryOptimization(activity: Activity) {
        val powerManager = getSystemService(POWER_SERVICE) as PowerManager
        val hasIgnored = powerManager.isIgnoringBatteryOptimizations(activity.packageName)
        //  判断当前APP是否有加入电池优化的白名单,如果没有,弹出加入电池优化的白名单的设置对话框。
        if (hasIgnored.not()) {
            val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
            intent.data = Uri.parse("package:" + activity.packageName)
            startActivity(intent)
        }
    }

6 播放无声音乐

6.1 在onCreate中播放无声音乐

private var mMediaPlayer: MediaPlayer? = null

    // 开始播放无声音乐
    private fun startMediaPlayer() {
        mMediaPlayer = MediaPlayer.create(this.applicationContext, R.raw.silent_music)
        mMediaPlayer?.isLooping = true
        if (mMediaPlayer?.isPlaying?.not() == true) {
            mMediaPlayer?.start()
        }

    }

6.2 在onDestroy中停止播放音乐

private fun stopMediaPlayer() {
        mMediaPlayer?.stop()
        mMediaPlayer?.release()
        mMediaPlayer = null
    }

代码片段+无声音乐下载地址: 传送门

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值