Android一键锁屏和举手亮屏
.
介绍
最近,由于项目需要开发语音控制相关功能,需要使用语音来实现锁定屏幕和唤醒屏幕的功能,我想开发一个一键锁定屏幕App。主要是我用的手机双击亮屏太麻烦了,不想按电源键。(主要是因为太穷买不起手机O(∩_∩)O哈哈~)
.
.
锁屏实现一
主要是基于
DeviceAdminReceiver
,安卓设备管理器实现一键锁屏功能
.
public class AdminManageReceiver extends DeviceAdminReceiver {
@Override public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent); } }
.
<?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>
.
<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:roundIcon="@drawable/ic_launcher" android:supportsRtl="true" android:theme="@style/Theme.LockAndLightScreenDemo"><!--隐藏状态栏和标题栏--> <activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver
android:name=".Receiver.AdminManageReceiver"
android:label="@string/app_name"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
</application>
.
不激活设备管理器权限是无法实现锁屏功能的。
DialogUtils
是我自己写的一个弹窗工具类,是基于AlertDialog
实现的。
private var mAdminName: ComponentName? = null
private var mDPM: DevicePolicyManager? = null
private fun ifOpenLockScreen() {
//判断是否有锁屏权限
if (checkLockPermission()) {
lockScreen()//锁屏
} else {
DialogUtils.createDialog(this@MainActivity,
R.drawable.dialog_icon_warning,
"提醒",
"点击「前往设置」前往激活设备管理器,如果未开启,锁屏功能无法使用!",
"前往设置", {
_, _ ->
showAdminManagement(mAdminName!!)
},
"算了", {
dialog, which ->
Toast.makeText(this, "未开启,锁屏功能无法使用", Toast.LENGTH_SHORT).show()
}
).show()
}
}
.
private var mAdminName: ComponentName? = null
private var mDPM: DevicePolicyManager? = null
//跳转到设备管理器激活页面
private fun showAdminManagement(mAdminName: ComponentName) {
val intent = Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)
intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, mAdminName)
intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "activity device")
startActivityForResult(intent, 1)
}
.
我这里为了使用方便在调用完这个方法后
finish()
,会退出本应用。如果想实现更完美的效果建议把锁屏功能在 实现,我这里就偷懒一下了。O(∩_∩)O哈哈~
//一键锁屏
private fun lockScreen() {
if (mDPM!!.isAdminActive(mAdminName!!)) {
mDPM!!.lockNow()
finish()
}
}
.
.
锁屏实现二
主要是基于
AccessibilityService
,安卓的无障碍服务来实现一键锁屏的功能
.
这里只继承
AccessibilityService
服务,但是没有做任何的逻辑代码处理,如果想实现更多的功能可以自己去查找安卓无障碍服务修改的资料来实现,这里就不做过多的介绍。
public class AccessibilitySetting extends AccessibilityService {
private static AccessibilityService service;
public AccessibilitySetting() {
service = this;
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
}
@Override
public void onInterrupt() {
}
public static AccessibilityService getService() {
if (service == null) {
return null;
}
return service;
}
}
.
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagRequestFilterKeyEvents"
android:canRetrieveWindowContent="true"
android:canRequestFilterKeyEvents="true"
android:description="@string/accessibility" />
.
<service
android:name=".Services.AccessibilitySetting"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibilityservice" />
</service>
.
/** * 判断是否有无障碍权限 */
private boolean checkAccessPermission() {
if (!isAccessibilityServiceRunning("AccessibilitySetting")) {
DialogUtils.createDialog(MainActivity.this,
R.drawable.dialog_icon_warning,
"提醒",
"点击「前往设置」前往设置辅助功能。",
"前往设置", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
jump2AccessPermissionSetting(MainActivity.this, false);
}
}, "算了", null).show();
Toast.makeText(this, "未开启,操作功能无法使用", Toast.LENGTH_SHORT).show();
return false;
} else {
Toast.makeText(this, "已开启", Toast.LENGTH_SHORT).show();
return true;
}
}
/** * 判断是否存在置顶的无障碍服务 * * @param name * @return */
public boolean isAccessibilityServiceRunning(String name) {
AccessibilityManager am = (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
List<AccessibilityServiceInfo> enableServices = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC);
for (AccessibilityServiceInfo enableService : enableServices) {
if (enableService.getId().endsWith(name)) {
return true;
}
}
return false;
}
.
/** * 跳转到辅助功能设置界面 * * @param activity */
private static final String INTENT_ACTION_ACCESSIBILITY_SETTINGS = "android.settings.ACCESSIBILITY_SETTINGS";
//辅助功能Key
public static final int REQUEST_PERMISS_REQUEST_ACCESSABLE = 300;
public static void jump2AccessPermissionSetting(Activity activity, boolean forResult) {
if (forResult) {
activity.startActivityForResult(new Intent(INTENT_ACTION_ACCESSIBILITY_SETTINGS), REQUEST_PERMISS_REQUEST_ACCESSABLE);
} else {
activity.startActivity(new Intent(INTENT_ACTION_ACCESSIBILITY_SETTINGS));
}
}
.
private void lockScreen() {
if (checkAccessPermission()){
if (Build.VERSION.SDK_INT < 16) {
Toast.makeText(AccessibilitySetting.getService(), "Android 4.1及以上系统才支持此功能,请升级后重试", Toast.LENGTH_SHORT).show();
} else {
if (AccessibilitySetting.getService() != null) {
AccessibilitySetting.getService().performGlobalAction(AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN);
}
}
}
}
同样也要对
AccessibilitySetting
服务进行保活操作,可以参考下面的抬手亮屏的实现。
.
.
抬手亮屏的实现
抬手亮屏的功能的实现主要是基于重力感应传感器实现的,如果想实现更完美的效果可以配合光线距离传感器来一起实现,我这里就偷懒一下了。O(∩_∩)O哈哈~,就没有使用光线距离传感器了。
.
private var shakeTime: Long = 0
private var showTime: Long = 0
private var sensorManager: SensorManager? = null
private var wakeLock: PowerManager.WakeLock? = null//亮屏
private lateinit var notification:Notification
//初始化重力感应
@SuppressLint("InvalidWakeLockTag")
private fun initSensorEvent() {
sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
val powerManager = getSystemService(POWER_SERVICE) as PowerManager
wakeLock = powerManager.newWakeLock(
PowerManager.ACQUIRE_CAUSES_WAKEUP or PowerManager.SCREEN_DIM_WAKE_LOCK, "WakeLock"
)
val accelerometer: Sensor = sensorManager!!.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
sensorManager!!.registerListener(
sensorEventListener,
accelerometer,
SensorManager.SENSOR_DELAY_UI
)
}
.
/** * 处理重力感应监听 */
private val sensorEventListener: SensorEventListener = object : SensorEventListener {
override fun onSensorChanged(event: SensorEvent) {
val values = event.values
//X轴方向的重力加速度,向右为正
val x = values[0]
//Y轴方向的重力加速度,向前为正
val y = values[1]
//Z轴方向的重力加速度,向上为正
val z = values[2]
val medumValue = 12
//判断是否抬手
if (Math.abs(x) > medumValue || Math.abs(y) > medumValue || Math.abs(z) > medumValue) {
shakeTime = System.currentTimeMillis()
}
if (z < 9 && z > 2 && -2 < x && x < 2 && 4 < y && y < 10) {
showTime = System.currentTimeMillis()
if (showTime - shakeTime in 1..800) {
shakeTime = 0
wakeLock!!.acquire()
wakeLock!!.release()//亮屏
}
}
}
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
}
}
<service
android:name=".Services.MyService"
android:priority = "1000"
android:foregroundServiceType="location"
android:enabled="true"
android:exported="true" />
<!--守护服务-->
<service android:name=".Services.GuardingServices"
android:priority = "1000"
android:foregroundServiceType="location"
android:enabled="true"
android:exported="true"/>
class MyService:Service() {
private var shakeTime: Long = 0
private var showTime: Long = 0
private var sensorManager: SensorManager? = null
private var wakeLock: PowerManager.WakeLock? = null//亮屏
private lateinit var notification:Notification
override fun onBind(intent: Intent?): IBinder? {
return null
}
override fun onCreate() {
super.onCreate()
notification = createNotification()
startForeground(1,notification)
initSensorEvent()
}
/** * 初始化重力感应 */
@SuppressLint("InvalidWakeLockTag")
private fun initSensorEvent() {
sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
val powerManager = getSystemService(POWER_SERVICE) as PowerManager
wakeLock = powerManager.newWakeLock(
PowerManager.ACQUIRE_CAUSES_WAKEUP or PowerManager.SCREEN_DIM_WAKE_LOCK, "WakeLock"
)
val accelerometer: Sensor = sensorManager!!.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
sensorManager!!.registerListener(
sensorEventListener,
accelerometer,
SensorManager.SENSOR_DELAY_UI
)
}
/** * 处理重力感应监听 */
private val sensorEventListener: SensorEventListener = object : SensorEventListener {
override fun onSensorChanged(event: SensorEvent) {
val values = event.values
//X轴方向的重力加速度,向右为正
val x = values[0]
//Y轴方向的重力加速度,向前为正
val y = values[1]
//Z轴方向的重力加速度,向上为正
val z = values[2]
val medumValue = 12
//判断是否抬手
if (Math.abs(x) > medumValue || Math.abs(y) > medumValue || Math.abs(z) > medumValue) {
shakeTime = System.currentTimeMillis()
}
if (z < 9 && z > 2 && -2 < x && x < 2 && 4 < y && y < 10) {
showTime = System.currentTimeMillis()
if (showTime - shakeTime in 1..800) {
shakeTime = 0
wakeLock!!.acquire()
wakeLock!!.release()
}
}
}
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
}
}
private fun createNotification(): Notification {
val channelId = "LockService"
val channelName = "LockService"
val importance = NotificationManager.IMPORTANCE_HIGH
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(channelId, channelName, importance)
channel.lightColor = Color.BLU