with your help and some guides on the internet, i'm managed to knock out this code. But I find myself with several problems, the application, according to my idea, it should start the media player at the time the phone is shaken, and start it once, but now the media player is started every time the phone is shaken . Furthermore, I would like that, the application worked and the screen off when the phone is shaken starts the media player and the screen is turned on
public class SensorTestActivity extends Activity implements SensorEventListener {
private SensorManager sensorManager;
private boolean color = false;
private View view;
private long lastUpdate;
MediaPlayer mMediaPlayer;
#Override
public void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
view = findViewById(R.id.textView);
view.setBackgroundColor(Color.BLUE);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
lastUpdate = System.currentTimeMillis();
}
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
getAccelerometer(event);
}
}
private void getAccelerometer(SensorEvent event) {
float[] values = event.values;
// Movement
float x = values[0];
float y = values[1];
float z = values[2];
float accelationSquareRoot = (x * x + y * y + z * z)/(SensorManager.GRAVITY_EARTH * SensorManager.GRAVITY_EARTH);
long actualTime = System.currentTimeMillis();
if (accelationSquareRoot >= 2) //
{
if (actualTime - lastUpdate < 200) {
return;
}
lastUpdate = actualTime;
Toast.makeText(this, "Device was shuffed", Toast.LENGTH_SHORT).show();
if (color) {
view.setBackgroundColor(Color.GREEN);
try {
mMediaPlayer = MediaPlayer.create(getBaseContext(), R.raw.mymusic);
mMediaPlayer.setLooping(false);
mMediaPlayer.start();
mMediaPlayer.setOnCompletionListener(new
OnCompletionListener() {
public void onCompletion(MediaPlayer arg0) {
// if (mMediaPlayer != null) {
// mMediaPlayer.release();
// mMediaPlayer = null;
// }
}
});
} catch (Exception e) {
if (mMediaPlayer != null) {
mMediaPlayer.release();
mMediaPlayer = null;
}
}
}
} else {
view.setBackgroundColor(Color.RED);
}
color = !color;
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
protected void onResume() {
super.onResume();
// register this class as a listener for the orientation and
// accelerometer sensors
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
protected void onPause() {
// unregister listener
super.onPause();
sensorManager.unregisterListener(this);
}
}
To start something just once, add a boolean.
boolean startOnce = true;
if (startOnce) {
....
startOnce = false;
}
Related
I created an EMF reader app in Android Studio and is having trouble with how to increase a drawable animation when the SensorManager and TextView increases as well as decreases with the SensorManager and TextView in the app.
Here's what I have so far:
public class MainActivity extends AppCompatActivity implements SensorEventListener {
TextView pkeEMF;
private static SensorManager sensorManager;
private Sensor emfSensor;
SoundPool spPKE;
int mpPKE;
ImageView animationView;
AnimationDrawable pkeAnimation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pkeEMF = (TextView) findViewById(R.id.pkeEMF);
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
emfSensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
animationView = (ImageView) findViewById(R.id.pkeDot);
animationView.setBackgroundResource(R.drawable.pkeamimation);
pkeAnimation = (AnimationDrawable) animationView.getBackground();
pkeAnimation.start();
spPKE = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
spPKE.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
mpPKE = spPKE.play(sampleId, 1, 1, 0, -1, 1);
}
});
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
getSupportActionBar().hide();
}
public void showAnimation(View view) {
Intent intent = new Intent(this, AnimationSound.class);
startActivity(intent);
}
#Override
protected void onResume() {
super.onResume();
if (emfSensor != null) {
sensorManager.registerListener(this, emfSensor, SensorManager.SENSOR_DELAY_NORMAL);
} else {
Toast.makeText(this, "Not Supported", Toast.LENGTH_SHORT).show();
finish();
}
mpPKE = spPKE.load(getApplicationContext(), R.raw.pke_running_loop, 1);
}
#Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
spPKE.stop(mpPKE);
}
#Override
public void onSensorChanged(SensorEvent event) {
float azimuth = Math.round(event.values[0]);
float pitch = Math.round(event.values[1]);
float roll = Math.round(event.values[2]);
double tesla = Math.sqrt((azimuth * azimuth) + (pitch * pitch) + (roll * roll));
String text = String.format("%.2f", tesla);
pkeEMF.setText(text + "μT");
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
How do I do this? I have been looking everywhere to find the answer on how to do this and came up with nothing.
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 implement a sensor that can detect a hand wave. I found an example that can do hand hover, but not hand wave.
The following code I used is from
How to controlandroid proximity sensor?
public class AndroidProximitySensorActivity extends Activity {
TextView ProximitySensor, ProximityMax, ProximityReading;
SensorManager mySensorManager;
Sensor myProximitySensor;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ProximitySensor = (TextView)findViewById(R.id.proximitySensor);
ProximityMax = (TextView)findViewById(R.id.proximityMax);
ProximityReading = (TextView)findViewById(R.id.proximityReading);
mySensorManager = (SensorManager)getSystemService(
Context.SENSOR_SERVICE);
myProximitySensor = mySensorManager.getDefaultSensor(
Sensor.TYPE_PROXIMITY);
if (myProximitySensor == null){
ProximitySensor.setText("No Proximity Sensor!");
}else{
ProximitySensor.setText(myProximitySensor.getName());
ProximityMax.setText("Maximum Range: "
+ String.valueOf(myProximitySensor.getMaximumRange()));
mySensorManager.registerListener(proximitySensorEventListener,
myProximitySensor,
SensorManager.SENSOR_DELAY_NORMAL);
}
}
SensorEventListener proximitySensorEventListener
= new SensorEventListener(){
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
if(event.sensor.getType()==Sensor.TYPE_PROXIMITY){
ProximityReading.setText("Proximity Sensor Reading:"
+ String.valueOf(event.values[0]));
}
}
};
}
In the above code, when the event.values[0] = 0, it means my hand is hover at the sensor. However, I need my sensor to detect a hand wave. How do I do it? Thanks.
Please try this code:
private SensorManager sensorManager;
private Sensor proximitySensor;
private final int WAVE_TIME = 2000;
private final int WAVE_NEEDED_MOVEMENTS = 3;
private long lastWaveTime = 0;
private float lastSensorValue;
private float maxSensorValue;
private float numOfMovements = 0;
public void onCreate() {
super.onCreate();
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
sensorManager.registerListener(proximitySensorEventListener, proximitySensor,SensorManager.SENSOR_DELAY_NORMAL);
maxSensorValue = proximitySensor.getMaximumRange();
}
#Override
public void onSensorChanged(SensorEvent event) {
if(lastWaveTime + WAVE_TIME > System.currentTimeMillis()) {
System.out.println("Reset timing...");
lastWaveTime = System.currentTimeMillis();
numOfMovements = 0;
lastSensorValue = event.values[0];
} else if((event.values[0] != maxSensorValue && lastSensorValue == maxSensorValue) || (event.values[0] == maxSensorValue && lastSensorValue != maxSensorValue) ){
numOfMovements++;
if(numOfMovements == WAVE_NEEDED_MOVEMENTS) {
System.out.println("WAVE EVENT");
lastWaveTime = System.currentTimeMillis();
numOfMovements = 0;
}
}
}
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 in the process of developing an Android music player which will do the the following actions once a shake action is detected. Actions: 1. Do Nothing 2. Play or Pause 3. Next Song 4. Previous Song
I have created a Service class for the shaking action and it is as follows.
public class Shaker extends Service implements SensorEventListener {
SharedPreferences sharedPreferences;
private static final int MIN_TIME_BETWEEN_SHAKES_MILLISECS = 1000;
private long mLastShakeTime;
private SensorManager sensorManager;
private static final String SHAKE_ACTION_PREFERENCE = "shake_action_preference";
private static final String SHAKE_THRESHOLD_PREFERENCE = "shake_threshold_preference";
#Override
public IBinder onBind(Intent intent) {
return null;
}
public void onCreate() {
sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
super.onCreate();
}
public void onDestroy() {
super.onDestroy();
sensorManager.unregisterListener(this);
}
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this, sensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);
return START_STICKY;
}
public void onStart(Intent intent, int startId) {
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this, sensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
long curTime = System.currentTimeMillis();
if ((curTime - mLastShakeTime) > MIN_TIME_BETWEEN_SHAKES_MILLISECS) {
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
double acceleration = Math.sqrt(Math.pow(x, 2) +
Math.pow(y, 2) +
Math.pow(z, 2)) - SensorManager.GRAVITY_EARTH;
Log.d("Acceleration", "Acceleration is " + acceleration + "m/s^2");
String threshold = sharedPreferences.getString(SHAKE_THRESHOLD_PREFERENCE, "medium");
float SHAKE_THRESHOLD;
if(threshold.equals("high"))
SHAKE_THRESHOLD = 40.5f;
else if(threshold.equals("low"))
SHAKE_THRESHOLD = 15.5f;
else
SHAKE_THRESHOLD = 25.5f;
if (acceleration > SHAKE_THRESHOLD) {
mLastShakeTime = curTime;
Log.d("Shake", "Shake, Rattle, and Roll");
String opt = sharedPreferences.getString(SHAKE_ACTION_PREFERENCE, "nothing");
Log.d("SharedPreference", opt);
Log.d("SharedPreference", threshold);
if(opt.equals("play")) {
MusicPlayer.playOrPause();
} else if(opt.equals("next")) {
MusicPlayer.next();
} else if(opt.equals("prev")) {
MusicPlayer.previous(getApplicationContext(), false);
}
}
}
}
}
}
But when I run the apk files in actual devices, the shaking function is working only on certain phones and not working for all the mobiles.
I have tried on different mobiles using same Android OS, but it is working in one and not working in the other.
I couldn't figure out why it is like this. Can anybody suggest a solution for this?
I had this problem. onSensorChanged method is called for any changes but in some devices, it is called more than once.It cause problem in logic of the code.
I solved this problem by adding a private static boolean variable. (It causes this method called once).Once this method executes,this variable becomes true.
#Override
public void onSensorChanged(SensorEvent event) {
if(!variable) {
variable=true;
...
...
variable=false;
}
}