Android CS323 Cornez
Lab 7: Working with Sensors
Exercise 1: Detecting a Shake/Jerk Gesture
Construct an app that toggles a lightbulb on and off when the user shakes or jerks their device.
activity_main.xml
MyShakeListener.java
MainActivity.java
Exercise 2: Roaming Bee (or Ball) using the Accelerometer.
This app is created in the textbook Lab Example 8-1
-
Construct an application containing a bee (or the ball shown below). You can add TextViews to the main layout to provide accelerometer readings.
-
When the application first launches, the user is presented with the bee or ball
positioned at a specific x, y location on the screen.
-
The TextViews are helpful, as they display the x, y, and z-axis readings from the accelerometer.
- As the user tilts and rotates the device, the text fileds will be updatedto show the current accelerometer
readings.
- In addition, the ball will move in accordance with the tilt and roll of the device, as shown in the figure.
- The ball will not be allowed to roll off screen, and will be deterred by the virtual boundaries of the
screen.
Bee.java (or Ball.java)
MainActivity.java (Needs to be completed)
Exercise 3: Geomagnetic Rotation - Compass
.
Implement a geomagnetic rotation vector for measuring the orientation of
an Android device relative to a north, south, east, and west direction.
-
A geomagnetic rotation vector sensor is a composite sensor that will be defined by the
accelerometer in tandem with the magnetometer. The application may need to specify each feature
in a separate a uses-feature element within the Manifest file.
-
Indicate that motion readings will occur from an accelerometer and directional readings from a
magnetometer (compass) on the device.
- Set a portrait screen orientation for the application.
- Use your own art creation for the compass image.
Exercise 4: Fling a Billiard Ball
This exercise allows users to fling a billiard ball across the screen in any direction.
When the billiard ball
hits the edges of the screen, it reverses direction as if it is bouncing off a wall. Friction
should be applied to movement so that the ball eventually comes to a halt.
Research GestureDetector and OnGestureListener.
Question 1: How is the velocity of a fling detected?
Question 2: Can the velocity of a fling be detected across just the x-axis?
Question 3: Identify the callback methods used to detect gestures.
NOTE: Rename billiardball so that it reads ball.
Create the following files:
ball_layout.xml
This XML file is an ImageView layout that holds the billiardball.png.
main_layout.xml
This XML file is an main activity layout. Specify the root View as a FrameLayout.
Set the background to table.png.
Set the id to frameLayout.
NOTE: The FrameLayout uses a coordinate system with 0,0 in the center.
Ball.java
public class Ball {
public int mX;
public int mY;
public int mRadius;
public double mVelocityX;
public double mVelocityY;
public int left, right, top, bottom;
public Ball(int mX, int mY, int mRadius, double mVelocityX, double mVelocityY){
this.mX = mX;
this.mY = mY;
this.mRadius = mRadius;
this.mVelocityX = mVelocityX;
this.mVelocityY = mVelocityY;
}
public void move(){
mX += mVelocityX;
mY += mVelocityY;
//COLLISIONS - REVERSE DIRECTIONS
if (mX < left){
mX = left;
mVelocityX *= -1;
}
else if (mX > right){
mX = right;
mVelocityX *= -1;
}
if (mY < top){
mY = top;
mVelocityY *= -1;
}
else if (mY > bottom){
mY = bottom;
mVelocityY *= -1;
}
//APPLY FRICTION TO THE VELOCITY
mVelocityX *= .93;
mVelocityY *= .93;
if (Math.abs(mVelocityX) < 1) mVelocityX = 0;
if (Math.abs(mVelocityY) < 1) mVelocityY = 0;
}
public void setCollisionBoundaries( int windowWidth, int windowHeight){
left = -windowWidth / 2 + mRadius;
right = windowWidth / 2 - mRadius;
top = -windowHeight / 2 + mRadius;
bottom = windowHeight / 2 - mRadius;
}
}
MainActivity.java
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity implements GestureDetector.OnGestureListener {
private GestureDetector aGesture;
private FrameLayout mainLayout;
private Thread backgroundThread;
private ImageView ballImageView;
private Ball mBall;
private int left, right, top, bottom;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//TASK 1: SET THE LAYOUT AND THE WINDOW ELEMENTS
requestWindowFeature(Window.FEATURE_NO_TITLE);
getSupportActionBar().hide();
setContentView(R.layout.main_layout);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
mainLayout = (FrameLayout) findViewById(R.id.frameLayout);
//TASK 2: CREATE A BILLIARD BALL
buildBilliardBall();
//TASK 3: CREATE A GESTURE DETECTOR
aGesture = new GestureDetector(this, this);
//TASK 4: CREATE THE BACKGROUND THREAD
backgroundThread = new Thread(calculateAction);
backgroundThread.start();
}
private void buildBilliardBall() {
//TASK 1: THE CREATE THE DATA MODEL FOR THE BILLIARD BALL
mBall = new Ball(0, 0, 150, 0, 0);
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
mBall.setCollisionBoundaries(metrics.widthPixels, metrics.heightPixels);
//TASK 2: CREATE A LAYOUT INFLATER TO ADD THE BILLIARD BALL IMAGEVIEW TO THE LAYOUT
LayoutInflater layoutInflater;
layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//TASK 3: ADD THE BALL TO THE LAYOUT
ballImageView = (ImageView) layoutInflater.inflate(R.layout.ball_layout, null);
ballImageView.setScaleX((float) .3);
ballImageView.setScaleY((float) .3);
ballImageView.setX((float) mBall.mX);
ballImageView.setY((float) mBall.mY);
mainLayout.addView(ballImageView, 0);
}
//**************** RUNNABLE **********************
private Runnable calculateAction = new Runnable() {
private static final int DELAY = 50;
public void run() {
try {
while (true) {
mBall.move();
Thread.sleep(DELAY);
threadHandler.sendEmptyMessage(0);
}
} catch (InterruptedException e) {
}
}
};
//****** HANDLER FOR UPDATING THE IMAGEVIEW CONTAINING THE BILLIARD BALL******
public Handler threadHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
//UPDATE BALL LOCATION
ballImageView.setX((float) mBall.mX);
ballImageView.setY((float) mBall.mY);
}
};
//***********************TOUCH GESTURES*************************
@Override
public boolean onTouchEvent(MotionEvent event) {
return aGesture.onTouchEvent(event);
}
@Override
public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) {
final float ADJUST = 0.025f;
mBall.mVelocityX = (int) velocityX * ADJUST;
mBall.mVelocityY = (int) velocityY * ADJUST;
return true;
}
@Override
public void onLongPress(MotionEvent event) {}
@Override
public void onShowPress(MotionEvent event) {}
@Override
public boolean onDown(MotionEvent event) {return false;}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {return false;}
@Override
public boolean onSingleTapUp(MotionEvent event) {return false;}
}