目录结构:

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. sql存储过程加密和解密(MSSQL)

    在网络上,看到有SQL Server 2000和SQL Server 2005 的存储过程加密和解密的方法,后来分析了其中的代码,发现它们的原理都是一样的.后来自己根据实际的应用环境,编写了两个存储过 ...

  2. IncrediBuild 2.40 过期时间

    IncrediBuild 2.40的License有2个文件CoordLicense.dat和AgentLicense.dat,分别位于Coordinator和Agent安装目录下,这两个文件都是RS ...

  3. [Spring Boot] Use Component Scan to scan for Bean

    Component Scan is important concept when we want to create Bean. Currently we know what, for the cla ...

  4. Docker 容器入门

    1.1 容器简介 1.1.1 什么是 Linux 容器 Linux容器是与系统其他部分隔离开的一系列进程,从另一个镜像运行,并由该镜像提供支持进程所需的全部文件.容器提供的镜像包含了应用的所有依赖项, ...

  5. ListView显示不同布局

    在使用不同布局的时候,getItemViewType和getViewType不能少,通常是不用这两个函数的重载的 listView.setAdapter(new BaseAdapter() { @Ov ...

  6. 带你走进EJB--将EJB发布为Webservice(4)

    接下来的我们将会自定义一个对象,然后看看EJB是如何对复杂的参数发布成WebService的. 代码如下:在第一个版本的基础之上加上增加用户的方法,参数为User. package com.tgb.e ...

  7. Lanczos Algorithm and it's Parallelization Stragegy

    由于写了降维的一个系列算法分析,本来以为对这个Lanczos算法会理解一点,但是还是不知道讲了什么,最多的就是会如何调用,然后出结果,所以就翻译官网的相关内容.本篇翻译来自Dimensional Re ...

  8. NUMA总结。

    vsphere 5.1性能最佳实践http://www.vmware.com/pdf/Perf_Best_Practices_vSphere5.1.pdf vNUMA 要求:硬件版本8以上. 1.整个 ...

  9. Hotmail Smtp邮箱发送的端口

    1.最近有项目需求做监控报警. 2.使用Smtp发邮件时,网上找了一大堆,Smtp服务是:smtp.live.com   端口是:25或587,试了好多次都不行.原来端口是465. 3.发送时,我启用 ...

  10. 深度学习-Windows平台下的Caffe编译教程

    一.安装CUDA7.5 Cuda是英伟达推出的GPU加速运算平台 我这里安装的是cuda7.5,已经安装过的忽略,还没有安装过的这里有安装教程.windows下面安装还是非常简单的. https:// ...