仿新版QQ锁屏下弹窗

首先,先感谢下: "貌似掉线"朋友,我在上这一个项目中也用到了这个功能,看了他写的博客后基本实现了我想要的。之所以说是“基本实现”,是因为还差一点,“貌似掉线”朋友博客上没有设置弹出窗的背景为当前手机的壁纸代码段,这里我来加上来:

新版的qq,可以在锁屏下弹窗显示qq消息,正好目前在做的项目也需要这一功能。经过各种试验和资料查找,终于实现,过程不难,但是却有一些地方需要注意。

下面是实现过程。

1.使用Activity,而不是View

QQ的弹窗一开始我以为是悬浮View,用WindowManager去添加,但是无论如何就是不显示,后来在朋友提示下换成Activity来实现,在锁屏状态下就能弹窗了。

2.Activity的设置

Activity需要进行以下设置,才可以在锁屏状态下弹窗。
首先是onCreate方法,需要添加4个标志,如下:
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. protected void onCreate(Bundle savedInstanceState) {  
  2.     super.onCreate(savedInstanceState);  
  3.     final Window win = getWindow();  
  4.     win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED  
  5.             | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD  
  6.             | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON  
  7.             | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);  
  8.   //设置背景为当前手机的壁纸
  9. LinearLayout layout = (LinearLayout) findViewById(R.id.lineLayout);
    WallpaperManager manager = WallpaperManager.getInstance(this);
    Drawable drawable = manager.getDrawable();
    layout.setBackground(drawable);
  10.     // 自己的代码  
  11. }  


四个标志位顾名思义,分别是锁屏状态下显示,解锁,保持屏幕长亮,打开屏幕。这样当Activity启动的时候,它会解锁并亮屏显示。
然后在AndroidManifest.xml文件当中,对该activity的声明需要加上以下属性:
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <activity android:name=".alarm.AlarmHandlerActivity"  
  2.           android:launchMode="singleInstance"  
  3.           android:excludeFromRecents="true"  
  4.           android:taskAffinity=""  
  5.           android:theme="@android:style/Theme.Wallpaper.NoTitleBar"/>  

而对于布局文件,要显示的view居中,背景透明。由于上面已经设置了背景为壁纸的背景,所以显示的是桌面的背景。如果背景设为默认的白色,则导致弹窗后面是一片白色,看起来很丑。如果背景设置为透明,则弹窗后面会显示出解锁后的界面(即使有锁屏密码,也是会显示解锁后的界面的),一样很影响视觉效果。

3.在广播中启动锁屏弹窗

我们设置的是锁屏下才弹窗的,非锁屏下就不适合弹出这个窗口了(你可以试一下,效果会很怪)。一般是注册一个广播接收器,在接收到指定广播之后判断是否需要弹窗,所以在BroadcastReceiver的接收代码中需要先判断是否为锁屏状态下:
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1.     @Override  
  2.     public void onReceive(Context context, Intent intent) {  
  3.         Log.d(LOG_TAG, intent.getAction());  
  4.         KeyguardManager km = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);  
  5.         if (km.inKeyguardRestrictedInputMode()) {  
  6.             Intent alarmIntent = new Intent(context, AlarmActivity.class);  
  7.             alarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  8.             context.startActivity(alarmIntent);  
  9.         }  
  10.     }  

这里用到的是KeyguardManager类,用来管理锁屏的,4.1之后该类的API新增了一个isKeyguardLocked()的方法判断是否锁屏,但在4.1之前,我们只能用inKeyguardRestrictedInputMode()方法,如果为true,即为锁屏状态。需要注意的是,在广播中启动Activity的context可能不是Activity对象,所以需要添加NEW_TASK的标志,否则启动时可能会报错。

4.更新弹窗信息

如果弹窗Activity本身并不主动更新信息,当有新的信息来时需要更新Activity的界面,由于在上面我们设的是singleInstance启动模式,所以需要覆写onNewIntent(Intent intent)方法,这样当再次启动这个activity时,新的intent会在该方法中传入。

5.再次亮起屏幕

如果该Activity并未退出,但是被手动按了锁屏键,当前面的广播接收器再次去启动它的时候,屏幕并不会被唤起,所以我们需要在activity当中添加唤醒屏幕的代码,这里用的是电源锁。可以添加在onNewIntent(Intent intent),因为它会被调用。也可以添加在其他合适的生命周期方法。添加代码如下:
[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);  
  2. if (!pm.isScreenOn()) {  
  3.     PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP |  
  4.             PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "bright");  
  5.     wl.acquire();  
  6.     wl.release();  
  7. }  

6.一些权限

下面是实现过程中需要的一些权限,由于我是从项目代码中抽取出来的,难免多加或遗漏,开发者自己注意一下:
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <uses-permission android:name="android.permission.DISABLE_KEYGUARD"/>  
  2. <uses-permission android:name="android.permission.WAKE_LOCK"/>  
原文出处: http://blog.csdn.net/maosidiaoxian/article/details/40587935
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值