目录结构:

contents structure [+]

最近笔者在做一个功能,就是实现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);
}
}

MainActivity.java

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");
} }

SinglePixelActivity.java

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),菜单键

【Android】Android屏幕状态操作的更多相关文章

  1. android 获得屏幕状态

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools= ...

  2. Android监听屏幕解锁和判断屏幕状态

    开发后台服务的时候经常需要对屏幕状态进行判断,如果是想要监听屏幕解锁事件,可以在配置里面注册action为 android.intent.action.USER_PRESENT的广播,则可以监听解锁事 ...

  3. 从零开始学android开发- 应用程序窗体显示状态操作requestWindowFeature

    我们在开发程序是经常会需要软件全屏显示.自定义标题(使用按钮等控件)和其他的需求,今天这一讲就是如何控制Android应用程序的窗体显示. 首先介绍一个重要方法那就是requestWindowFeat ...

  4. Android开发之应用程序窗体显示状态操作(requestWindowFeature()的应用)

    转自:http://www.cnblogs.com/salam/archive/2010/11/30/1892143.html 我们在开发程序是经常会需要软件全屏显示.自定义标题(使用按钮等控件)和其 ...

  5. Android 应用程序窗口显示状态操作(requestWindowFeature()的应用)

     我们在开发程序是常常会须要软件全屏显示.自己定义标题(使用button等控件)和其它的需求,今天这一讲就是怎样控制Android应用程序的窗口显示. 首先介绍一个重要方法那就是requestWi ...

  6. Android 应用程序窗体显示状态操作(requestWindowFeature()的应用)

     我们在开发程序是经常会需要软件全屏显示.自定义标题(使用按钮等控件)和其他的需求,今天这一讲就是如何控制Android应用程序的窗体显示. 首先介绍一个重要方法那就是requestWindowF ...

  7. Android 应用程序窗体显示状态操作(requestWindowFeature()的应用)(转载)

    转自:http://www.cnblogs.com/salam/archive/2010/11/30/1892143.html 我们在开发程序是经常会需要软件全屏显示.自定义标题(使用按钮等控件)和其 ...

  8. android自适应屏幕方向和大小

    一:不同的layout Android手机 屏幕 大小不一,有480x320, 640x360, 800x480.怎样才能让App自动 适应不同的屏幕 呢?      其实很简单,只需要在res目录下 ...

  9. android中的数据库操作

    如何在android中调用数据库资源 在android中主要有两种方法来实现对数据库的访问,一种是adb shell方式,另一种是通过相关的android 的java类来间接的对数据库来进行操作.其中 ...

随机推荐

  1. GIT 如何从另一分支合并特定的文件

    是否遇到过这种情景: 您在一个分支上工作,发现该分支上的某些文件实现的功能已经在其他分支上实现了 但因为这两个分支实现不同的功能,因此不能进行简单的合并工作,但您又不想重复其他已经完成的工作 以下操作 ...

  2. CMake can't find GLEW

      Q: I'm on Windows and there is a FindGLEW.cmake file in my CMake modules folder, presumably put th ...

  3. vue版本冲突解决办法

    ERROR in Vue packages version mismatch: vue@2.1.4 vue-template-compiler@2.1.5 This may cause things ...

  4. oauth2-server-php-docs 授权类型

    授权码 概观 在Authorization Code交付式时使用的客户端想要请求访问受保护资源代表其他用户(即第三方).这是最常与OAuth关联的授予类型. 详细了解授权码 用例 代表第三方来电 履行 ...

  5. notepad++列块编辑操作

    1. 同一时候编辑连续的列区域: 鼠标先在要进行列编辑的起点点击,再同一时候按shift+alt不放,鼠标在要进行列编辑的结尾区域点击. 2. 在起点到文档结尾全部列插入数据: 鼠标先在要插入数据的位 ...

  6. asp.net序列化

    JsonHelp.cs using System.IO; using System.Text; using System.Runtime.Serialization.Json; namespace W ...

  7. js - 关于循环

    ES5:for,foreach,for..in ES6:for..of // ES5(可参见ES6的析构写法) const value = ["a", "b", ...

  8. [转]Maven介绍,包括作用、核心概念、用法、常用命令、扩展及配置

    转自:http://www.trinea.cn/android/maven/ 两年半前写的关于Maven的介绍,现在看来都还是不错的,自己转下.写博客的一大好处就是方便自己以后查阅,自己总结的总是最靠 ...

  9. updateFilter

    $.fn.updateFilter = function(filterType, paramVal) { // filter="DATE|GREATERTHANEQUALS|LESSTHAN ...

  10. JavaWeb分页显示内容之分页查询的三种思路(数据库分页查询)

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6134851.html 在开发过程中,经常做的一件事,也是最基本的事,就是从数据库中查询数据,然后在客户端显示出 ...