I am working with accelerometer for android, I do not understand why the three axis for them which I have assigned to mSensorX, mSensorY and mSensorZ are labelled as unused when I have used them in the onSensorChange, could someone please help me understand this.
package com.example.imageaccel;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.widget.TextView;
public class ImageAccelActivity extends Activity implements SensorEventListener {
/** Called when the activity is first created. */
TextView x, y, z;
private float mSensorX;
private float mSensorY;
private float mSensorZ;
private Bitmap car;
private SensorManager sm = null;
// Bitmap car1;
// float x1, y1, z1, sensorX, sensorY, sensorZ;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
x = (TextView)findViewById(R.id.x_axis);
y = (TextView)findViewById(R.id.y_axis);
z = (TextView)findViewById(R.id.z_axis);
SensorManager sm = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
if (sm.getSensorList(Sensor.TYPE_ACCELEROMETER).size() !=0){
Sensor s = sm.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
sm.registerListener(this, s, SensorManager.SENSOR_DELAY_NORMAL);
}
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
sm.registerListener(this, sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
sm.unregisterListener(this);
super.onPause();
}
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent ev) {
// TODO Auto-generated method stub
if(ev.sensor.getType()==Sensor.TYPE_ACCELEROMETER){
mSensorX = ev.values[0];
mSensorY = ev.values[1];
mSensorZ = ev.values[2];
}
}
protected void onDraw(Canvas canvas) {
/*
* draw the background
*/
canvas.drawBitmap(car, 0, 0, null);
}
}
You're setting them to a value but that's only half the story. The complaint is most likely that you're never using them after that. It's similar to the C code:
int main (void) {
int a = 1;
return 0;
}
While that compiles and runs fine, you do get a warning (using gcc -Wall) that:
warning: unused variable 'a'
Quick way to check this theory, put a:
System.out.println (mSensorX + "," + mSensorY + "," + mSensorZ);
(or some other sort of use) following the setting and see if the warning disappears.
I think there is a warning because of the if statement there..In some cases they won't be used and hence the warning..That's my opinion:)
Related
This SensorTestActivity.java in which Android Studio marks R in red:
package szabojanos.accelerometer;
import android.app.Activity;
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.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
public class SensorTestActivity extends Activity implements SensorEventListener {
private SensorManager sensorManager;
private boolean color = false;
private View view;
private long lastUpdate;
#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.GREEN);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
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;
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 = event.timestamp;
if (accelationSquareRoot >= 2) //
{
if (actualTime - lastUpdate < 200) {
return;
}
lastUpdate = actualTime;
Toast.makeText(this, "Az eszköz fel volt rázva", Toast.LENGTH_SHORT)
.show();
if (color) {
view.setBackgroundColor(Color.GREEN);
} else {
view.setBackgroundColor(Color.RED);
}
color = !color;
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(this,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
And this is android_sensor_test.xml layout file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
I was following this Tutorial: http://www.vogella.com/tutorials/AndroidSensor/article.html#tutorial-accelerometer
Any help would be appreciated.
Clean-Rebuild Your project at first and then Import R
Basic Syntax
import szabojanos.accelerometer.R;
FYI
Call requestWindowFeature after super.onCreate.
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);// Call this after super.onCreate
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
You are missing the .R import. You could auto fix this by going on the red line and press the combination ALT+ENTER and choose import yourpackage.R
import yourpackage.R and if there is any issues in youe xml file please resolve then try to clean and build.
I am doing a project which is detecting the direction of moving by using accelerometer However, the 3 axis of accelerometer will not always follow the world xyz plane as we tilt or rotate our phone. I was trying to fix it by getting the pitch and roll from the phone and convert the axis of the phone to the world xyz axis. But now my pitch and roll always get 0. Can anyone help me ? or is there any other way to solve my problem? Thanks for the help!
package com.example.suntracking;
import android.app.Activity;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
public class AxisCheck extends Activity implements SensorEventListener{
Sensor accelerometer,magnetometer;
float[] lastAccelerometer = new float[3];
float[] lastMagnetometer = new float[3];
boolean lastAccelerometerSet = false;
boolean lastMagnetometerSet = false;
SensorManager sm;
float pval,rval;
float[] mR = new float[9];
float[] mhold= new float[3];
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
initialize();
accelerometer = sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
magnetometer = sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
finish();
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
sm.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
sm.registerListener(this, magnetometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
sm.unregisterListener(this);
}
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
private void initialize() {
// TODO Auto-generated method stub
sm =(SensorManager)getSystemService(SENSOR_SERVICE);
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
if (event.sensor == accelerometer) {
System.arraycopy(event.values, 0, lastAccelerometer, 0, event.values.length);
lastAccelerometerSet = true;
} else if (event.sensor == magnetometer) {
System.arraycopy(event.values, 0, lastMagnetometer, 0, event.values.length);
lastMagnetometerSet = true;
}
if (lastAccelerometerSet && lastMagnetometerSet) {
SensorManager.getRotationMatrix(mR, null, lastAccelerometer, lastMagnetometer);
SensorManager.getOrientation(mR,mhold);
pval = Math.round(mhold[1]);
rval = Math.round(mhold[2]);
savePreferences();
}
}
private void savePreferences() {
// TODO Auto-generated method stub
SharedPreferences savedata = getSharedPreferences("savealldata",0);
Editor editor=savedata.edit();
editor.putFloat("pval", pval);
editor.putFloat("rval", rval);
editor.commit();
}
}
I am working on a game and have run into some issues. My architecture is something like this:
class GameView is used to draw bitmaps on my surfaces
class GameLoopThread is used to implement my game loop (if it wasn't obvious...)
class MovementUtils is used to hold all of my utilities related to moving objects
I want to house methods like gravity and movement controls in MovementUtils, but I'm having trouble actually updating the values in GameView. I tried using an intent, to no avail. I'll post my code, and maybe someone can show me what I should do. Also, ignore the Accelerometer lines, that's another problem entirely...
GameView.java
package com.example.connorgame;
import java.util.EventObject;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
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.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
public class GameView extends SurfaceView {
private Bitmap platform;
private Bitmap character;
private Bitmap background;
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private MainActivity mainactivity;
private MovementUtils moveutil;
public float charX = 0;
public float charY = 0;
private boolean isFalling = true;
private boolean isJumping = false;
private float initialJumpY = 0;
private int initialFrame;
private int currentFrame;
private int frameDifference;
public GameView(Context context) {
super(context);
gameLoopThread = new GameLoopThread(this);
mainactivity = (MainActivity) context;
moveutil = new MovementUtils();
holder = getHolder();
holder.addCallback(new Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
gameLoopThread.setRunning(true);
gameLoopThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
});
platform = BitmapFactory.decodeResource(getResources(), R.drawable.platform);
character = BitmapFactory.decodeResource(getResources(), R.drawable.character);
background = BitmapFactory.decodeResource(getResources(), R.drawable.background);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(background, 0, 0, null);
canvas.drawBitmap(platform, 30, 700, null);
canvas.drawBitmap(character, charX, charY, null);
moveutil.gravity(charY, isFalling);
if (charY > getHeight() - character.getHeight()) {
initialFrame = gameLoopThread.numFrames;
initialJumpY = charY;
isFalling = false;
isJumping = true;
}
if (isJumping == true && isFalling == false) {
currentFrame = gameLoopThread.numFrames;
frameDifference = (currentFrame - initialFrame);
charY = charY - 5;
if (charY == initialJumpY - 100) {
isJumping = false;
isFalling = true;
}
}
}
}
MovementUtils.java
package com.example.connorgame;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
public class MovementUtils {
public void gravity (float charY, boolean isFalling) {
if(isFalling == true){
charY = charY + 5;
}
}
}
If I understand what you're doing correctly, you're trying to have charY in the GameView class modified by the gravity function. The issue is that float is a primitive, so it is based by value and only the local copy will be modified. If you passed an object instead, the object would be modified.
One solution is probably to just return the new Y position instead of trying to make gravity() change the Y position.
Another solution is to pass the GameView to MovementUtils and let MovementUtils modify it.
In other words, you would pass the GameView like this new MovementUtils(this);
And the gravity function would call a void setCharY(int y); in GameView.
public class MovementUtils {
private GameView gameView;
public MovementUtils(GameView view) {
this.gameView = view;
}
public void gravity (float charY, boolean isFalling) {
if(isFalling == true){
charY = charY + 5;
gameView.setCharY(charY);
}
}
}
Java only supports passing by value
So when you call moveutil.gravity(charY, isFalling);
and change it within the function, e.g.
public void gravity (float charY, boolean isFalling) {
if(isFalling == true){
charY = charY + 5;
}
Such change only occur in the local copy of the variable charY and does not affect the instance variable charY defined in your GameView class
To solve this, you can define your variables as objects as well as the argument to your functions, e.g.
public void gravity (Float charY, boolean isFalling) {}
And in your GameView class:
private Float charX = 0; // why you define them public !?
private Float charY = 0;
Alternatively, you can pass an instance of your GameView class or create a ValueObject class (similar to Context object in android) and use it to pass arguments
The following example is taken from internet. In all the example the code is explained using a seprate thread for sensor manager. Could you please let me know why all the accelerometer is explained with a seperate thread for SensorManager
package com.example.myapp1;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.TextView;
import android.widget.Toast;
public class Accelerate extends Activity implements SensorEventListener {
float x, y, sensorX, sensorY;
Bitmap ball;
SensorManager sm;
Sensor s;
MyBringBackSurface ourSurfaceView;
public class MyBringBackSurface extends SurfaceView implements Runnable {
SurfaceHolder ourHolder;
Thread ourThread = null;
boolean isRunning = false;
public MyBringBackSurface(Context context) {
super(context);
Log.i("Notice","In constructor of mybringbacksurface");
ourHolder = getHolder();
}
public void pause() {
isRunning = false;
Log.i("Notice","In pause of mybringbacksurface");
while (true) {
try {
ourThread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
ourThread = null;
}
public void resume() {
Log.i("Notice","In resume of mybringbacksurface");
isRunning = true;
ourThread = new Thread(this);
ourThread.start();
}
public void run() {
// TODO Auto-generated method stub
Log.i("Notice","In run of mybringbacksurface");
while (isRunning) {
if (!ourHolder.getSurface().isValid())
continue;
Canvas canvas = ourHolder.lockCanvas();
canvas.drawRGB(02, 02, 150);
float centerX = canvas.getWidth() / 2;
float centerY = canvas.getHeight() / 2;
canvas.drawBitmap(ball, centerX - sensorX * 18, centerY
+ sensorY * 18, null);
ourHolder.unlockCanvasAndPost(canvas);
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
Log.i("Notice","In oncreate of of Accelerator");
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
sm = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sm.getSensorList(Sensor.TYPE_ACCELEROMETER).size() != 0) {
s = sm.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
sm.registerListener(this, s, SensorManager.SENSOR_DELAY_NORMAL);
}
ball = BitmapFactory.decodeResource(getResources(), R.drawable.greenball);
x = y = sensorX = sensorY = 0;
ourSurfaceView = new MyBringBackSurface(this);
ourSurfaceView.resume();
setContentView(ourSurfaceView);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
Log.i("Notice","In pause of Accelerator");
sm.unregisterListener(this, s);
super.onPause();
ourSurfaceView.pause();
}
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
public void onSensorChanged(SensorEvent e) {
// TODO Auto-generated method stub
Log.i("Notice","In sensorchanged of of Accelerator");
try {
Thread.sleep(32);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
sensorX = e.values[0];
sensorY = e.values[1];
}
}
Because the continuous while loop in the run() method would block the main thread and cause your app to be shut down with an "Application Not Responding" or ANR.
Anytime you have a long running loop like that, it must happen in a separate thread.
I have implemented a program that is able to get the distance and direction of other person. Now I want to show this information by a dynamic arrow pointing to the other person direction (like a needle) and as the user moves his phone, the arrow will change its direction to still point the other person direction.
So, it is to be implemented like this: an activity will pass the direction (of the other person) in degrees (0<= x <=360) to another activity whose task is to graphically show the arrow.
I know how to know the azimuth value and thereby calculate the degree of rotation of arrow for a particular direction value (x). I know the logic of implementation but I have no knowledge about graphic, animation etc.
Any quick Help is highly appreciated.
This is the code which meets the requirement. I dont know but a better solution may exists :-
package com.visd.giraffe;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.drawable.BitmapDrawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;
import android.widget.TextView;
public class arrowhandler extends Activity implements SensorEventListener {
Matrix mtx = new Matrix();
ImageView img;
Bitmap bmp ;
int w,h;
float d = 0;
float oldval = 0,currentrot = 0, rotate = 0,senserotat;
private SensorManager sensorManager = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Get a reference to a SensorManager
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
setContentView(R.layout.mmmain);
String[] arrs = getIntent().getExtras().getStringArray("SMSR");
int degr = arrs[0].indexOf("Dgr:");
String msgg = "Location of " + arrs[0].substring((arrs[0].indexOf("nosss"))+5) + "\n\n" + arrs[0].substring(0, degr);
Log.d("AOA",arrs[0].substring(degr+4));
d = (Float.valueOf(arrs[0].substring(degr+4, arrs[0].indexOf("nosss")))).floatValue();
Log.d("AOA dv", Float.toString(d));
if (d>0)
{
d = d+180;
}
else if (d<0)
{
d = 180 - (Math.abs(d));
}
Log.d("AOA dv", "2" + Float.toString(d));
Log.d("AOA",Float.toString(d));
TextView t = (TextView) findViewById(R.id.textView1);
t.setText(msgg);
img=(ImageView)findViewById(R.id.imageView1);
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.bluearrow);
// Getting width & height of the given image.
w = bmp.getWidth();
h = bmp.getHeight();
}
// This method will update the UI on new sensor events
public void onSensorChanged(SensorEvent sensorEvent) {
synchronized (this) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
}
if (sensorEvent.sensor.getType() == Sensor.TYPE_ORIENTATION) {
senserotat = d-sensorEvent.values[0];
if (senserotat < 0)
{
senserotat = 360 - (Math.abs(senserotat));
}
rotate = (360-currentrot)+senserotat;
if (rotate>360)
{
rotate = rotate-360;
}
mtx.postRotate(rotate);
// Rotating Bitmap
Bitmap rotatedBMP = Bitmap.createBitmap(bmp, 0, 0, w, h, mtx, true);
BitmapDrawable bmd = new BitmapDrawable(rotatedBMP);
img.setImageDrawable(bmd);
currentrot = senserotat;
//Log.d("TTTT", Float.toString(sensorEvent.values[0]));
}
}
}
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
protected void onResume() {
super.onResume();
// Register this class as a listener for the accelerometer sensor
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
// ...and the orientation sensor
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION), SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
protected void onStop() {
// Unregister the listener
sensorManager.unregisterListener(this);
super.onStop();
}
}