【Android】Android屏幕状态操作
目录结构:
最近笔者在做一个功能,就是实现Android程序在锁屏后可以继续运行,笔者在网上查了一些资料,现在整理出来,希望能够对你有所帮助。
1.如何监听屏幕锁屏
监听屏幕锁屏可以通过如下方式来实现,直接通过代码来判定,或通过监听器来实现
如何实现Android程序在手机锁屏后继续运行
1)通过代码来判定屏幕的锁屏状态
可以通过PowerManager的isScreenOn方法,代码如下:
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); //如果为true,则表示屏幕“亮”了,否则屏幕“暗”了。 boolean isScreenOn = pm.isScreenOn();
这里需要解释一下:
屏幕“亮”,表示有两种状态:a、未锁屏 b、目前正处于解锁状态 。这两种状态屏幕都是亮的;
屏幕“暗”,表示目前屏幕是黑的 。
通过KeyguardManager的inKeyguardRestrictedInputMode方法,也可以实现判断屏幕的锁屏状态
KeyguardManager mKeyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); boolean flag = mKeyguardManager.inKeyguardRestrictedInputMode();
对flag进行一下说明,经过试验,总结为:
如果flag为true,表示有两种状态:a、屏幕是黑的 b、目前正处于锁屏状态 。
如果flag为false,表示目前未锁屏
当然也可以通过反射的方式来调用上面的两种方法:
Method mReflectScreenState; try { mReflectScreenState = PowerManager.class.getMethod(isScreenOn, new Class[] {}); PowerManager pm = (PowerManager)
context.getSystemService(Activity.POWER_SERVICE); boolean isScreenOn= (Boolean) mReflectScreenState.invoke(pm); } catch (Exception e) { e.printStackTrace()
2)通过监听器来判定屏幕的锁屏状态
当安卓系统锁屏或者屏幕亮起,或是屏幕解锁的时候,系统内部都会发送相应的广播,我们只需要对广播进行监听就可以了
注册广播的伪代码如下:
ScreenBroadcastReceiver mScreenReceiver; class ScreenBroadcastReceiver extends BroadcastReceiver { String action = null; @Override public void onReceive(Context context, Intent intent) { action = intent.getAction(); if (Intent.ACTION_SCREEN_ON.equals(action)) { // 开屏 } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 锁屏 } else if (Intent.ACTION_USER_PRESENT.equals(action)) { // 解锁 } } } private void startScreenBroadcastReceiver() { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_USER_PRESENT); context.registerReceiver(mScreenReceiver, filter); }
2.如何实现手机屏幕在锁屏后继续运行
在上面我们知道了如何监听屏幕的状态,接下要实现如何在屏幕关闭后程序不停止运行。关于这个功能,笔者在网上搜索了一些资料,Android的WakeLock机制就是其中一种,使用Android的service也可以。但是经过笔者的测试发现效果都不太理想,对于Android版本的兼容性不强,笔者的Android4.4可以支持,但是Android6.0经过测试发现却不支持。
下面笔者介绍一种万能方法,在这里感谢知乎给我提出的意见(听说是QQ锁屏的黑科技呢)。
就是在屏幕锁屏的时候,跳转到另一个界面,该界面只有一个像素点。
代码如下:
MainActivity.java
package org.screenlock.main; import java.lang.reflect.Method; import java.util.Date; import java.util.Timer; import java.util.TimerTask; import com.example.screenlocktest.R; import android.os.Build; import android.os.Bundle; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.app.Activity; import android.app.KeyguardManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.graphics.PixelFormat; import android.text.format.Time; import android.util.DisplayMetrics; import android.util.Log; import android.view.Gravity; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { Context context = null; Intent mintent=null; static Activity mactivity=null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); this.context = this; mintent=new Intent(this,SinglePixelActivity.class); startScreenBroadcastReceiver(new ScreenBroadcastReceiver()); Timer timer=new Timer(); TimerTask timerTask=new TimerTask() { @Override public void run() { Log.i("info", new Date().toString()); } }; timer.schedule(timerTask, 0,10* 1000);//每10秒钟运行一次,用于观察程序是否在运行 } /** * 注册屏幕广播 */ private void startScreenBroadcastReceiver(ScreenBroadcastReceiver mScreenReceiver) { IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_SCREEN_ON); filter.addAction(Intent.ACTION_SCREEN_OFF); filter.addAction(Intent.ACTION_USER_PRESENT); context.registerReceiver(mScreenReceiver, filter); } private class ScreenBroadcastReceiver extends BroadcastReceiver { private String action = null; @Override public void onReceive(Context context, Intent intent) { action = intent.getAction(); if (Intent.ACTION_SCREEN_ON.equals(action)) { // 开屏 Log.i("info", "开屏"); finishScreenActivity(); } else if (Intent.ACTION_SCREEN_OFF.equals(action)) { // 锁屏 Log.i("info", "锁屏"); startScreenActivity(); } else if (Intent.ACTION_USER_PRESENT.equals(action)) { // 解锁 Log.i("info", "解屏"); } } } /** * 关闭屏幕锁屏界面 */ private void finishScreenActivity(){ if(mactivity!=null){ mactivity.finish(); } } /** * 跳转到屏幕锁屏界面 */ private void startScreenActivity(){ startActivity(mintent); } }
SinglePixelActivity.java
package org.screenlock.main; import android.app.Activity; import android.os.Bundle; import android.util.Log; import android.view.Window; import android.view.WindowManager; public class SinglePixelActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Window window= getWindow(); WindowManager.LayoutParams params=new WindowManager.LayoutParams(); params.x=0; params.y=0; params.width=1; params.height=1; window.setAttributes(params); MainActivity.mactivity=this; Log.i("info", "SinglePixelActivity onCreate"); } @Override protected void onStart() { super.onStart(); Log.i("info", "SinglePixelActivity onStart"); } @Override protected void onResume() { super.onResume(); Log.i("info", "SinglePixelActivity onResume"); } @Override protected void onPause() { super.onPause(); Log.i("info", "SinglePixelActivity onPause"); } @Override protected void onStop() { super.onStop(); Log.i("info", "SinglePixelActivity onStop"); } @Override protected void onRestart() { super.onRestart(); Log.i("info", "SinglePixelActivity onRestart"); } @Override protected void onDestroy() { super.onDestroy(); Log.i("info", "SinglePixelActivity onDestroy"); } }
AndroidManifest.xml中需要添加如下:
<activity android:name="org.screenlock.main.SinglePixelActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
运行上面的程序,可以看到计时器在正常打印东西,说明程序并没有完全停止,还可以看到打印如下的日志:
info SinglePixelActivity onCreate
info SinglePixelActivity onStart
info SinglePixelActivity onResume
info SinglePixelActivity onPause
info SinglePixelActivity onStop
从日志中可以看出,当锁屏后,这个SinglePixelActivity立即进入了OnStop状态,在Onstop的状态的页面是很有可能被系统回收的。因此可以再配合上WakeLock机制,若WakeLock不合适的话,那么可以尝试播放无声音乐。保持系统不回收该App的资源。
需要注意,当锁屏后再次打开的跳转逻辑处理也是一个问题,可以参考 Android实现监听返回键,主键(HOME),菜单键