- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 Android 服务,我想在设备锁定时采取行动。
我想澄清一下:
我添加这些要点是因为我发现无数人问同样的问题并得到其中一个回答。我很高兴他们这样做了,因为答案很有用和/或有教育意义,但它们不是我现在要找的。
最佳答案
我已经提出了一个可能的解决方案,但它有一些重要的注意事项。
一般方法:检测“屏幕关闭”事件,然后定期检查设备是否已锁定。这远非理想,但似乎没有任何方法可以检测设备何时被锁定。基本上,“没有正确的方法来做到这一点,所以你需要一起破解一些东西”。
信用:这是基于@Markus 在评论中的建议,结合来自链接问题答案的一些代码以及我自己的一些额外的繁重工作。
注意事项:
AndroidManifest.xml
添加启动 Activity :
<activity android:name=".StartLockMonitorActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
添加一个广播接收器:
<receiver android:name=".StateReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
添加主要服务:
<service
android:name=".LockMonitor"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="com.sample.screenmonitor.LockMonitor.ACTION_START_SERVICE"/>
</intent-filter>
</service>
添加权限:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
res/values/styles.xml
添加透明样式:
<style name="Theme.Transparent" parent="android:Theme">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@color/transparent</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">true</item>
<item name="android:backgroundDimEnabled">false</item>
</style>
res/values/colors.xml
添加透明色:
<color name="transparent">#00000000</color>
StartLockMonitorActivity.java
这是主入口点,它只是启动服务:
package com.sample.screenmonitor;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
public class StartLockMonitorActivity extends AppCompatActivity {
public static final String TAG = "LockMonitor-SLM";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.w(TAG, "Starting service...");
final Intent newIntent = new Intent(this, LockMonitor.class);
newIntent.setAction(LockMonitor.ACTION_CHECK_LOCK);
startService(newIntent);
Toast.makeText(this, "Starting Lock Monitor Service", Toast.LENGTH_LONG).show();
finish();
}
}
StateReceiver.java
这会在设备重新启动时重新启动服务。服务第一次启动时,它会添加一些额外的过滤器(请参阅 LockMonitor.java
中的注释,其中描述了为什么 list 中没有这样做)。
package com.sample.screenmonitor;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
public class StateReceiver extends BroadcastReceiver {
public static final String TAG = "LockMonitor-SR";
@Override
public void onReceive(Context context, Intent intent) {
Log.i(TAG, "onReceive: redirect intent to LockMonitor");
final Intent newIntent = new Intent(context, LockMonitor.class);
newIntent.setAction(LockMonitor.ACTION_CHECK_LOCK);
newIntent.putExtra(LockMonitor.EXTRA_STATE, intent.getAction());
context.startService(newIntent);
}
}
LockMonitor.java
package com.sample.screenmonitor;
import android.app.KeyguardManager;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.os.PowerManager;
import android.support.annotation.Nullable;
import android.util.Log;
import java.util.Timer;
import java.util.TimerTask;
public class LockMonitor extends Service {
public static final String TAG = "LockMonitor";
public static final String ACTION_CHECK_LOCK = "com.sample.screenmonitor.LockMonitor.ACTION_CHECK_LOCK";
public static final String EXTRA_CHECK_LOCK_DELAY_INDEX = "com.sample.screenmonitor.LockMonitor.EXTRA_CHECK_LOCK_DELAY_INDEX";
public static final String EXTRA_STATE = "com.sample.screenmonitor.LockMonitor.EXTRA_STATE";
BroadcastReceiver receiver = null;
static final Timer timer = new Timer();
CheckLockTask checkLockTask = null;
public LockMonitor() {
Log.d(TAG, "LockMonitor constructor");
}
@Override
public void onDestroy() {
Log.d(TAG, "LM.onDestroy");
super.onDestroy();
if (receiver != null) {
unregisterReceiver(receiver);
receiver = null;
}
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "LM.onStartCommand");
if (intent != null && intent.getAction() == ACTION_CHECK_LOCK) {
checkLock(intent);
}
if (receiver == null) {
// Unlike other broad casted intents, for these you CANNOT declare them in the Android Manifest;
// instead they must be registered in an IntentFilter.
receiver = new StateReceiver();
IntentFilter filter = new IntentFilter(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_ON);
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_USER_PRESENT);
registerReceiver(receiver, filter);
}
return START_STICKY;
}
void checkLock(final Intent intent) {
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
final boolean isProtected = keyguardManager.isKeyguardSecure();
final boolean isLocked = keyguardManager.inKeyguardRestrictedInputMode();
final boolean isInteractive = powerManager.isInteractive();
final int delayIndex = getSafeCheckLockDelay(intent.getIntExtra(EXTRA_CHECK_LOCK_DELAY_INDEX, -1));
Log.i(TAG,
String.format("LM.checkLock with state=%s, isProtected=%b, isLocked=%b, isInteractive=%b, delay=%d",
intent != null ? intent.getStringExtra(EXTRA_STATE) : "",
isProtected, isLocked, isInteractive, checkLockDelays[delayIndex])
);
if (checkLockTask != null) {
Log.i(TAG, String.format("LM.checkLock: cancelling CheckLockTask[%x]", System.identityHashCode(checkLockTask)));
checkLockTask.cancel();
}
if (isProtected && !isLocked && !isInteractive) {
checkLockTask = new CheckLockTask(this, delayIndex);
Log.i(TAG, String.format("LM.checkLock: scheduling CheckLockTask[%x] for %d ms", System.identityHashCode(checkLockTask), checkLockDelays[delayIndex]));
timer.schedule(checkLockTask, checkLockDelays[delayIndex]);
} else {
Log.d(TAG, "LM.checkLock: no need to schedule CheckLockTask");
if (isProtected && isLocked) {
Log.e(TAG, "Do important stuff here!");
}
}
}
static final int SECOND = 1000;
static final int MINUTE = 60 * SECOND;
// This tracks the deltas between the actual options of 5s, 15s, 30s, 1m, 2m, 5m, 10m
// It also includes an initial offset and some extra times (for safety)
static final int[] checkLockDelays = new int[] { 1*SECOND, 5*SECOND, 10*SECOND, 20*SECOND, 30*SECOND, 1*MINUTE, 3*MINUTE, 5*MINUTE, 10*MINUTE, 30*MINUTE };
static int getSafeCheckLockDelay(final int delayIndex) {
final int safeDelayIndex;
if (delayIndex >= checkLockDelays.length) {
safeDelayIndex = checkLockDelays.length - 1;
} else if (delayIndex < 0) {
safeDelayIndex = 0;
} else {
safeDelayIndex = delayIndex;
}
Log.v(TAG, String.format("getSafeCheckLockDelay(%d) returns %d", delayIndex, safeDelayIndex));
return safeDelayIndex;
}
class CheckLockTask extends TimerTask {
final int delayIndex;
final Context context;
CheckLockTask(final Context context, final int delayIndex) {
this.context = context;
this.delayIndex = delayIndex;
}
@Override
public void run() {
Log.i(TAG, String.format("CLT.run [%x]: redirect intent to LockMonitor", System.identityHashCode(this)));
final Intent newIntent = new Intent(context, LockMonitor.class);
newIntent.setAction(ACTION_CHECK_LOCK);
newIntent.putExtra(EXTRA_CHECK_LOCK_DELAY_INDEX, getSafeCheckLockDelay(delayIndex + 1));
context.startService(newIntent);
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.d(TAG, "LM.onBind");
return null;
}
}
关于android - Android 服务有没有办法检测设备何时被锁定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35139125/
我对 Java 并发性比较陌生(还没有阅读 JCIP,但它在我的列表中!)并且我有一个关于锁定行为的问题。具体来说,Java 是锁定对象的引用,还是锁定对象本身? 代码示例(不是 sscce,因为我不
我的团队使用 TortoiseSVN 编写版本控制代码。有时,有人使用“获取锁定”选项。是否有可能看到解决方案中的锁? 最佳答案 http://tortoisesvn.net/docs/nightly
我在使用 SVN 时遇到了一个小问题。 当我跑 svn stat我明白了: ~ some/dir 当我跑 svn commit -m "test"我明白了:svn: working copy
我启用了 jenkins 安全性,认为它会提示我创建一个帐户。我尝试在 c:/program files/jenkins 中删除和编辑我的 config.xml 文件,但我不确定如何在没有访问权限的情
实现与 S3 结合使用的简单锁定机制的推荐方法是什么? 我想做的例子: 通过对象 ID 获取锁 从 S3 读取对象 修改数据 将对象写入 S3 释放锁 理想情况下寻找基于云的锁定机制。我可以在本地使用
找到这个here : 一般来说,在以下任何情况下,请考虑在列上创建索引: 索引列上存在引用完整性约束,或者列。索引是避免全表锁的一种方法,否则,如果您更新父表主键,则需要,合并到父表中,或从父表中删除
在我的程序中,我将把每个“ block ”数据存储在一个单独的文件中。多个线程都会读取和写入各种文件,我想避免因未正确同步而可能出现的问题。本质上,我想要一个设置,其中每个文件的行为就好像它有自己的
我想使用此script作为资源,通过使用Windows API(重置管理器)与Go for Windows中的内容相同 到目前为止,我的代码是 Rstrtmgr := syscall.NewLazyD
这里的问题是:“这些选择中的哪一个对于线程安全选择的剧院具有最佳性能?” public static List lockList = initializeLocks(); public boolean
我有一个侧面菜单,单击图标时打开,单击页面或单击菜单上的项目时关闭。我正在尝试实现锁定,因此当单击锁定图标时,即使您单击菜单项或页面,菜单也不会关闭。 我能够将图标从锁定图标更改为解锁图标,但我在停止
使用 TRueType 字体编写 SDL 程序。我调用 TTF_Init() 来初始化 TTF 并使用 TTF_OpenFont( name, size ) 打开我的字体。 我有一个例程,可以使用以下
我正在尝试调试基于运行 FreeRTOS 的 STM32F3 uC 的应用程序。我已在应用程序的线程上下文中的随机位置手动将 PSP 设置为无效值(例如 0),希望触发 memManageFault/
我有以下 C# 代码: 1. List bandEdgeList; 2. 3. bandEdgeList = CicApplication.BandEdgeCache.Where(r
我正在用骰子制作游戏。这个想法是持有/锁定骰子。我把骰子做成按钮,这样现在就可以点击它们了。示例:我抛出一个“6”和一个“1”。我点击“6”,所以现在只会抛出“1”。 我对这个有点迷失了,我需要创建
我正在使用以下代码下载约 200mb 的播客并将其写入文档目录: var podcastRequest = NSURLRequest(URL: audioUrl) NSURLConnection.se
下面的类 DoStuff 启动一个线程并同步以保护监听器对象在 null 时不被访问。 现在,当从外部访问 DoStuff 类函数 setOnProgressListener() 时,我遇到了问题,因
我正在编写一个使用巨大背景 Canvas 的网站。我试图锁定浏览器调整大小处理程序以避免滚动问题(背景越界等) 这是我第一次做一个完整的后台网站。任何有关优化的建议(png 大小 580.72 KB
我是 C# 和线程的新手,我有这个问题要解决: 我有一个处理一些数据的线程,它会不时(必要时)触发我在启动线程之前设置的事件方法 (DataProcessor)。该线程位于专有 dll 中。所以我不能
我正在使用相机,我使用的是文档中给出的完全相同的示例: http://developer.android.com/resources/samples/ApiDemos/src/com/example/
我有几个座位可供用户预订。同一时间,只有一个用户可以参与预订过程,这样同一个座位就不会被多个用户预订。在我的 Java 代码中,我使用了“synchronized”关键字来完成它。这行得通。 但是,现
我是一名优秀的程序员,十分优秀!