I created a view from ImageView. this imageview is a ball on screen(Depending on the acceleration sensor). now how can i do getting current positon it on the screen ?because I don't want the ball be out of the screen. like :
All my code :
public class MainActivity extends Activity implements SensorEventListener {
private SensorManager sensorManager;
private Sensor accelerometer;
AnimatedView animatedView = null;
ShapeDrawable mDrawable = new ShapeDrawable();
public static int x;
public static int y;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
accelerometer = sensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
animatedView = new AnimatedView(this);
setContentView(animatedView);
}
#Override
protected void onResume() {
super.onResume();
sensorManager.registerListener(this, accelerometer,
SensorManager.SENSOR_DELAY_GAME);
}
#Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
x -= ((int) event.values[0])*4;
y += ((int) event.values[1])*4;
}
}
public class AnimatedView extends ImageView {
static final int width = 100;
static final int height = 100;
public AnimatedView(Context context) {
super(context);
// TODO Auto-generated constructor stub
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xffffAC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
#Override
protected void onDraw(Canvas canvas) {
mDrawable.setBounds(x, y, x + width, y + height);
mDrawable.draw(canvas);
invalidate();
}
}
}
other question,
Which one is better to use?TYPE_ACCELEROMETER or TYPE_GRAVITY?
I want to support more devices.
You already know the position, which is your x and y.
What you need to do is to stop these values from falling of the screen.
First, get the size of your screen:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
now size holds the screenSize.
Then add the following to your method
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
x -= ((int) event.values[0])*4;
y += ((int) event.values[1])*4;
if(x < 0)
x = 0;
else if(x > size.x)
x = size.x
if(y < 0)
y = 0;
else if (y > size.y)
y = size.y
}
I would also recomend that you use a thread to handle the x and y position. You can control how often a thread will run, the sensor will trigger every time an event happens.
For a better understanding of the Android Sensors, read this: http://www.codeproject.com/Articles/729759/Android-Sensor-Fusion-Tutorial
Some sensors are hardware sensors, others are software sensors that combine hardware sensors.
In your case: Im not sure what the purpose of your app is, but I guess that you want to move the ball by tilting the screen. I would say that GRAVITY works perfectly for that.
You can retrieve the location of a view by calling the getTop() and getLeft() functions which return x and y coordinates respectively, reference: http://developer.android.com/reference/android/view/View.html#Position
Choosing the type depends on the goal offcourse, using Acceleromtere means measuring the acceleration of the device whilst gravity measures the gravitational force on the device.
Please note that acceleromter values include gravity values as mentioned here: http://developer.android.com/guide/topics/sensors/sensors_motion.html
I personally would suggest using Accelerometer or the Gyroscope. The gyroscope doesn't use acceleration but the actual orientation of the device in space, which might be what you are actually looking for.
Related
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.;
}
}
}
I had created dynamic line graph using AChartEngine Api, which shows the changes in G-Force value. All works fine but when graph moves ahead in X-axis i have to manually scroll in X-axis to see it further, please check my image below if you are not getting me properly.
how can i make it auto scrollable in x-axis to avoid manually scrolling?
Following is my code
public class GraphActivity extends Activity implements SensorEventListener{
private LinearLayout lyGforce;
//=== G-force =======
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private float gOffset;
private boolean calibrate;
private static TimeSeries timeSeriesGforce;
private static XYMultipleSeriesDataset datasetGforce;
private static XYMultipleSeriesRenderer rendererGforce;
private static XYSeriesRenderer rendererSeriesGforce;
private static GraphicalView viewGforce;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.mainactivity);
lyGforce = (LinearLayout) findViewById(R.id.lygforce);
//=========== G-force =======
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
datasetGforce = new XYMultipleSeriesDataset();
rendererGforce = new XYMultipleSeriesRenderer();
rendererGforce.setApplyBackgroundColor(true);
rendererGforce.setBackgroundColor(Color.argb(100, 50, 50, 50));
rendererGforce.setAxisTitleTextSize(16);
rendererGforce.setChartTitleTextSize(20);
rendererGforce.setLabelsTextSize(15);
rendererGforce.setLegendTextSize(15);
rendererGforce.setMargins(new int[] { 20, 30, 15, 0 });
rendererGforce.setZoomButtonsVisible(true);
rendererGforce.setPointSize(10);
rendererGforce.setShowGrid(true);
rendererGforce.setGridColor(Color.WHITE);
rendererSeriesGforce = new XYSeriesRenderer();
rendererSeriesGforce.setColor(Color.GREEN);
rendererSeriesGforce.setLineWidth(2);
rendererGforce.addSeriesRenderer(rendererSeriesGforce);
timeSeriesGforce = new TimeSeries("G-Force");
datasetGforce.addSeries(timeSeriesGforce);
viewGforce = ChartFactory.getTimeChartView(this, datasetGforce, rendererGforce, "");
viewGforce.refreshDrawableState();
viewGforce.repaint();
lyGforce.addView(viewGforce);
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
// ============= G-force ==================//
calibrate = true;
mSensorManager.registerListener(this, mAccelerometer,
SensorManager.SENSOR_DELAY_UI);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
//========== G-force=============//
mSensorManager.unregisterListener(this);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
//========== G-force=============//
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
float x = event.values[0];
float y = event.values[1]; // Use to calculate G-Force value
float z = event.values[2];
if(calibrate)
gOffset = y - SensorManager.GRAVITY_EARTH;
double gForce = ((y - gOffset) / SensorManager.GRAVITY_EARTH);
timeSeriesGforce.add(new Date(), gForce);
rendererGforce.setXAxisMax(rendererGforce.getXAxisMax() + 30);
rendererGforce.setXAxisMin(rendererGforce.getXAxisMin() + 30);
viewGforce.repaint();
Log.e("NIRAV","G-Force: "+String.valueOf(gForce));
calibrate = false;
break;
default:
break;
}
}
}
You can do this by changing the visible area on the X axis:
renderer.setXAxisMin(min);
renderer.setXAxisMax(max);
I am trying to get the tilt angel from Android orientation.
The values which i am getting from
SensorManager.getOrientation(mRotationMatrix, mValuesOrientation)
is not degrees.... On putting the phone on a horizontal plane it returns improper values
I have tries using few methods found on net without any luck..
So far tried
Math.sin(Math.toRadians(mValuesOrientation[0]));
Math.toDegrees(mValuesOrientation[0]);
and others
Code is below
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SensorManager sensorManager = (SensorManager) this.getSystemService(SENSOR_SERVICE);
final float[] mValuesMagnet = new float[3];
final float[] mValuesAccel = new float[3];
final float[] mValuesOrientation = new float[3];
final float[] mRotationMatrix = new float[9];
final Button btn_valider = (Button) findViewById(R.id.button1);
final TextView txt1 = (TextView) findViewById(R.id.editText1);
final SensorEventListener mEventListener = new SensorEventListener() {
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent event) {
// Handle the events for which we registered
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
System.arraycopy(event.values, 0, mValuesAccel, 0, 3);
break;
case Sensor.TYPE_MAGNETIC_FIELD:
System.arraycopy(event.values, 0, mValuesMagnet, 0, 3);
break;
}
};
};
// You have set the event lisetner up, now just need to register this with the
// sensor manager along with the sensor wanted.
setListners(sensorManager, mEventListener);
btn_valider.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
SensorManager.getRotationMatrix(mRotationMatrix, null, mValuesAccel, mValuesMagnet);
SensorManager.getOrientation(mRotationMatrix, mValuesOrientation);
String test;
/* double accX = -mValuesOrientation[0]/SensorManager.GRAVITY_EARTH;
double accY = -mValuesOrientation[1]/SensorManager.GRAVITY_EARTH;
double accZ = -mValuesOrientation[2]/SensorManager.GRAVITY_EARTH;
double totAcc = Math.sqrt((accX*accX)+(accY*accY)+(accZ*accZ));
double tiltX = Math.asin(accX/totAcc);
double tiltY = Math.asin(accY/totAcc);
double tiltZ = Math.asin(accZ/totAcc);*/
//float tiltX = mValuesOrientation[0] * 57.2957795f;
//float tiltY = mValuesOrientation[1] * 57.2957795f;
//float tiltZ = mValuesOrientation[2] * 57.2957795f;
//double tiltX =Math.sin(Math.toRadians(mValuesOrientation[0]));
//double tiltY =Math.sin(Math.toRadians(mValuesOrientation[1]));
//double tiltZ =Math.sin(Math.toRadians(mValuesOrientation[2]));
//String.format("Azimuth: %.2f\n\nPitch:%.2f\nRoll", azimuth,
// pitch, roll);
double tiltX = Math.toDegrees(mValuesOrientation[0]);
double tiltY = Math.toDegrees(mValuesOrientation[1]);
double tiltZ = Math.toDegrees(mValuesOrientation[2]);
test = "results New: " +tiltX +" "+tiltY+ " "+ tiltZ;
Log.d("test", test);
txt1.setText(test);
}
});
}
public void setListners(SensorManager sensorManager, SensorEventListener mEventListener)
{
sensorManager.registerListener(mEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(mEventListener, sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
}
The getOrientation return the azimuth, pitch and roll in Radian.
mValuesOrientation[0] is the azimuth, rotation about the z-axis.
mValuesOrientation[1] is the pitch, rotation about the x-axis.
mValuesOrientation[2] is the roll, rotation about the y-axis.
If your phone is lying flat on a table, the pitch and roll should be almost 0, but not the azimuth. It is only 0 if your phone longer size, the y axis, is pointing exactly toward magnetic North.
You can use pitch or roll (depending on the device orientation) to calculate the inclination of the phone, ie the angle between the surface of the screen and the world xy plane or you can use the inclination of my answer at How to measure the tilt of the phone in XY plane using accelerometer in Android
You should also read my answer at Convert magnetic field X, Y, Z values from device into global reference frame to get a better understanding of the rotation matrix.
I want to display the compass(Image View) on device at a specific location.I tried Like this below code to display the compass view on device but the thing is i need to display at Specific location and small view only but it occupies entire screen space.Can you help me to fix an compass image at specific location.Using this line of code i am getting an image form Drawable folder. this.setImageResource(R.drawable.compassrose); So how to fix that image at specific location.
Class1:-
public class Compass extends Activity implements SensorListener {
SensorManager sensorManager;
static final int sensor = SensorManager.SENSOR_ORIENTATION;
Rose rose;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//http://ofps.oreilly.com/titles/9781449390501/Android_System_Services.html
// Set full screen view
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
//FLAG_FULLSCREEN
//FLAG_SCALED
rose = new Rose(this);
setContentView(rose);
// get sensor manager
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
}
// register to listen to sensors
#Override
public void onResume() {
super.onResume();
sensorManager.registerListener(this, sensor);
}
// unregister
#Override
public void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
// Ignore for now
public void onAccuracyChanged(int sensor, int accuracy) {
}
// Listen to sensor and provide output
public void onSensorChanged(int sensor, float[] values) {
if (sensor != Compass.sensor)
return;
int orientation = (int) values[0];
rose.setDirection(orientation);
}
}
Class 2:-
public class Rose extends ImageView {
Paint paint;
int direction = 0;
public Rose(Context context) {
super(context);
paint = new Paint();
paint.setColor(Color.WHITE);
paint.setStrokeWidth(2);
paint.setStyle(Style.STROKE);
this.setImageResource(R.drawable.compassrose);
}
#Override
public void onDraw(Canvas canvas) {
int height = this.getHeight();
int width = this.getWidth();
canvas.rotate(direction, width / 2, height / 2);
super.onDraw(canvas);
}
public void setDirection(int direction) {
this.direction = direction;
this.invalidate();
}
}
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
rose = new Rose(this);
txtorientation = (TextView) findViewById(R.id.textView1);
compassLayout = (RelativeLayout)findViewById(R.id.CompassLayout);
compassLayout.addView(rose);
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
Log.d("Compass", "onCreated");
}
Are you asking how to position an ImageView in an Android layout? Have you tried with XML, or does it need to be set programmatically?
If you are just trying to position an ImageView, then try going through some of the layout tutorials: http://developer.android.com/resources/tutorials/views/index.html
If not, then please add more detail to your question
I have seen a few code examples of 1.0 / 1.1 but since a lot of that is deprecated now I was hoping to find a nice 1.5+ example. I have some code here that I wrote but it doesn't really work properly. Any help would be great, thanks!
public class collectAccel extends Activity implements SensorEventListener,
OnClickListener{
private SensorManager sensorMgr;
private TextView xLabel, yLabel, zLabel;
private Button StartBtn;
private List<Sensor> sensorList;
private float x, y, z;
private long lastUpdate = -1;
// deltas for calibration
private float cx, cy, cz;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
xLabel = (TextView) findViewById(R.id.x_label);
yLabel = (TextView) findViewById(R.id.y_label);
zLabel = (TextView) findViewById(R.id.z_label);
StartBtn = (Button) findViewById(R.id.Button1);
StartBtn.setOnClickListener(this);
}
#Override
public void onClick(View arg0) {
if (xLabel.getVisibility() != 1)
xLabel.setVisibility(1);
if (yLabel.getVisibility() != 1)
yLabel.setVisibility(1);
if (zLabel.getVisibility() != 1)
zLabel.setVisibility(1);
}
#Override
protected void onPause() {
super.onPause();
sensorMgr.unregisterListener((SensorEventListener)this, sensorList.get(0));
sensorMgr = null;
cx = 0;
cy = 0;
cz = 0;
}
#Override
protected void onResume() {
super.onResume();
sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
sensorList = sensorMgr.getSensorList(Sensor.TYPE_ACCELEROMETER);
boolean accelSupported = sensorMgr.registerListener((SensorEventListener)this,
sensorList.get(0),
SENSOR_DELAY_UI);
if (!accelSupported) {
// on accelerometer on this device
sensorMgr.unregisterListener((SensorEventListener)this, sensorList.get(0));
}
}
#Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
cx = 0;
cy = 0;
cz = 0;
}
#Override
public void onSensorChanged(SensorEvent arg0) {
if (arg0.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
long curTime = System.currentTimeMillis();
// only allow one update every 100ms, otherwise updates
// come way too fast and the phone gets bogged down
// with garbage collection
if (lastUpdate == -1 || (curTime - lastUpdate) > 100) {
lastUpdate = curTime;
x = arg0.values[0];
y = arg0.values[1];
z = arg0.values[2];
xLabel.setText(String.format("X: %+2.5f (%+2.5f)", (x+cx), cx));
yLabel.setText(String.format("Y: %+2.5f (%+2.5f)", (y+cy), cy));
zLabel.setText(String.format("Z: %+2.5f (%+2.5f)", (z+cz), cz));
}
}
}
}
You can look it up in the Android Reference but It looks like you'll need
SensorManager mgr = Context.getSystemService(SENSOR_SERVICE);
IList<Sensor> sensorList = mgr.getSensorList(SensorManager.SENSOR_ACCELEROMETER);
If you really want the list, but I think you are actually meant to use SensorManager.RegisterListener(SensorListener listener, int sensors, int rate) or another version of that method.