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!!
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.
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){
}
}
}
(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 try to get orientation on my Android Emulator by SensorManager.getOrientation. Before this i use SensorManager.getRotationMatrix to get rotation matrix, but this always return false.
Here is code of my Activity:
public class MainActivity extends Activity implements SurfaceHolder.Callback, View.OnClickListener{
public final static String DEBUG_TAG = "MainActivity";
private SensorManager sensorManager;
private SurfaceView preview;
private float[] mGravs;
private float[] mGeoMags;
private float[] mRotationM;
private float[] mOrientation;
private Sensor mAccelerometer;
private Sensor mMagneticField;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
preview = (SurfaceView)findViewById(R.id.SurfaceView1);
sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mMagneticField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
mGravs = new float[3];
mGeoMags = new float[3];
mRotationM = new float[16];
mOrientation = new float[3];
List<Sensor> sensorList = sensorManager.getSensorList(Sensor.TYPE_ALL);
for (int nI = 0; nI < sensorList.size(); nI++) {
Log.d(DEBUG_TAG, sensorList.get(nI).getName());
}
}
private SensorEventListener sensorEventListener = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent event)
{
synchronized (this) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mGravs, 0, 3);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
System.arraycopy(event.values, 0, mGeoMags, 0, 3);
break;
default:
return;
}
if (mGravs != null && mGeoMags != null) {
boolean bSuccess = SensorManager.getRotationMatrix(mRotationM, null, mGravs, mGeoMags);
if (bSuccess) {
SensorManager.getOrientation(mRotationM, mOrientation);
}
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
};
private boolean openHardware()
{
sensorManager.registerListener(sensorEventListener, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(sensorEventListener, mMagneticField, SensorManager.SENSOR_DELAY_NORMAL);
return true;
}
private void closeHardware()
{
sensorManager.unregisterListener(sensorEventListener);
}
#Override
protected void onResume()
{
super.onResume();
openHardware();
}
#Override
protected void onPause()
{
super.onPause();
closeHardware();
}
#Override
protected void onStop()
{
closeHardware();
super.onStop();
}
}
Ok, this problem occur because magnetic field sensor always return [0.0, 0.0, 0.0].
How can i make magnetic field sensor return something else?
I had the same problem. Everything got false
This answer has helped me: https://stackoverflow.com/a/14224122/1549127
Hi I am building a 3D game for Android.
I am currently trying to add a sensor to my game that allows the player to tilt the android as its controls.
Ideally I would like to use the ORIENTATION sensor, but I noticed it has been deprecated. Does anyone know how to detect tilt in the android and doesn't use this sensor?
There is no actual "orientation" sensor - this is (was) actually a composite sensor, generated from a combination of the accelerometer and the magnometer.
From http://developer.android.com/reference/android/hardware/SensorEvent.html
"This sensor type exists for legacy reasons, please use getRotationMatrix() in conjunction with remapCoordinateSystem() and getOrientation() to compute these values instead."
public class OrientationTestActivity extends Activity implements SensorEventListener
{
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private Sensor mMagnetometer;
private float[] mLastAccelerometer = new float[3];
private float[] mLastMagnetometer = new float[3];
private boolean mLastAccelerometerSet = false;
private boolean mLastMagnetometerSet = false;
private float[] mR = new float[9];
private float[] mOrientation = new float[3];
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
}
protected void onResume() {
super.onResume();
mLastAccelerometerSet = false;
mLastMagnetometerSet = false;
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
mSensorManager.registerListener(this, mMagnetometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor == mAccelerometer) {
System.arraycopy(event.values, 0, mLastAccelerometer, 0, event.values.length);
mLastAccelerometerSet = true;
} else if (event.sensor == mMagnetometer) {
System.arraycopy(event.values, 0, mLastMagnetometer, 0, event.values.length);
mLastMagnetometerSet = true;
}
if (mLastAccelerometerSet && mLastMagnetometerSet) {
SensorManager.getRotationMatrix(mR, null, mLastAccelerometer, mLastMagnetometer);
SensorManager.getOrientation(mR, mOrientation);
Log.i("OrientationTestActivity", String.format("Orientation: %f, %f, %f",
mOrientation[0], mOrientation[1], mOrientation[2]));
}
}
}