If the user turns over the phone I want to react to that by stopping my text to speech reading. It would be a nice feature for my app, but how can I detect this motion? I'm not really familiar with motion sensors and I could not find this specific motion listener anywhere, mostly just screen orientations. Thanks for the help!
This sample activity demonstrates how a device's gravity sensor can be used to detect when the device is turned over. In method onSensorChanged(), term factor determines how complete the "turn over" must be. Typical range might be 0.7 to 0.95.
Support for Gravity Sensor was added in Android API 9. Not all devices have a gravity sensor.
public class MainActivity extends AppCompatActivity implements SensorEventListener {
private static final String TAG = "Demo";
private SensorManager mSensorManager;
private Sensor mGravitySensor;
private boolean mFacingDown;
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// nothing
}
#Override
public void onSensorChanged(SensorEvent event) {
final float factor = 0.95F;
if (event.sensor == mGravitySensor) {
boolean nowDown = event.values[2] < -SensorManager.GRAVITY_EARTH * factor;
if (nowDown != mFacingDown) {
if (nowDown) {
Log.i(TAG, "DOWN");
} else {
Log.i(TAG, "UP");
}
mFacingDown = nowDown;
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mGravitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
if (mGravitySensor == null) {
Log.w(TAG, "Device has no gravity sensor");
}
}
#Override
protected void onResume() {
super.onResume();
if (mGravitySensor != null) {
mSensorManager.registerListener(this, mGravitySensor, SensorManager.SENSOR_DELAY_NORMAL);
}
}
#Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
}
Related
I am trying to display the data from two different sensors and if i comment out the accelerometer data the app will run and show the light sensor data but trying to display the accelerometer data being displayed causes it to crash on launch. if i comment out everything to do with the light sensor i do get the accelerometer data to be shown but they will not be able to be shown at the same time.
the issue being that both sensors use event.values yet at least from my own research this should work although else if gives error in on sensorChanged
which was how Get multiple sensor data at the same time in Android recommended to solve this issue
any help would be great
public class MainActivity extends AppCompatActivity implements SensorEventListener {
//System sensor manager
SensorManager sensorManager;
//active sensors
Sensor lightSensor;
Sensor acelSensor;
TextView xText, yText, zText, lightS;
double ax,ay,az;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//initulise veriables
lightS = (TextView) findViewById(R.id.lightS);
xText = (TextView) findViewById(R.id.xText);
yText = (TextView) findViewById(R.id.yText);
zText = (TextView) findViewById(R.id.zText);
//instance of sensor manager
sensorManager = (SensorManager) getSystemService(Service.SENSOR_SERVICE);
//get sensors from sensor manager
lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
acelSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
//if error
if (lightSensor == null) { lightS.setText("sensor_error"); }
if (acelSensor == null) {
xText.setText("sensor_error");
}}
#Override
public void onStart() {
super.onStart();
if (lightSensor !=null)
{
sensorManager.registerListener(this, lightSensor, SensorManager.SENSOR_DELAY_FASTEST);
}
if (acelSensor !=null)
{
sensorManager.registerListener(this, acelSensor, SensorManager.SENSOR_DELAY_FASTEST);
}
}
#Override
public void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
#Override
public void onResume() {
super.onResume();
sensorManager.registerListener(this, lightSensor, SensorManager.SENSOR_DELAY_FASTEST);
sensorManager.registerListener(this, acelSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_LIGHT) ;
{
float lux = event.values[0];
lightS.setText(String.valueOf(lux));
}
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) ;{
/*ax=event.values[0];
ay=event.values[1];
az=event.values[2];*/
xText.setText("X: " + event.values[0]);
yText.setText("Y: " + event.values[1]);
zText.setText("Z: " + event.values[2]);
}
}
You are registering your sensors twice, once at onstart(), and again at onresume().
I removed the extra onregistersensor().
public class MainActivity extends AppCompatActivity implements SensorEventListener {
//System sensor manager
SensorManager sensorManager;
//active sensors
Sensor lightSensor;
Sensor acelSensor;
TextView xText, yText, zText, lightS;
double x;
double y;
double z;
double ax, ay, az;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//initulise veriables
// lightS = (TextView) findViewById(R.id.lightS);
// xText = (TextView) findViewById(R.id.xText);
// yText = (TextView) findViewById(R.id.yText);
// zText = (TextView) findViewById(R.id.zText);
//instance of sensor manager
sensorManager = (SensorManager) getSystemService(Service.SENSOR_SERVICE);
}
#Override
public void onStart() {
super.onStart();
}
#Override
public void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
#Override
public void onResume() {
super.onResume();
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI);
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT),
SensorManager.SENSOR_DELAY_UI);
}
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_LIGHT) ;
{
float lux = event.values[0];
System.out.println("lux " + lux);
}
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
x = event.values[0] /9.8;
y = event.values[1] /9.8;
z = event.values[2] /9.8;
System.out.println("x: " + x);
System.out.println("y: " + y);
System.out.println("z: " + z);
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
I'm trying to follow a tutorial about sensor. It works fine with an activity. However, I want this to work in the background when the phone is locked. What's the best way to do that?
Here's the link to the tutorial
http://jasonmcreynolds.com/?p=388
ShakeDetector class
public class ShakeDetector implements SensorEventListener {
/*
* The gForce that is necessary to register as shake.
* Must be greater than 1G (one earth gravity unit).
* You can install "G-Force", by Blake La Pierre
* from the Google Play Store and run it to see how
* many G's it takes to register a shake
*/
private static final float SHAKE_THRESHOLD_GRAVITY = 2.7F;
private static final int SHAKE_SLOP_TIME_MS = 500;
private static final int SHAKE_COUNT_RESET_TIME_MS = 3000;
private OnShakeListener mListener;
private long mShakeTimestamp;
private int mShakeCount;
public void setOnShakeListener(OnShakeListener listener) {
this.mListener = listener;
}
public interface OnShakeListener {
public void onShake(int count);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// ignore
}
#Override
public void onSensorChanged(SensorEvent event) {
if (mListener != null) {
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
float gX = x / SensorManager.GRAVITY_EARTH;
float gY = y / SensorManager.GRAVITY_EARTH;
float gZ = z / SensorManager.GRAVITY_EARTH;
// gForce will be close to 1 when there is no movement.
Float f = new Float(gX * gX + gY * gY + gZ * gZ);
Double d = Math.sqrt(f.doubleValue());
float gForce = d.floatValue();
if (gForce > SHAKE_THRESHOLD_GRAVITY) {
final long now = System.currentTimeMillis();
// ignore shake events too close to each other (500ms)
if (mShakeTimestamp + SHAKE_SLOP_TIME_MS > now) {
return;
}
// reset the shake count after 3 seconds of no shakes
if (mShakeTimestamp + SHAKE_COUNT_RESET_TIME_MS < now) {
mShakeCount = 0;
}
mShakeTimestamp = now;
mShakeCount++;
mListener.onShake(mShakeCount);
}
}
}
}
Main Acitivty
public class MainActivity extends AppCompatActivity {
// The following are used for the shake detection
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private ShakeDetector mShakeDetector;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent = new Intent(MainActivity.this, ShakeService.class);
startService(intent);
// ShakeDetector initialization
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mShakeDetector = new ShakeDetector();
mShakeDetector.setOnShakeListener(new ShakeDetector.OnShakeListener() {
#Override
public void onShake(int count) {
Toast.makeText(getApplicationContext(), "shake",Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onResume() {
super.onResume();
// Add the following line to register the Session Manager Listener onResume
mSensorManager.registerListener(mShakeDetector, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
}
#Override
public void onPause() {
// Add the following line to unregister the Sensor Manager onPause
mSensorManager.unregisterListener(mShakeDetector);
super.onPause();
}
}
Shake Service
public class ShakeService extends Service {
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private ShakeDetector mShakeDetector;
public ShakeService() {
}
#Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
#Override
public void onCreate() {
super.onCreate();
// ShakeDetector initialization
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mShakeDetector = new ShakeDetector();
mShakeDetector.setOnShakeListener(new ShakeDetector.OnShakeListener() {
#Override
public void onShake(int count) {
Intent i = getApplicationContext().getPackageManager().getLaunchIntentForPackage("com.facebook.katana");
getApplicationContext().startActivity(i);
}
});
mSensorManager.registerListener(mShakeDetector, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
}
#Override
public void onDestroy() {
mSensorManager.unregisterListener(mShakeDetector);
super.onDestroy();
}
}
You need to use Threads, AsyncTask is the easiest to implement. Take a look at this, if that's what you're looking for: https://developer.android.com/guide/components/processes-and-threads.html
here is a goog example
http://joerichard.net/android/android-shake-detector/
Steps: create a sensor event listener and then get from Activity. Create a service that fires when shake event happen.
I am using AccessibilityService to monitor whenever the foreground activity is changed. Additionally whenever a such a change occurs, I need to read the accelerometer readings for the next 5 seconds. I implemented the following code, but I am not getting continuous readings. Sometimes No reading is shown in between 2 app switches
I am able to detect the foreground activity change accurately, and I can run an activity independently that can show the sensor state changes. But problem exists in combining both.
public class WindowChangeDetectingService extends AccessibilityService implements SensorEventListener {
#Override
protected void onServiceConnected() {
...
}
SensorManager mSensorManager;
Sensor mAccelerometerSensor;
SensorEventListener mListener;
#Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
try {
mSensorManager.unregisterListener(mListener);
}
catch (Exception e){
Log.d("not unregs",e.toString());
}
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mAccelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometerSensor, SensorManager.SENSOR_DELAY_NORMAL);
Handler h = new Handler();
h.postDelayed(new Runnable() {
#Override
public void run() {
// do stuff with sensor values
mSensorManager.unregisterListener(mListener);
}
}, 5000);
ComponentName componentName = new ComponentName(
event.getPackageName().toString(),
event.getClassName().toString()
);
ActivityInfo activityInfo = tryGetActivity(componentName);
boolean isActivity = activityInfo != null;
if (isActivity)
Log.i("CurrentActivity", componentName.flattenToShortString());
}
}
#Override
public void onInterrupt() {}
#Override
public void onSensorChanged(SensorEvent event) {
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
Log.i("\nAccelerometer: \n","X:"+x+"\tY:"+y+"\tZ:"+z);
}
}
Use SENSOR_DELAY_GAME or SENSOR_DELAY_FASTEST instead of SENSOR_DELAY_NORMAL
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mAccelerometerSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this,
mAccelerometerSensor, SensorManager.SENSOR_DELAY_GAME);//change here
I know that there are only two values of proximity : 0.0 & 1.0
I need a simple code to detect proximity through the device's sensors, and perform any task if proximity changes to 1.0
this is what i found.
public class SensorActivity extends Activity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mSensor;
ImageView iv;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.sensor_screen);
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
iv = (ImageView) findViewById(R.id.imageView1);
}
protected void onResume() {
super.onResume();
mSensorManager.registerListener(this, mSensor,
SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent event) {
if (event.values[0] == 0) {
iv.setImageResource(R.drawable.near);
} else {
iv.setImageResource(R.drawable.far);
}
}
}
You can use the getMaximumRange() method to obtain your proximity sensor's max range and use it to determine what to do.
SensorManager sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
Sensor proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
float maxRange = proximitySensor.getMaximumRange();
Now use maxRange to do what you want to do.
public void onSensorChanged(SensorEvent event) {
if(maxRange == event.values[0]) {
// Do something when something is far away.
}
else {
// Do something when something is near.
}
}
One very important thing. The proximity sensor varies from device to device. It not always reports 1.0 and 0.0. For example my Moto G (1st Gen.) reports 3 cm as its min range and 100 cm as its max range. So its best to obtain the max range of the device's sensor and use it in your code rather then hard-coding the value.
I am a java newer,
I want to get, for example, 10 different values of my phone's acceleration,
and get an average value from them.
But I can only find answers for continued data, or only one data.
Now I can get one data and display it on my screen.
Can I use for loop to calculate for 10 times?
Thank you.
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
aAngle = event.values[0];
bAngle = event.values[1];
}
private Button.OnClickListener listener = new Button.OnClickListener() {
switch(viewMode){
case VIEW_MODE_1:
title.setText(Double.toString(aAngle) + " " + Double.toString(bAngle));
break;}
I've tried to cast a for loop in the OnSensorChanged method, but it didn't work at all.
I tried to do this, but it seems to have a runtime error.
List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
if (sensors.size() > 0 && sensors.size() <= 10) {
sensorManager.registerListener(this,sensors.get(count),SensorManager.SENSOR_DELAY_NORMAL);
count ++;
}
also, I create two list to save the result every time when my angle is changed.
for(int i = 0; i < aAngleList.size(); i++){
double aAngleTotal = 0;
double bAngleTotal = 0;
aAngleTotal += aAngleList.get(i);
bAngleTotal += bAngleList.get(i);
aAngleAverage = aAngleTotal / aAngleList.size();
bAngleAverage = bAngleTotal / bAngleList.size();
}
public void onSensorChanged(SensorEvent event) {
aAngleList.add(aAngle);
bAngleList.add(bAngle);
}
the for loop is in onResume, right under the if (sensors...)
onSensorChanged is fired everytime your sensor gets a new reading. you can place a counter for ten changes. keep track of values in a list,hashmap and aggregate them.
public class SensorActivity extends Activity, implements SensorEventListener {
private final SensorManager mSensorManager;
private final Sensor mAccelerometer;
private int count=0;
private List<String> eventX=new ArrayList<String>();
public SensorActivity() {
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
protected void onResume() {
super.onResume();
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent event) {
eventX.add(event.getValueMethodwhateverItis());
count++;
if (count=10){
//aggregate from list do anything you want.;
}
}
}