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

Stella981
• 阅读 664

实现功能如下:在背景运行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);
    }

大功告成

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
保卫大萝卜 保卫大萝卜
2年前
低代码,虽然有点毒瘤,但管用就好
最近看到不少低门槛开发软件应用的新闻:“30分钟搭一款核酸检测登记应用”、“2小时紧急上线抗疫求助应用”、“00后低代码开发者毕业月薪过万”等等。近期,广西防城港市出现疫情,全市展开一轮大规模核酸检测。柳钢工人彭期文在钉钉上仅用30分钟就通过低代码搭起一款“核酸检测登记”应用,原本需要大规模的排队登记,如今手机一扫,3小时就能完成7000余人
Chase620 Chase620
3年前
iOS开发:后台运行以及保持程序在后台长时间运行
第一部分1.先说说iOS应用程序5个状态:停止运行应用程序已经终止,或者还未启动。不活动应用程序处于前台但不再接收事件(例如,用户在app处于活动时锁住了设备)。活动app处于“使用中”的状态。后台app不再屏幕上显示,但它仍然执行代码。挂起app仍然驻留内存但不再执行代码。按下Home键时,app从活动状态转入后台,绝大部分app通
待兔 待兔
3个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
哪吒 哪吒
3年前
栅格布局xs sm md lg xl
1.单位xl对应屏幕1920px超大显示器lg对应屏幕1200px,小于1920px台式19201080显示器md对应屏幕992px,小于1200px适合笔记本sm对应屏幕768px,小于992px适合平板xs对应屏幕<768手机端屏幕例如有如下代码将屏幕分成3列,进行响应式布局当屏幕的大小变成手机般大小(屏幕宽度<768px)时只显示xs2
Stella981 Stella981
3年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Stella981 Stella981
3年前
Android自动化性能收集
<h1Android自动化性能收集</h1<pAndroid功能测试自动化框架较多,UIAutomator,Robotium,Appium等。Case执行过程中,可能希望收集手机的性能指标,包括内存、cpu、流量等。使用javashellbat简单实现了android手机性能收集。</p<h2简述</h2<p过程很简单:</p
Stella981 Stella981
3年前
Linux系统中日志级别详情
日志信息分类1.等级由低到高:debug<info<warn<Error<Fatal;2.区别:debug级别最低,可以随意的使用于任何觉得有利于在调试时更详细的了解系统运行状态的东东;info 重要,输出信息:用来反馈系统的当前状态给最终用户的;后三个,警告、错误、严重错误,这三者应该都在系统运行时检测到了一个不正常的状态。wa
曼成 曼成
8个月前
web页面中接入空号检测API教程,实现可视化号码检测
在Web应用中,空号检测API可以帮助我们识别无效或不活跃的手机号码,从而优化用户数据库。本文将指导你如何在Web页面中接入空号检测API,并实现一个简单的用户界面来展示检测结果。
E小媛同学 E小媛同学
7个月前
如何快速实现手机号码实时检测的功能
在现代的网络服务中,手机号码实时检测功能是一项重要的安全措施,它能够帮助验证用户身份,防止欺诈行为,并且提供用户行为分析的数据支持。本文将详细介绍如何通过编写UI代码和接入API来实现手机号码实时检测功能。