Hi I want to use GyroSensor in Android. I want to get value of GyroSensor on logcat. But, I can't print value on logcat. error name is "Sensor or listener is null". My code is under there. please help me. Plus, I used Api 25 amulator. If my code is wrong, you can give other code.
public class MainActivity extends AppCompatActivity {
private SensorManager mSensorManager = null;
private SensorEventListener mGyroLis;
private Sensor mGyroSensor = null;
private double timestamp;
private double pitch;
private double roll;
private double yaw;
private double dt;
private double RAD2DGR = 180 / Math.PI;
private static final float NS2S = 1.0f/10000000000.0f;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mGyroSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
mGyroLis = new GyroscopeListener();
findViewById(R.id.a_start).setOnTouchListener(new View.OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event){
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
mSensorManager.registerListener(mGyroLis, mGyroSensor, SensorManager.SENSOR_DELAY_UI);
break;
case MotionEvent.ACTION_UP:
mSensorManager.unregisterListener(mGyroLis);
break;
}
return false;
}
});
}
#Override
public void onPause(){
super.onPause();
Log.e("LOG","onpause()");
mSensorManager.unregisterListener(mGyroLis);
}
#Override
public void onDestroy(){
super.onDestroy();
Log.e("LOG","ondestroy()");
mSensorManager.unregisterListener(mGyroLis);
}
private class GyroscopeListener implements SensorEventListener {
#Override
public void onSensorChanged(SensorEvent event){
double gyroZ = event.values[2];
dt = (event.timestamp - timestamp) * NS2S;
timestamp = event.timestamp;
if(dt - timestamp*NS2S != 0){
yaw = yaw + gyroZ*dt;
Log.d("LOG", "GYROSCOPE [z]:" + String.format("%.4f", event.values[2])+"[yaw]:"+String.format("%.4f", yaw+RAD2DGR));
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy){
}
}
}
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'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;
}
}
(Now it works perfectly)I am new to android development and I have written an showActivity to show my result data from another class. In that class I implement a sensorEventListener and get sensor data. But when I want to display data in my showActivity, I get nothing to show. All the data is 0(or false) and I dont know what's wrong with my code. It's much appreciated if you can give me some advise on how to fix it. Thanks a lot.
This is my showActivity:
public class MapShowActivity extends AppCompatActivity {
public SensorUse mySensorUse ;
private TextView myText;
private Button myButton;
private Timer timer = new Timer();
private int count = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mySensorUse = new SensorUse(MapShowActivity.this);
setContentView(R.layout.activity_map_show);
myText = (TextView)findViewById(R.id.orientation);
}
public void startTimer(){
timer.scheduleAtFixedRate(detectNewOrientation, 100, 100);
}
TimerTask detectNewOrientation = new TimerTask(){
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
myText.setText(String.valueOf(mySensorUse.getOx()));
}
});
}
};
#Override
protected void onResume() {
super.onResume();
mySensorUse.sensorRegister(MapShowActivity.this);
startTimer();
}
#Override
protected void onPause() {
super.onPause();
mySensorUse.sensorUnregister();
}
}
And this is my Sensor class:
public class SensorUse implements SensorEventListener{
private float[] accValues = new float[3];
private float[] magValues = new float[3];
private float[] orientationValues = new float[4];
private float[] resultRotationMatrix = new float[16];
public float ax;
public float ay;
public float az;
public float sumAcc;
public float ox;
public static boolean flag = false;
public boolean rotationMatrixGenerated;
private SensorManager mySensorManager;
private Sensor accSencor, magSensor;
public SensorUse(Context context){
}
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION){
accValues = event.values.clone();
ax = accValues[0];
ay = accValues[1];
az = accValues[2];
sumAcc = (float) Math.sqrt(ax*ax + ay*ay + az*az);
flag = true;
}
else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD){
magValues = event.values.clone();
}
if (accValues != null && magValues != null){
rotationMatrixGenerated = SensorManager.getRotationMatrix(resultRotationMatrix,
null, accValues, magValues);
if(rotationMatrixGenerated) {
SensorManager.getOrientation(resultRotationMatrix, orientationValues);
ox = (float) Math.toDegrees(orientationValues[0]);
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void sensorRegister(Context context){
mySensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
accSencor = mySensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
magSensor = mySensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
mySensorManager.registerListener(this, accSencor, SensorManager.SENSOR_DELAY_GAME);
mySensorManager.registerListener(this, magSensor, SensorManager.SENSOR_DELAY_GAME);
}
public void sensorUnregister(){
mySensorManager.unregisterListener(this, accSencor);
mySensorManager.unregisterListener(this, magSensor);
}
public float getAx(){
return ax;
}
public float getOx(){
return ox;
}
}
App doesn't know which class will be handling the sensor data.
You have to register your sensor class (SensorUse) object
to get accelerometer data.
Find example code below:
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
senAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(mySensorUse, senAccelerometer , SensorManager.SENSOR_DELAY_NORMAL);
sensorManger is object of SensorManager
mySensorUse is class that has implemented SensorEventListener
I am working on an app in which i need to make text scroll based on device tilt information. I have tried few solutions but nothing seems to be working. I am able to get the tilting information using the following code :-
public class SensorActivity extends Activity implements SensorEventListener {
float[] mMagnetValues = new float[3];
float[] mAccelValues = new float[3];
float[] mOrientationValues = new float[3];
float[] mRotationMatrix = new float[9];
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SensorManager sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
SensorManager.SENSOR_DELAY_NORMAL);
TextView txt1 = (TextView) findViewById(R.id.textView1);
}
#Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mAccelValues, 0, 3);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
System.arraycopy(event.values, 0, mMagnetValues, 0, 3);
break;
}
SensorManager.getRotationMatrix(mRotationMatrix, null, mAccelValues, mMagnetValues);
SensorManager.getOrientation(mRotationMatrix, mOrientationValues);
Log.e("Values", mOrientationValues[0] + " " + mOrientationValues[1] + " " + mOrientationValues);
};
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) { }
public void scrollTextUp() {
ScrollView scrollView = (ScrollView)findViewById(R.id.scroll);
scrollView.scrollBy(0, 5);
}
public void scrollTextBottom() {
ScrollView scrollView = (ScrollView)findViewById(R.id.scroll);
scrollView.scrollBy(0, -5);
}
}
I assume that mOrientationValues[1] needs to be used to scroll but how to use this value is a big question for me right now. Please help.
Any help would be really appreciated. If you have found any good tutorial or example please share it.
Thanks.
So after playing around for few hours, this is the solution i used. Requirements for my apps was to make text scroll in a readable speed, that is why i used a constant scroll speed but i welcome everyone to improve this answer based on tilt speed etc so it could help others as well.
TiltScrollController Class -
public class TiltScrollController implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mAccelSensor;
private Sensor mMagnetSensor;
private float mCurrentPosition;
private boolean isCurrentPositionSet = false;
private int count = 0;
private ScrollListener mListener;
float[] mMagnetValues = new float[3];
float[] mAccelValues = new float[3];
float[] mOrientationValues = new float[3];
float[] mRotationMatrix = new float[9];
public TiltScrollController(SensorManager sensorManager, ScrollListener listener) {
mSensorManager = sensorManager;
mListener = listener;
mAccelSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mMagnetSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}
#Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mAccelValues, 0, 3);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
System.arraycopy(event.values, 0, mMagnetValues, 0, 3);
break;
}
SensorManager.getRotationMatrix(mRotationMatrix, null, mAccelValues, mMagnetValues);
SensorManager.getOrientation(mRotationMatrix, mOrientationValues);
if (!isCurrentPositionSet) {
mCurrentPosition = mOrientationValues[1];
count += 1;
if(count == 2) {
isCurrentPositionSet = true;
}
}
if(mCurrentPosition + 0.25 < mOrientationValues[1]) {
//Scroll to Top
mListener.onTiltUp();
}
else if (mCurrentPosition - 0.25 > mOrientationValues[1]) {
//Scroll to Bottom
mListener.onTiltDown();
}
};
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
public void requestAllSensors() {
mSensorManager.registerListener(this, mAccelSensor, SensorManager.SENSOR_DELAY_NORMAL);
mSensorManager.registerListener(this, mMagnetSensor, SensorManager.SENSOR_DELAY_NORMAL);
}
public void killAllSensors() {
mSensorManager.unregisterListener(this, mAccelSensor);
mSensorManager.unregisterListener(this, mMagnetSensor);
}
public interface ScrollListener {
public void onTiltUp();
public void onTiltDown();
}
}
Your activity class -
public class SensorActivity extends Activity {
private ScrollView mScrollView;
private TiltScrollController mTiltScrollController;
private SensorManager mSensorManager;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mScrollView = (ScrollView)findViewById(R.id.scroll);
mSensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
mTiltScrollController = new TiltScrollController(mSensorManager, new TiltScrollListener());
}
public void scrollTextUp() {
mScrollView.smoothScrollBy(0, 6);
}
public void scrollTextBottom() {
mScrollView.smoothScrollBy(0, -6);
}
#Override
protected void onPause() {
mTiltScrollController.killAllSensors();
super.onPause();
}
public class TiltScrollListener implements TiltScrollController.ScrollListener {
#Override
public void onTiltUp() {
scrollTextUp();
}
#Override
public void onTiltDown() {
scrollTextBottom();
}
}
}
Cheers!!