【Android】App锁屏或者切到后台,调起服务;切换到前台,终止服务(针对声网聊天室声音采集问题处理)

一、应用场景

1、声网集成聊天室,锁屏或者后台,手机采集声音异常。对方听不到本人说话。

原因是:Android 9 设备,应用锁屏或切后台后一分钟内音频采集无效。从 Android 官网来看,这是系统强制限制。原文如下:

Limited access to sensors in background
Android 9 limits the ability for background apps to access user input and sensor data. If your app is running in the background on a device running Android 9, the system applies the following restrictions to your app:

  • Your app cannot access the microphone or camera.
  • Sensors that use the continuous reporting mode, such as accelerometers and gyroscopes, don’t receive events.
  • Sensors that use the on-change or one-shot reporting modes don’t receive events. If your app needs to detect sensor events on devices
    running Android 9, use a foreground service.

详见 Android 行为变更

2、解决方案: 目前 Android 官网没有明确说明后台采集声音或视频应如何处理,但使用前台服务可以让应用正常工作。
如果 Android 9 设备用户有锁屏后采集音频或视频的需求,可以在锁屏或退至后台前起一个 Service,并在退出锁屏或返回前台前终止 Service。

二、解决办法

1、监听app锁屏或切后台,以及切换到前台

我们这里直接贴出代码,具体的可以参考这篇文章:监听app锁屏或切后台,以及切换到前台

import android.app.Activity;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

/**
 * Describe: 监听app锁屏或切后台
 * Created by Gao Chunfa on 2020/3/19.
 * Company: Hainan DaDi(Jinan) Network Technology Co. Ltd
 */
class ActivityLifecycleListener implements Application.ActivityLifecycleCallbacks {

    private int activityCount = 0;
    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {

    }
    @Override
    public void onActivityStarted(Activity activity) {
        activityCount++;
        getAppStatus();
    }
    @Override
    public void onActivityResumed(Activity activity) {

    }
    @Override
    public void onActivityPaused(Activity activity) {

    }
    @Override
    public void onActivityStopped(Activity activity) {
        activityCount--;
        getAppStatus();
    }
    @Override
    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {

    }
    @Override
    public void onActivityDestroyed(Activity activity) {

    }
    /**
     * 根据activityCount,判断app状态
     */
    public void getAppStatus() {
        if (activityCount == 0) {
            //App进入后台或者APP锁屏了
            //开启服务
        } else {
            //App进入前台
            //结束服务
        }
    }   
}
2、创建前台服务

在Android 8.0 中谷歌对后台service进行了严格限制,不允许默默无闻的后台service存在,若想用service,必须以startForegroundService的方式启动service,对所启动Service进行通知处理(Google对Android8.0之后进行的强制处理),并且必须在service内部5s内执行startForeground方法显示一个前台通知,否则会产生ANR或者crash。

因此我们需要在启动服务的地方根据版本判断是调用startForegroundService()或者startService()函数;

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
     //android8.0以上通过startForegroundService启动service
     startForegroundService(new Intent(MainActivity.this,MyService.class));
 }else{
     startService(new Intent(MainActivity.this, MyService.class));
     }

同时注意:应用必须在创建服务后的五秒内调用该服务的 startForeground() 函数。
因此我们在创建服务后,在onCreate()方法中调用该方法(startForeground)

public class MyService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
       startForeground(1,notification());
    }
}

服务的全部代码如下:

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.IBinder;
import android.support.annotation.Nullable;
import net.liexiang.dianjing.R;

/**
 * Describe: app后台后启动一个服务
 * Created by Gao Chunfa on 2020/3/19.
 * Company: Hainan DaDi(Jinan) Network Technology Co. Ltd
 */
public class KeepAppLifeService extends Service {
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private NotificationManager notificationManager;
    private String notificationId   = "keep_app_live";
    private String notificationName = "APP后台运行中";

    @Override
    public void onCreate() {
        super.onCreate();
        notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        //创建NotificationChannel
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(notificationId, notificationName, NotificationManager.IMPORTANCE_HIGH);
            //不震动
            channel.enableVibration(false);
            //静音
            channel.setSound(null, null);
            notificationManager.createNotificationChannel(channel);
        }
        //创建服务后,五秒内调用该方法
        startForeground(1, getNotification());

    }

    /**
     * 获取通知(Android8.0后需要)
     * @return
     */
    private Notification getNotification() {
        Notification.Builder builder = new Notification.Builder(this)
                .setSmallIcon(R.mipmap.ic_logo)
                .setContentTitle("伙玩")
                .setContentIntent(getIntent())
                .setContentText("后台运行中");
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            builder.setChannelId(notificationId);
        }
        return builder.build();
    }

    /**
     * 点击后,直接打开app(之前的页面),不跳转特定activity
     * @return
     */
    private PendingIntent getIntent() {
        Intent msgIntent = getApplicationContext().getPackageManager().getLaunchIntentForPackage(getPackageName());//获取启动Activity
        PendingIntent pendingIntent = PendingIntent.getActivity(
                getApplicationContext(),
                1,
                msgIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);

        return pendingIntent;
    }
}

注意:
如果想通知栏点击后,直接打开app(之前的页面),不跳转特定activity
需要在启动Activity中的onCreate方法中加上如下代码
否则每次home键都会回到首页

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (!isTaskRoot()) {
           finish();
           return;
        }
    }

大功告成~~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值