zoukankan      html  css  js  c++  java
  • Android实现简单的检测手机自由落体关闭屏幕

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

    大功告成

     
  • 相关阅读:
    注册和登录与数据库内的链接
    数据访问
    马厩分配问题
    Codeforces Round #365 (Div. 2) D.Mishka and Interesting sum
    最优比例生成树模板
    01分数规划模板
    hiho一下第109周《Tower Defense Game》
    begin.BZOJ 1383: 三取方格数
    最小生成树
    Codeforces Round #364 (Div. 1)B. Connecting Universities
  • 原文地址:https://www.cnblogs.com/kunkka/p/9779540.html
Copyright © 2011-2022 走看看