Android实现简单的检测手机自由落体关闭屏幕

摘要:
1.需要加速度传感器TYPE来检测自由落体运动_ ACCELEROMETERSensorManagermSensorManager;@OverridepublicvotionCreate(){super.onCreate();mSensorManager=(SensorManager)getSystemService(SENSOR_SERVICE);

实现功能如下:在背景运行app,检测到自由落体状态时,熄灭屏幕,可重复测试。

1. 检测自由落体动作 

需要使用到加速度感应器 TYPE_ACCELEROMETER

SensorManager mSensorManager;
private float mLastX;
private float mLastY;
private float mLastZ;
private double force;

    @Override
    public void onCreate() {
        super.onCreate();
        mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        mSensorManager.registerListener(sensorListener, 
            mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), 
            SensorManager.SENSOR_DELAY_GAME);
    }

    private final SensorEventListener sensorListener = new SensorEventListener() {
        @Override
        public void onSensorChanged(SensorEvent event) {
            try {
                if(event.sensor == null){
                    return;
                }
            }catch (Exception ex){

            }

            if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
                mLastX = event.values[0];
                mLastY = event.values[1];
                mLastZ = event.values[2];
                force = Math.sqrt(mLastX*mLastX+mLastY*mLastY+mLastZ*mLastZ);

            }
            if(force < 1 ){
                Log.i("Kunkka","force < 1 START-------------");
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (force < 1) {
                            Log.i("Kunkka","force < 1 END, SCREEN OFF");
                            screenOff();
                        }
                    }
                }, 20);
            }
        }

        @Override
        public void onAccuracyChanged(Sensor sensor, int accuracy) {

        }
    };

标黄的是判断手机失重的依据,即三个方向的合力为0。由于不是那么精确,让其合力<1即可。

另外为了防止手机平时突然出现符合这个结果的,当第一次出现符合条件的合力时,延迟20ms再检测一次,(最好连续检测多次来确定连续处于失重状态),假如依旧符合失重,就认定此时在失重状态。再做下一步的处理。

2. 关闭屏幕

熄灭屏幕代码:

private void screenOff(){
    DevicePolicyManager policyManager = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
    ComponentName adminReceiver = new ComponentName(DeviceFallDetectService.this, MyAdminReceiver.class);
    boolean admin = policyManager.isAdminActive(adminReceiver);
    if (admin) {
        policyManager.lockNow();
    } else {
        Toast.makeText(this,"没有设备管理权限",
                Toast.LENGTH_LONG).show();
    }
}

息屏主要使用的是DevicePolicyManager 类,此外MyAdminReceiver是一个息屏管理的广播接收器,该接受器非常重要,系统设置中正是通过该接收器才找到的应用程序,该广播接收器在AndroidManifest.xml中的声明如下:

<receiver
    android:name=".MyAdminReceiver"
    android:permission="android.permission.BIND_DEVICE_ADMIN">
    <meta-data
        android:name="android.app.device_admin"
        android:resource="@xml/admin"/>

    <intent-filter>
        <action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/>
    </intent-filter>
</receiver>
xml/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>

Receiver的源码空的就可以,只需要继承DeviceAdminReceiver:

public class MyAdminReceiver extends DeviceAdminReceiver {

}

网上说还需要加权限

<uses-permission android:name="android.permission.USES_POLICY_FORCE_LOCK" />

但我没加去运行也没出什么问题。

3. Forground service实现重复运行

由于运行在background service中的话,屏幕关了再打开,好像background service就被停下了。

为了每次屏幕亮了都可以继续运行,把service改成O之后的foreground service:

首先startservice的地方,改成foreground方式启动:

Intent intent = new Intent(MainActivity.this,
        DeviceFallDetectService.class);
startForegroundService(intent);
MainActivity.this.finish();

然后在service的onStartCommand中,立刻声明startForeground。

并且android O 以后每个Notification都需要依附一个channel,要不然就报错。加一个简单的channel:

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        initChanel();
        return super.onStartCommand(intent, flags, startId);
    }

    private void initChanel(){
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID,"FallDetect",
                NotificationManager.IMPORTANCE_HIGH);

        NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        manager.createNotificationChannel(channel);

        Notification notification = new Notification.Builder(getApplicationContext(),CHANNEL_ID).build();
        startForeground(3210, notification);
    }

大功告成

 

免责声明:文章转载自《Android实现简单的检测手机自由落体关闭屏幕》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇windows下创建h2集群,及java集成详细步骤python3中的编码与解码原理下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Django——缓存机制

一、缓存介绍 缓存就是将常用的一些数据保存在内存或者们擦车中,在一定时间内,如果有请求访问这些数据的时候,则不用去服务器操作数据库渲染,直接缓存中获取,节约时间,增加访问速度,环节服务器压力 二、Django中的6种缓存方式 开发调试缓存 内存缓存 文件缓存 数据库缓存 Memcache缓存 Memcache缓存 三、Django缓存配置 1.2.1...

前端js实现打印excel表格

产品原型: 图片.png 功能需求:点击导出考勤表格按钮,会自动下载成Excel格式 图片.png 图片.png jsp页面代码: <div class="tools"> <button type="button" onclick="method5('dataTable')">导出考勤表</but...

WPF自动隐藏的消息框(鼠标放上去将一直显示,移开动画继续),提供normal和error两种边框。

原地址-> http://www.cnblogs.com/yk250/p/5660777.html 介绍:传统的确定,取消,OK,CANCAL之类的对话框太繁琐了,由于项目需要而诞生的仿手机式提示对话框。当然传统的对话框项目中也有,这里就不做介绍了。 出场和退场动画做得很简单,就用Blend随便鼓捣了一番,将就用吧。 预览效果如下: 思路其实很简单...

C# 读取Json文件

夜阑听雨随笔 - 32  文章 - 0  评论 - 34 C# 读取Json文件C#读取Json文件并赋值给初始值 一、有Json文件如下(若用记事本编辑记得另存为-编码选择 U-TF8): 二、读取方法: using Newtonsoft.Json; using Newtonsoft.Json.Linq; /// <summary&...

Appium(二)---启动App+模拟滑动

环境搭建好了,就可以实现基本的操作,比如启动App和模拟滑动。这里我实现的是在真机(乐视1s)上启动抖音App,并滑动抖音的视频列表,代码如下: from appium importwebdriver from time importsleep classAction(): def __init__(self): #初始化配置,这里设置的...

为CDH 5.7集群添加Kerberos身份验证及Sentry权限控制

转载请注明出处:http://www.cnblogs.com/xiaodf/ 4. 为CDH 5集群添加Kerberos身份验证 4.1 安装sentry1、点击“操作”,“添加服务”;2、选择sentry,并“继续”; 3、选择一组依赖关系 4、确认新服务的主机分配 5、配置存储数据库;  在mysql中创建对应用户和数据库: mysql>cre...