之前写了一篇关于系统应用实现一次贴片多次读卡的文章,实际运用过程中发现了一些小问题,某些设备(android 8.0可以,android7.0不可以)在线程中反射调用系统api时有时会不成功,导致之后设备读得了卡,但是我的应用收不到,不走onNewIntent,尝试4.4以上的新方法enableReaderMode()也不返回NfcAdapter.ReaderCallback的onTagDiscovered回调。
莫得办法,又不能删库跑路,只能另寻他路,在摆弄着我的设备时,忽然发现了一个有趣的现象,当我熄屏再亮屏的时候,我的app居然又收到了标签信息。
实现思路:通过控制屏幕的亮灭来实现一次贴卡多次读卡
网上很多说用PowerManager和PowerManager.WakeLock来实现亮灭,根本就不行,还需要设备管理员权限才可以。
具体如下:
1.添加权限:
<uses-permission android:name="android.permission.WAKE_LOCK" />
2.添加Receiver:
< android:name=".newfunction.nfc.receiver.ScreenOffAdminReceiver"
android:label="@string/app_name"
android:permission="android.permission.BIND_DEVICE_ADMIN">
android:name="android.app.device_admin"
android:resource="@xml/device_admin" />
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</receiver>
3.Receiver的实现:
public class ScreenOffAdminReceiver extends DeviceAdminReceiver {
}
4.需要的xml包下device_admin.xml:
<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
<!-- 强行锁定 在里仅这个是需要的-->
<force-lock />
</uses-policies>
</device-admin>
5.activity中初始化参数
private DevicePolicyManager policyManager;
private ComponentName adminReceiver;
private PowerManager mPowerManager;
private PowerManager.WakeLock mWakeLock;
private void initParams() {
adminReceiver =new ComponentName(this, ScreenOffAdminReceiver.class);
mPowerManager = (PowerManager) getSystemService(POWER_SERVICE);
policyManager = (DevicePolicyManager)this.getSystemService(Context.DEVICE_POLICY_SERVICE);
}
6.检测是否有权限的方法以及亮灭屏
/**
* @param view 亮屏
*/
public void checkScreenOn(View view) {
mWakeLock =mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "tag");
mWakeLock.acquire();
mWakeLock.release();
}
/**
* @param view 熄屏
*/
public void checkScreenOff(View view) {
boolean admin =policyManager.isAdminActive(adminReceiver);
if (admin) {
policyManager.lockNow();
}else {
showToast("没有设备管理权限");
}
}
/**
* @param view 检测并去激活设备管理器权限
*/
public void checkAndTurnOnDeviceManager(View view) {
Intent intent =new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, adminReceiver);
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "开启后就可以使用锁屏功能了...");//显示位置见图二
startActivityForResult(intent, 0);
}
private boolean isOpen() {
if (policyManager.isAdminActive(adminReceiver)) {//判断超级管理员是否激活
return true;
}else {
return false;
}
}
//用户激活设备管理权限的回调
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (isOpen())
showToast("设备已被激活");
else
showToast("设备没有被激活");
}
private void showToast(String Str) {
Toast.makeText(this, Str, Toast.LENGTH_SHORT).show();
}
7.使用
while (isNfcTestStart) {
checkScreenOn(null);//亮屏
//业务逻辑
checkScreenOff(null);//熄屏
}
这样就实现了一次读卡终生读取了,更好的实现目前还没找到,有知道的大佬评论区或者私信我,一起探讨探讨。
手打不易,点个赞呗。
亮灭屏参考文章:
https://blog.csdn.net/u011913612/article/details/77822280