Переходим на тёмную сторону




Аппараты Samsung

Учитывайте тот факт, что некоторые производители порой мудрят с сенсорами. Например, Samsung разместил на своём сайте таблицу возвращаемых значений для своих аппаратов:

Sr No Galaxy S Galaxy S II Range
      (0; 1000)
      <1000; 9000
      <9000; 15000)
      <15000; …)

Samsung выложила для разработчиков свой пример, в котором предлагается определять степень освещённости через перечисление LightLevel. В своём примере я добавил их способ: перечисление LightLevel и метод getLightLevelBySensorValue. Показания выводятся в текстовой метке у метода onSensorChanged().

Пример можно проверить на эмуляторе. Выберите раздел Virtual sensors и меняйте значения у секции Lihgt (lux) на вкладке Additional sensors. Для наглядности я наложил окно настроек на эмулятор и ползунком менял значение от 0 до 40000.

Переходим на тёмную сторону

Что касается практического применения, то можете определять степень освещённости и предлагать пользователю переключиться на дневной/ночной режим чтения текста на экране. Например, ночью многие любят читать белый текст на чёрном фоне.

Установите некое пороговое значение, например, 50 люкс для перехода из дневного режима в ночной.

 

private final int NIGHT = 0;

private final int DAY = 1;

private final int THRESHOLD_LUX = 50;

private int mStatus;

 

@Override

public void onSensorChanged(SensorEventsensorEvent) {

final LightLevellightLevel = getLightLevelBySensorValue(sensorEvent.values[0]);

 

if (sensorEvent.sensor.getType() == Sensor.TYPE_LIGHT) {

mLightValueTextView.setText("LIGHT: " + sensorEvent.values[0]);

}

 

float luxValue = sensorEvent.values[0];

mStatus = luxValue< THRESHOLD_LUX?NIGHT: DAY;

if(mStatus == 0){

// Ночь

mLightValueTextView.setBackgroundColor(Color.BLACK);

mLightValueTextView.setTextColor(Color.WHITE);

}else {

// День

mLightValueTextView.setBackgroundColor(Color.WHITE);

mLightValueTextView.setTextColor(Color.BLACK);

}

}

Припаденииосвещённостименьше 50 люкстекстоваяметкапоменяетсвоицвета.

Может случиться так, что устройство будет находится в таком месте, где уровень освещённости будет примерно равен выбранному пороговому значению, колеблясь то в одну, то в другую сторону. Это приведет к тому, что приложение будет очень часто переключаться из одного режима в другой. Для устранения недостатка создадим два пороговых значения: верхнее и нижнее. Всё, что выше верхнего порога будет считаться днём, остальное — ночью, а изменения между порогами будем игнорировать.

 

//private final int THRESHOLD_LUX = 50;

// выбираемдиапазонзначений

private static final int THRESHOLD_DAY_LUX = 55;

private static final int THRESHOLD_NIGHT_LUX = 45;

 

@Override

public void onSensorChanged(SensorEvent sensorEvent) {

final LightLevel lightLevel = getLightLevelBySensorValue(sensorEvent.values[0]);

 

if (sensorEvent.sensor.getType() == Sensor.TYPE_LIGHT) {

mLightValueTextView.setText("LIGHT: " + sensorEvent.values[0]);

}

 

float luxValue = sensorEvent.values[0];

 

if (luxValue < THRESHOLD_NIGHT_LUX){

mStatus = NIGHT;

} else if (luxValue > THRESHOLD_DAY_LUX){

mStatus = DAY;

}

 

if(mStatus == 0){

// Ночь

mLightValueTextView.setBackgroundColor(Color.BLACK);

mLightValueTextView.setTextColor(Color.WHITE);

}else {

// День

mLightValueTextView.setBackgroundColor(Color.WHITE);

mLightValueTextView.setTextColor(Color.BLACK);

}

}

В идеальных условиях данного примера вполне достаточно. Но представьте себе, что вы едете в поезде и тени деревьев за окном приводят к ложным срабатываниям при кратковременном сильном изменении уровня освещённости. Мы можем избавиться от этой проблемы, если установим фильтр низких частот, который сгладит все резкие и кратковременные изменения данных от датчика.

 

private static final float SMOOTHING = 10;

private final LowPassFilter mLowPassFilter = new LowPassFilter(SMOOTHING);

 

// вметоде onSensorChanged()

float luxValue = sensorEvent.values[0];

luxValue = mLowPassFilter.submit(luxValue);

 

public class LowPassFilter {

 

private float filteredValue;

private final float smoothing;

private boolean firstTime = true;

 

public LowPassFilter(float smoothing) {

this.smoothing = smoothing;

}

 

public float submit(float newValue){

if (firstTime){

filteredValue = newValue;

firstTime = false;

return filteredValue;

}

filteredValue += (newValue - filteredValue) / smoothing;

return filteredValue;

}

}

Итоговыйвариант:

import android.content.Context;

import android.graphics.Color;

import android.hardware.Sensor;

import android.hardware.SensorEvent;

import android.hardware.SensorEventListener;

import android.hardware.SensorManager;

import android.os.Bundle;

import android.os.Environment;

import android.support.v7.app.AppCompatActivity;

import android.view.Menu;

import android.view.MenuItem;

import android.widget.TextView;

import android.widget.Toast;

 

public class MainActivity extends AppCompatActivity implements SensorEventListener {

 

// фильтрнизкихчастот

private static final float SMOOTHING = 10;

private final LowPassFilter mLowPassFilter = new LowPassFilter(SMOOTHING);

 

private final int NIGHT = 0;

private final int DAY = 1;

//private final int THRESHOLD_LUX = 50;

private static final int THRESHOLD_DAY_LUX = 55;

private static final int THRESHOLD_NIGHT_LUX = 45;

private int mStatus;

 

private SensorManager mSensorManager;

private Sensor mLightSensor;

private TextView mLightValueTextView;

 

 

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

 

setContentView(R.layout.activity_main);

 

mLightValueTextView = (TextView) findViewById(R.id.textViewInfo);

 

mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);

 

if (mLightSensor == null) {

Toast.makeText(getApplicationContext(), "Датчикосвещениянеобнаружен!",

Toast.LENGTH_SHORT).show();

} else {

Toast.makeText(getApplicationContext(), "Датчикосвещения " + mLightSensor.getName()

+ " доступен", Toast.LENGTH_SHORT).show();

}

}

 

// Лучшеперенестив onStart()

protected void onResume() {

mSensorManager.registerListener(this, mLightSensor, SensorManager.SENSOR_DELAY_UI);

super.onResume();

}

 

// Лучшеперенестив onStop()

protected void onPause() {

mSensorManager.unregisterListener(this);

super.onPause();

}

 

@Override

public void onSensorChanged(SensorEvent sensorEvent) {

final LightLevel lightLevel = getLightLevelBySensorValue(sensorEvent.values[0]);

 

if (sensorEvent.sensor.getType() == Sensor.TYPE_LIGHT) {

mLightValueTextView.setText("LIGHT: " + sensorEvent.values[0] +

"\nLight level: " + lightLevel);

}

 

float luxValue = sensorEvent.values[0];

luxValue = mLowPassFilter.submit(luxValue);

 

if (luxValue < THRESHOLD_NIGHT_LUX){

mStatus = NIGHT;

} else if (luxValue > THRESHOLD_DAY_LUX){

mStatus = DAY;

}

 

//mStatus = luxValue < THRESHOLD_LUX? NIGHT: DAY;

if(mStatus == 0){

// Ночь

mLightValueTextView.setBackgroundColor(Color.BLACK);

mLightValueTextView.setTextColor(Color.WHITE);

}else {

// День

mLightValueTextView.setBackgroundColor(Color.WHITE);

mLightValueTextView.setTextColor(Color.BLACK);

}

}

 

@Override

public void onAccuracyChanged(Sensor sensor, int i) {

 

}

 

// Дляаппаратов Samsung

private enum LightLevel {

LIGHT_LVL_UNKNOWN, LIGHT_LVL_1, LIGHT_LVL_2, LIGHT_LVL_3, LIGHT_LVL_4

}

 

private LightLevel getLightLevelBySensorValue(float sensorValue) {

if (sensorValue < 1000.0) {

return LightLevel.LIGHT_LVL_1;

}

if (sensorValue >= 1000.0 && sensorValue < 9000.0) {

return LightLevel.LIGHT_LVL_2;

}

if (sensorValue >= 9000.0 && sensorValue < 15000.0) {

return LightLevel.LIGHT_LVL_3;

}

if (sensorValue >= 15000) {

return LightLevel.LIGHT_LVL_4;

}

return LightLevel.LIGHT_LVL_UNKNOWN;

}

 

public class LowPassFilter {

 

private float filteredValue;

private final float smoothing;

private boolean firstTime = true;

 

public LowPassFilter(float smoothing) {

this.smoothing = smoothing;

}

 

public float submit(float newValue){

if (firstTime){

filteredValue = newValue;

firstTime = false;

return filteredValue;

}

filteredValue += (newValue - filteredValue) / smoothing;

return filteredValue;

}

}

}

В заключение можно упомянуть о константах для датчика освещённости: LIGHT_CLOUDY, LIGHT_FULLMOON, LIGHT_SUNRISE и др., которые можете использовать в своих примерах.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2022-11-28 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: