本博文是根据http://blog.csdn.net/killer991684069/article/details/53096588所改编,加以具体说明所创作,如果想看原文请点击链接,原文中有demo大家可以下载运行看效果
本博文讲述的是自定义的是自定义的提醒样式,但是如果光做提醒的话也就几行代码在广播broadCastReceive的onReceive()中添加一下代码即可,但是部分手机接收不到推送,比如说oppo大部分机型等,需要手动开启
KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
if (km.inKeyguardRestrictedInputMode()) {
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (!pm.isScreenOn()) {
PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP |
PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "bright");
wl.acquire();
wl.release();
}
}
博主最近领导发了新需求需要在锁屏上显示提示框,网上找了很多博客,基本都是一抹一样照抄的,一点责任心都没有,有的连博主寄语也抄上了,我也是服了那些人,后来找到了个这个博主的博客写的还可以,那么就可以实现锁屏提示框的效果,具体效果图如下:
然后第一个想到的就是利用windowsManager去做,然后挣扎了一天多确实做出来的,但是当
layoutParams.type = WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
设置的时候就涉及到权限的问题了,但是当然你也可以不用TYPE_KEYGUARD_DIALOG这个属性TYPE_TOAST等都可以不过这几个属性无法获取焦点,就是无法做到点击等跳转事件,因此我感觉失败了,因为他总是报一个错,权限不合法,或不存在,
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
这个权限属于系统最高级别的权限很难获取到,即使你在设置中去手动设置,或者代码中动态注册,也不行,机型的不同还是可能失败,那么没有这个权限windowsManager做的锁屏提示框就无法使用。
废话说了不少了,那么我们可以进入正题代码部分了。
1、首先我们这个弹出的提示框是利用单独的activity去实现的不是一个view,我们需要在setContentView(R.layout.activity_main);前面上下面代码,用户锁屏亮屏的检测
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
);
2 获取手机当前壁纸
我们知道QQ在锁屏弹窗的时候其背景跟我们的壁纸是一致的,这里准确说来是和桌面上的壁纸一致。
这里就需要用到壁纸管理器:
public Bitmap getWallPaper() { WallpaperManager wallpaperManager = WallpaperManager .getInstance(MainActivity.this); // 获取当前壁纸 Drawable wallpaperDrawable = wallpaperManager.getDrawable(); Bitmap bm = ((BitmapDrawable) wallpaperDrawable).getBitmap(); int heightPixels = getResources().getDisplayMetrics().heightPixels; int widthPixels = getResources().getDisplayMetrics().widthPixels; int with = bm.getHeight()*widthPixels/heightPixels > bm.getWidth() ? bm.getWidth():bm.getHeight()*widthPixels/heightPixels; Bitmap pbm = Bitmap.createBitmap(bm, 0, 0, with, bm.getHeight()); // 设置 背景 return pbm; }
获取到的壁纸直接加载到当前的activity上,作为其背景图片:
@Override public void onAttachedToWindow() { super.onAttachedToWindow(); if (true) { final View view = getWindow().getDecorView(); final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) view.getLayoutParams(); lp.gravity = Gravity.CENTER; // lp.width = getResources().getDisplayMetrics().widthPixels / 2; // lp.height = getResources().getDisplayMetrics().heightPixels / 3; if (Build.VERSION.SDK_INT >= 16) { view.setBackground(new BitmapDrawable(getWallPaper())); } else { view.setBackgroundColor(Color.WHITE); } getWindowManager().updateViewLayout(view, lp); } }
3 监听屏幕状态/锁屏/解锁/亮屏
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("ndh--","onStartCommand");
/* 注册屏幕唤醒时的广播 */
IntentFilter intentenfilter = new IntentFilter();
intentenfilter.addAction(Intent.ACTION_SCREEN_ON);
intentenfilter.addAction(Intent.ACTION_SCREEN_OFF);
intentenfilter.addAction(Intent.ACTION_USER_PRESENT);
receiver = new ScreenStateReceiver();
registerReceiver(receiver, intentenfilter);
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d("ndh--", "action=" + action);
if (Intent.ACTION_SCREEN_ON.equals(action)) { // 开屏
ScreenStateManager.screenState=1;
Log.d("ndh--", "screen on");
} else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 锁屏
ScreenStateManager.screenState=-1;
Log.d("ndh--", "screen off");
Intent intent1 = new Intent(context, MainActivity.class);
intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent1);
} else if (Intent.ACTION_USER_PRESENT.equals(action)) { // 解锁
ScreenStateManager.screenState=0;
Log.d("ndh--", "user_present");
}
}
}
PS 可能真正的场景是,有一条通知到来,然后我们判断一下当前的屏幕活动状态,如果是亮屏,挂载普通界面,如果是锁屏则挂载特制的锁屏Activity界面。这里判断屏幕是否处于活动状态
事例代码地址:https://github.com/killer8000/popup-window-on-lock-screen
我根据博主的demo改了下,我们可以融入推送中,在我们接受到推送的时候,启动,锁,屏提示框的activity并且把推送信息保存至shareprefence中,在锁屏界面中展示后获取保存的信息,展示出来,这样做是以防用户没看下次接着展示,当用户解锁了或者点击了推送消息的话我们就可以删除本地保存,在用户查看后一定要清除本地保存本地保存的信息。如果有不懂的可以下面留言尽快回答,