android 解决部分手机Android系统8.0以上在锁屏状态收到消息无法在锁屏页点亮并显示消息的问题

背景介绍

最近在做IM相关的项目,产品需求是用户在线,但用户手机是息屏状态或在解锁页面的情况下收到新的消息,需要在自动点亮屏幕并显示通知样式的内容,点击消息跳转到具体的聊天界面,就像QQ或微信锁屏状态下的消息处理。

解决思路(只贴重要代码)

1.首先需要在锁屏页显示具体的消息内容,需要一个activity,此activity需要亮屏

    @Override protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        final Window win = getWindow();
        win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                //| WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);

        setContentView(R.layout.activity_alarmhandler);

        initView();

        initData();

        initEvent();
    }
    
 @Override protected void onNewIntent(Intent intent) {

        PowerManager powerManager = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
        handlerMessage(intent);
        //if (!powerManager.isScreenOn()) {
        //点亮屏幕
        PowerManager.WakeLock wl = powerManager.newWakeLock(
                PowerManager.ACQUIRE_CAUSES_WAKEUP |
                        PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "bright");
        wl.acquire(10000);
        wl.release();
        //}
    }

顺便贴下该activity的manifest,对android:taskAffinity不熟悉的同学可以自己找资料了解下,这就不科普了

<!--锁屏页面消息显示 为一个activity的taskAffinity设置一个空字符串,表明这个activity不属于任何task-->
    <activity
        android:excludeFromRecents="true"
        android:launchMode="singleInstance"
        android:taskAffinity=""
        android:theme="@android:style/Theme.Wallpaper.NoTitleBar"
        android:name=".ui.AlarmHandlerActivity"/>

2.有新消息到来,在消息处理器中用EventBus将消息告知具体activity;

  KeyguardManager mKeyguardManager = (KeyguardManager) IMApp.getInstance().getSystemService(Context.KEYGUARD_SERVICE);
                            boolean flag = mKeyguardManager.inKeyguardRestrictedInputMode();

                            if (flag) {
                                //如果flag为true,表示有两种状态:a、屏幕是黑的 b、目前正处于解锁状态
                                if (!SettingBean.getInstance().isMessageShowContentEnable()) {
                                    text = IMApp.getInstance()
                                            .getString(R.string.you_has_map_new_msg);
                                }
                                String sessionId = wrapper.conversation.getSessionId();
                                long time = wrapper.conversation.getTime();
                                ChatType chatType= wrapper.message.getChatType();
                                MsgData msgData = new MsgData();
                                msgData.setMsgContainer(text);
                                msgData.setMsgSender(userName);
                                msgData.setDate(String.valueOf(time));
                                msgData.setSessionId(sessionId);
                                msgData.setChatType(chatType.getValue());
                               }

3.在MainActivity绑定一个service,当EventBus收到新消息时通过service发送一个本地广播


    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override public void onServiceConnected(ComponentName name, IBinder service) {
            mBinder = (AlarmHandlerService.MyBinder) service;
            mBinder.getService().setDataCallback(new AlarmHandlerService.DataCallback() {
                @Override public void dataChanged(MsgData msgData) {
                    Log.d("alrict", "dataChanged: 锁屏收到消息");
                }
            });
        }

        @Override public void onServiceDisconnected(ComponentName name) {
            mBinder = null;
        }
    };

 		Intent intent = new Intent(MainActivity.this, AlarmHandlerService.class);
        bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE);

   @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEventMainThread(SreenOffMsgEvent event) {
        Log.d("llw", "onEventMainThread:锁屏状态下收到一条新消息 ");
        if (mBinder != null) {
            mBinder.setData(event.getMsgData());
        }
    }

在service中处理
重点代码 intent.addFlags(0x01000000); 为什么要设置这个flag,因为在Android8.0以后,自定义静态广播不可以在后台发送,而加这个flags,可以打破这个限制,这个是硬件编码上的一个flag值,具体没研究过

public class AlarmHandlerService extends Service {
    private String TAG = "AlarmHandlerService";
    private MsgData data;
    private DataCallback dataCallback = null;
    private AlarmHandlerReceive mHandlerReceive;
    private LocalBroadcastManager mLocalBroadcastManager;

    @Override public void onCreate() {
        super.onCreate();
    }

    @Nullable @Override public IBinder onBind(Intent intent) {
        IntentFilter filter = new IntentFilter("com.xxx.xxx");
        mHandlerReceive = new AlarmHandlerReceive();
        //注册本地接收器
        mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);
        mLocalBroadcastManager.registerReceiver(mHandlerReceive,filter);
        return new MyBinder();
    }

    public class MyBinder extends Binder {
       public AlarmHandlerService getService() {
            return AlarmHandlerService.this;
        }

        public void setData(MsgData data) {
            AlarmHandlerService.this.data = data;
            Intent intent = new Intent();
            intent.setAction("com.xxx.xxx");
            intent.putExtra("msgData", data);
            intent.addFlags(0x01000000);
            mLocalBroadcastManager.sendBroadcast(intent);
        }
    }

    public DataCallback getDataCallback() {
        return dataCallback;
    }

    public void setDataCallback(DataCallback dataCallback) {
        this.dataCallback = dataCallback;
    }

    public interface DataCallback {
        void dataChanged(MsgData msgData);
    }

    @Override public void onDestroy() {
        super.onDestroy();
        mLocalBroadcastManager.unregisterReceiver(mHandlerReceive);
    }
}

4.在receiver中处理
覆盖锁屏显示这个功能在小米手机上需要“锁屏显示”权限,目前只能用户自己开启,无法通过代码申请

public class AlarmHandlerReceive extends BroadcastReceiver {
    private String TAG = "AlarmHandler";

    @Override public void onReceive(Context context, Intent intent) {
        Log.d(TAG, "onReceive: 收到广播");
        //覆盖锁屏显示这个功能在小米手机上需要“锁屏显示”权限,目前只能用户自己开启,无法通过代码申请
        MsgData msgData = intent.getParcelableExtra("msgData");
        //拿到锁屏管理者
        KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
        if (km != null && km.isKeyguardLocked()) {   //为true就是锁屏状态下
            //启动Activity
            Intent alarmIntent = new Intent(context, AlarmHandlerActivity.class);
            alarmIntent.putExtra("msgData", msgData);
            //activity需要新的任务栈
            alarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(alarmIntent);
        }
    }
}

5.锁屏界面的代码就是第一点,xml就不贴了
如果有朋友有更好的方案,麻烦告知一声,谢谢!
至此

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值