Android 小问题汇总(2)

作者: zcwfeng | 来源:发表于2022-05-24 14:30 被阅读0次

    <持续更新中>:更新目录

      1. 声网后台保活策略和IntentService使用回调监听,解决Android 临时后台任务问题

    声网类似问题,就是直播中关于声网退到后台无法发出声音,类似声网保活问题。从而引发创建后台,startForegroundService的问题如下:

    Android 8.0以上如果使用service就会报“ Context.startForegroundService() did not then call Service.startForeground()”这个错,是因为Google限制了在调用了startForegroundService方法以后,5s内一定要调用startForeground方法,但是这个其实很难杜绝,因为每台设备情况不一样,如果手机卡一点,很可能就卡过这5s了,所以我们只能尽量减少。

    1.不要在fragment里启动service,建议在mainActivity里启动,并且要成对的start和stop,在onDestroy()里stop。

    2.在onCreate和onStartCommand都startForeground(),并且id不要用0。

    网上的几点意见都用了但是还是在华为手机,出现偶发崩溃,因为华为强制杀死后台的系统机制,让人还是挺头大的。给出我的方案,但是很多问题

    1. 由于Serveice不稳定,而且开启后台杀死困难,所以选择用IntentService替代

    /**
     * 后台服务,用于保持语音房,在后台服务不被回收
     */
    class KeepAppLifeService : IntentService("KeepAppLifeService") {
    
        override fun onHandleIntent(intent: Intent?) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                // 注意notification也要适配Android 8 哦
                startForeground(1, getNotification())
            }
            // 静音
            FSAudioManager.getInstance()
                .sound(SPUtils.getInstance().getBoolean(SPUtils.SwitchRef.IS_OPEN_SOUND, false))
    
            //麦位静音处理
            val user = AudioRoomManager.getInstance().userStates
            user.entries.forEach {
                if (it.value.isShut) {
                    FSAudioManager.getInstance().soundOne(it.key.toInt(), true)
                }
            }
        }
    
        private var notificationManager: NotificationManager? = null
        private val notificationId = "keep_app_live"
        private val notificationName = "keep_app_live_channel"
    
        override fun onCreate() {
            super.onCreate()
            notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager
            //创建NotificationChannel
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val channel = NotificationChannel(
                    notificationId,
                    notificationName,
                    NotificationManager.IMPORTANCE_HIGH
                )
                //不震动
                channel.enableVibration(false)
                //静音
                channel.setSound(null, null)
                notificationManager?.createNotificationChannel(channel)
                startForeground(1, getNotification())
            }
        }
    
        /**
         * 获取通知(Android8.0后需要)
         */
        private fun getNotification(): Notification? {
            val builder: Notification.Builder = Notification.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle(getString(R.string.app_name))
                .setContentIntent(getIntent())
                .setContentText(getString(R.string.text_on_keep_live))
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                builder.setChannelId(notificationId)
            }
            return builder.build()
        }
    
        /**
         * 点击后,直接打开app(之前的页面),不跳转特定activity
         */
        @SuppressLint("UnspecifiedImmutableFlag")
        private fun getIntent(): PendingIntent? {
            val msgIntent =
                applicationContext.packageManager.getLaunchIntentForPackage(packageName) //获取启动Activity
            return PendingIntent.getActivity(
                applicationContext,
                1,
                msgIntent,
                PendingIntent.FLAG_UPDATE_CURRENT
            )
        }
    }
    

    2. 启动和关闭时机

    通常我们需要一个这样的Activity管理和Application回掉

    /**
     * -----------
     * Activity生命周期监听管理
     * 在Application进行注册
     * 包括功能:Activity活动列表管理,退出App
     */
    public class ActivityLifecycleCallback implements Application.ActivityLifecycleCallbacks
    

    根据这个我们就可以做计数,判断在前台还是后台操作

    /**
         * 根据getAppStatus,判断app状态
         */
        public void getAppStatus(Activity activity) {
            if (isForget == 0) {
                //App进入后台或者APP锁屏了
                //开启服务
                LogUtils.i("KeepAppLifeService:开启服务");
                //当前房间id
                long roomId = AudioRoomManager.getInstance().getRoomId();
                //如果当前在房间中 并且房间id != -1 开启服务
                if(roomId != -1 && AudioRoomManager.getInstance() != null && AudioRoomManager.getInstance().isInRoom()){
                    if(App.getInstance() != null) {
                        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O){
                            App.getInstance().startForegroundService(new Intent(activity, KeepAppLifeService.class));
                        }else{
                            App.getInstance().startService(new Intent(activity, KeepAppLifeService.class));
                        }
                    }
    
                }
            } else {
                //App进入前台
                //结束服务
                //停止Service
                try {
                    LogUtils.i("KeepAppLifeService:结束服务");
                    Intent intentFour = new Intent(activity, KeepAppLifeService.class);
                    activity.stopService(intentFour);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    

    相关文章

      网友评论

        本文标题:Android 小问题汇总(2)

        本文链接:https://www.haomeiwen.com/subject/otvjprtx.html