I have a requirement to rotate image arrow to particular location. Here is my current code:
public void onSensorChanged(SensorEvent event) {
float azimuth = event.values[0];
Location currentLoc = getHelper().getCurrentLocation();
if(currentLoc == null || cardinal == null || cardinal.getLocation() == null) {
return;
}
azimuth = (float) Math.toDegrees(azimuth);
GeomagneticField geoField = new GeomagneticField(
(float) currentLoc.getLatitude(),
(float) currentLoc.getLongitude(),
(float) currentLoc.getAltitude(),
System.currentTimeMillis());
azimuth += geoField.getDeclination(); // converts magnetic north into true north
float bearing = currentLoc.bearingTo(cardinal.getLocation()); // (it's already in degrees)
float direction = azimuth - bearing;
direction = -direction;
if(compass != null) {
compass.setDirection(direction);
}
}
And here is my custom imageview:
public void onDraw(Canvas canvas) { //
int height = this.getHeight(); //
int width = this.getWidth();
canvas.rotate(direction, width / 2, height / 2); //
super.onDraw(canvas); //
}
And here is the arrow image that I am using:
This code does not work at all. Can anybody points me where I am doing wrong?
I found the solution myself. I am posting the answer for other guys who are looking for same solution: Here is the updated code:
float azimuth = event.values[0];
Location currentLoc = getHelper().getCurrentLocation();
if(currentLoc == null || cardinal == null || cardinal.getLocation() == null) {
return;
}
try {
GeomagneticField geoField = new GeomagneticField(
Double.valueOf(currentLoc.getLatitude()).floatValue(),
Double.valueOf(currentLoc.getLongitude()).floatValue(),
Double.valueOf(currentLoc.getAltitude()).floatValue(),
System.currentTimeMillis() );
float myBearing = currentLoc.bearingTo(cardinal.getLocation());
azimuth += geoField.getDeclination();
azimuth = (myBearing - azimuth) * -1;
azimuth = normalizeDegree(azimuth);
// compass.updateValues(-azimuth);
} catch (Exception e) {
e.printStackTrace();
}
if(compass != null) {
compass.setDirection(-azimuth);
}
Related
I have this app in which the screen orientation is fixed on portrait and instead of doing a full screen rotation, and having to re-build the activity, I have decided to use the accelerometer instead.
The following code works fine on all the devices I test until I came across this one device (One+ running 6.0), in which I was unable to get the geomagnetic field in order to calculate the orientation.
Is this a problem from the hardware? am I missing some permissions?
I have looked into it and I didn't find any documentation saying I need to ask for permissions during runtime for an accelerometer.
Here is the code of the onSensor:
public void onSensorChanged(SensorEvent event) {
boolean isOrientationEnabled;
try {
isOrientationEnabled = Settings.System.getInt(getContentResolver(),
Settings.System.ACCELEROMETER_ROTATION) == 1;
} catch (Settings.SettingNotFoundException e) {
isOrientationEnabled = false;
}
if (!isOrientationEnabled){
if(this.Orientation!= ORIENTATION_PORTRAIT)rotateViews(ORIENTATION_PORTRAIT);
this.Orientation = ORIENTATION_PORTRAIT;
return;
}
if(allow_rotation) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
mGravity = event.values;
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
mGeomagnetic = event.values;
//mGeomagnetic is null
if (mGravity != null && mGeomagnetic != null) {
float R[] = new float[9];
float I[] = new float[9];
boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
if (success) {
float orientation[] = new float[3];
SensorManager.getOrientation(R, orientation);
// orientation contains: azimut, pitch and roll
float pitch = (float) Math.toDegrees(orientation[1]);
if (pitch < -45 && pitch > -135) {
// if device is laid flat on a surface
if(this.Orientation!= ORIENTATION_PORTRAIT) rotateViews(ORIENTATION_PORTRAIT);
this.Orientation = ORIENTATION_PORTRAIT;
return;
}
float roll = (float) Math.abs(Math.toDegrees(orientation[2]));
if ((roll > 60 && roll < 135)) {
// The device is closer to landscape orientation. Enable fullscreen
int landscape_mode;//0 = right, 2 = left
if (Math.toDegrees(orientation[2]) > 0) landscape_mode = ORIENTATION_LANDSCAPE_RIGHT;
else landscape_mode = ORIENTATION_LANDSCAPE_LEFT;
if(this.Orientation!=landscape_mode) rotateViews(landscape_mode);
this.Orientation = landscape_mode;
} else if (roll < 45 && roll > 135) {
// The device is closer to portrait orientation. Disable fullscreen
if(this.Orientation!=1)rotateViews(ORIENTATION_PORTRAIT);
this.Orientation = ORIENTATION_PORTRAIT;
}
}
}
}
}
You do not need Magnetic sensor for pitch and roll. Just low pass filter accelerometer to get gravity.
private static final float ALPHA = 0.8;
private float[] mGravity;
public void onSensorChanged(SensorEvent event) {
mGravity[0] = ALPHA * mGravity[0] + (1 - ALPHA) * event.values[0];
mGravity[1] = ALPHA * mGravity[1] + (1 - ALPHA) * event.values[1];
mGravity[2] = ALPHA * mGravity[2] + (1 - ALPHA) * event.values[2];
double gravityNorm = Math.sqrt(mGravity[0] * mGravity[0] + mGravity[1] * mGravity[1] + mGravity[2] * mGravity[2]);
pitch = (float) Math.asin(-mGravity[1] / gravityNorm);
roll = (float) Math.atan2(-mGravity[0] / gravityNorm, mGravity[2] / gravityNorm);
}
How to draw canvas by coordinate and let them scale with picture together?
1. In image side the colored polygon should scale with background image, but it is not.
(It shows on the correct position)
2. polygonList contain coordinate, should change value when scale, so onSigleTabEvent can found if the click position is in the pologon. But now, it is not working because the coordinate always become infinity. (Solved!)
PS: the TouchImageView is embed in the XML file.
The onDraw method in the TouchImageView .java
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (polygonList != null) {
for (Polygon polygon : polygonList) {
canvas.drawPath(polygon.path, polygon.paint);
}
}
onDrawReady = true;
imageRenderedAtLeastOnce = true;
if (delayedZoomVariables != null) {
setZoom(delayedZoomVariables.scale, delayedZoomVariables.focusX,
delayedZoomVariables.focusY,
delayedZoomVariables.scaleType);
delayedZoomVariables = null;
}
}
private void fixTrans() {
matrix.getValues(m);
// update all polygon coordinate
for (Polygon polygon : polygonList) {
for (Coordinate coordinate : polygon.coordinates) {
coordinate.x = coordinate.x * m[0] + m[2];
coordinate.y = coordinate.y * m[4] + m[5];
}
}
float transX = m[Matrix.MTRANS_X];
float transY = m[Matrix.MTRANS_Y];
float fixTransX = getFixTrans(transX, viewWidth, getImageWidth());
float fixTransY = getFixTrans(transY, viewHeight, getImageHeight());
if (fixTransX != 0 || fixTransY != 0) {
matrix.postTranslate(fixTransX, fixTransY);
}
}
MainActivity.java
List locations = floorPlan.getLocation();
Log.i("FloorPlanAct", "SetupClickArea(), Location.count():" + locations.size());
List polygonList = new ArrayList<>();
for (Location location : locations) {
List<Coordinate> coordinateList = location.getCoordinate();
// Test data, has location, but no coordinate
// Paint as a pen
Paint paint = new Paint();
paint.setARGB(location.areaColorA, location.areaColorR,
location.areaColorG, location.areaColorB);
paint.setAlpha(128);
paint.setStyle(Paint.Style.FILL);
// Group pen and path as a Polygon~
Polygon polygon = new Polygon(coordinateList, paint, location);
polygonList.add(polygon);
}
// 1. Prepare originalImagePosition
preparePolygon(polygonList, obj.orignalMatrix);
// Create a click area
TouchImageView imgClickArea = holder.imgClickArea;
imgClickArea.init(act, polygonList, obj.scaledBitmap, obj.orignalMatrix);
public void preparePolygon(List<Polygon> polygonList, Matrix
orignalMatrix){
float[] m = new float[9];
orignalMatrix.getValues(m);
for (Polygon polygon : polygonList) {
List<Coordinate> coordinates = polygon.coordinates;
// Path walk follow the coordinate
Path path = new Path();
path.reset(); // only needed when reusing this path for a new build
int coordinateCount = coordinates.size();
Log.i("TouchImageView", "***** initPolygon(), Polygon ******");
for (int i = 0; i < coordinateCount; i++) {
// Calculate the point of screen
Coordinate coordinate = coordinates.get(i);
Log.i("TouchImageView", "**** Coordinate ****");
Log.i("TouchImageView", "Original :" + coordinate.x + "," + coordinate.y);
coordinate.x = coordinate.x * m[0] + m[2];
coordinate.y = coordinate.y * m[4] + m[5];
Log.i("TouchImageView", "On the screen:" + coordinate.x + "," + coordinate.y);
if (i == 0) {
path.moveTo(coordinate.x, coordinate.y);
} else {
path.lineTo(coordinate.x, coordinate.y);
}
}
path.close();
polygon.path = path;
}
}
I'm writing Fall Detection application as a project for studies. I'm using accelerometer to detect impacts such as falls, jumps, and shakes, then I'm using barometer to check the height. If the height is bigger then 0.5 m between standing posture and lying posture after impact, it should detect it as fall.
I have a problem with saving barometer's pressure value before Impact from accelerometer and compare it with current pressure to see the difference.
Now I'm saving pressure value when Impact is detected and then later when currentstate is active or inactive. I need this to check the height and to see if the fall has really happend. Here is the code:
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
double ax = event.values[0];
double ay = event.values[1];
double az = event.values[2];
double acceleration = getMagnitude(ax, ay, az);
pushAcceleration(acceleration);
setKinematicState(accelerationFrame, ay);
/*
Checking Barometers Height in case of Falling
*/
if (currentState != previousState) {
if (currentState == KinematicState.FALL) {
PressuredataObject barometer;
barometer = pressuredataObjects.get(pressuredataObjects.size() - 1);
beforeFallAltitude = SensorManager.getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, barometer.getAirPressure());
impactDetected = true;
}
if ((currentState == KinematicState.INACTIVE || currentState == KinematicState.ACTIVE) && impactDetected) {
PressuredataObject barometer;
barometer = pressuredataObjects.get(pressuredataObjects.size() - 1);
afterFallAltitude = SensorManager.getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, barometer.getAirPressure());
float diffAltitude = beforeFallAltitude - afterFallAltitude;
float abs_diffAltitude = (diffAltitude < 0) ? -diffAltitude : diffAltitude;
if (abs_diffAltitude > 0.5) {
Log.d("abs_diffAltitude", "" + abs_diffAltitude);
state.setText("FALL DETECTED");
state.setTextColor(Color.parseColor("#FF0000"));
fallPlayer.start();
showDialog();
}
impactDetected = false;
}
systemState(currentState);
previousState = currentState;
}
}
if (event.sensor.getType() == Sensor.TYPE_PRESSURE) {
float[] values = event.values;
pressuredataObjects.add(new PressuredataObject(values[0], 0f, System.currentTimeMillis()));
if (pressuredataObjects.size() > BUFF_SIZE)
pressuredataObjects.remove(0);
PressuredataObject lastMeasure = pressuredataObjects.get(pressuredataObjects.size() - 1);
PressuredataObject medianValue = PressureUtilities.selectMedianValue(pressuredataObjects);
// Calculate speed and altitude
float speed = 0f;
float altitude = 0f;
if (pdoPrevious == null) {
medianValue.setSpeed(0);
} else {
speed = lastMeasure.getSpeed();
altitude = SensorManager.getAltitude(SensorManager.PRESSURE_STANDARD_ATMOSPHERE, lastMeasure.getAirPressure());
}
pdoPrevious = medianValue;
}
}
And here you can see the functions for accelerometer
private void setKinematicState(List<Double> buffer, double accelerationY) {
int zrc = getMagnitudeValues(buffer);
if (zrc <= 3) {
currentState = KinematicState.INACTIVE;
} else if (zrc > 3 && zrc < 6) {
currentState = KinematicState.ACTIVE;
}
else if (zrc > 6) {
currentState = KinematicState.FALL;
}
}
private int getMagnitudeValues(List<Double> accelerationFrame) {
int count = 0;
for (int i = 1; i < accelerationFrame.size(); i++) {
if ((accelerationFrame.get(i - 1) - GRAVITY_ACC) < APPROXIMATION_ERROR
&& (accelerationFrame.get(i) - GRAVITY_ACC) > APPROXIMATION_ERROR) {
count++;
}
}
return count;
}
private double getMagnitude(double accelerationX, double accelerationY, double accelerationZ) {
return Math.sqrt(accelerationX * accelerationX
+ accelerationY * accelerationY + accelerationZ * accelerationZ);
}
private void pushAcceleration(double acceleration) {
accelerationFrame.add(acceleration);
if (accelerationFrame.size() > BUFF_SIZE)
accelerationFrame.remove(0);
}
Does anyone has any idea how to save previous pressure value just before the impact from accelerometer?
I am working on a Compass type Android application, where I would have an image of a Compass, with letters indicating various directions ('N' for North, 'E' for East and so on). The user could press any of the letters and get some info about a given direction. I am looking for a way how to bind the touch coordinates to the image, i.e. if a user press a letter 'N' they would always get similar coordinates irrelevant to which direction handset is facing. Below is the code I am using now.
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
View v=inflater.inflate(R.layout.compass_fragment, container, false);
compassView = (CompassView) v.findViewById(R.id.compass_view);
compassView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motion) {
Log.i(TAG, "In onTouch");
// Get the action that was done on this touch event
switch (motion.getAction())
{
case MotionEvent.ACTION_DOWN:
{
return true;
}
case MotionEvent.ACTION_UP:
{
float x = motion.getX();
float y = motion.getY();
Log.i(TAG, "ACTION UP x = " + x + " y = " + y);
break;
}
}
// if you return false, these actions will not be recorded
return true;
}
});
mSensorManager = (SensorManager)getActivity().getSystemService(Context.SENSOR_SERVICE);
accelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
magnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
return(v);
}
I worked it out the answer to my question. It works the way I wanted, without using the buttons. I attached below the code, hope it might be useful for someone else.
To get the touched direction on the compass I calculate the offset angle between the current compass bearing (degrees variable which updated by setDegrees method called from another class) and the angle of the touch location in relation to the Y axis.
public class CompassView extends ImageView {
private float degrees=0;
private String touchDirection;
public CompassView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
int height = this.getHeight();
int width = this.getWidth();
canvas.rotate(360-degrees, width/2, height/2);
super.onDraw(canvas);
}
public void setDegrees(float degrees) {
this.degrees = degrees;
this.invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
float eventX = event.getX();
float eventY = event.getY();
touchDirection = getTouchDirection(eventX, eventY);
Context context = getContext();
Intent intent = new Intent(context, CompassDirectionInfo.class);
Bundle bundle = new Bundle();
bundle.putString("DIRECTION", touchDirection);
intent.putExtras(bundle);
context.startActivity(intent);
break;
default:
return false;
}
return true;
}
private String getTouchDirection (float eventX, float eventY) {
String direction = "";
float centreX = getWidth()/2, centreY = getHeight()/2;
float tx = (float) (eventX - centreX), ty = (float) (eventY - centreY);
float radius = (float) Math.sqrt(tx*tx + ty*ty);
float offsetX = 0, offsetY = radius, adjEventX = eventX - centreX, adjEventY = centreY - eventY;
double cosaU = ((offsetX * adjEventX) + (offsetY * adjEventY));
double cosaD = ( Math.sqrt((offsetX * offsetX) + (offsetY * offsetY)) * Math.sqrt((adjEventX * adjEventX) + (adjEventY * adjEventY)));
double cosa = cosaU / cosaD;
double degr = ( Math.acos(cosa) * (180 / Math.PI));
if (adjEventX < 0)
degr = 360 - degr;
float offsetDegrees = (float) (degrees + degr);
if (offsetDegrees > 360)
offsetDegrees = offsetDegrees - 360;
if (offsetDegrees < 22.5 || offsetDegrees > 336.5)
direction = "NORTH";
else if (offsetDegrees > 22.5 && offsetDegrees < 67.5)
direction = "NORTHEAST";
else if (offsetDegrees > 67.5 && offsetDegrees < 112.5)
direction = "EAST";
else if (offsetDegrees > 112.5 && offsetDegrees < 156.5)
direction = "SOUTHEAST";
else if (offsetDegrees > 156.5 && offsetDegrees < 201.5)
direction = "SOUTH";
else if (offsetDegrees > 201.5 && offsetDegrees < 246.5)
direction = "SOUTHWEST";
else if (offsetDegrees > 246.5 && offsetDegrees < 291.5)
direction = "WEST";
else if (offsetDegrees > 291.5 && offsetDegrees < 336.5)
direction = "NORTHWEST";
return direction;
}
}
i m working on Android Maps and i need to Add Compass functionality in it that is When I click on Compass Button it shows separate compass.
Can any one guide me the Right direction or refrence me any tutorial. I need to add Compass seperatly
thanks in Advance for reading and Replying
The Scenario in My Cass is To Use Separately use The Compass When click on Compass Button
it Will Show
Distance from Current Location(My Location) to the Destination location
Compass
Compass Head Towards North Direction
So to achieve all these I've used the following approach
hope this will help anyone who has the same scenario as I have
The Code Snippet of my Class That will get Distance between two points around the globe and show image as Compass with head towards north direction
public class MapController extends MapActivity implements SensorEventListener {
public static GeoPoint Mypoint, MapPoint;
double km, meter;
public static int kmInDec, meterInDec;
private SensorManager mSensorManager;
private Sensor mAccelerometer, mField;
Location myLoc, mapLoc;
double myLat, myLong, mapLat, mapLong;
public static double lat, lng;
public static double mylat = Double.parseDouble(Constants.DEVICE_OBJ.lat);//31.567615d;
public static double mylon = Double.parseDouble(Constants.DEVICE_OBJ.lng);//74.360962d;
com.google.android.maps.MapController mapController;
public static boolean enabled = false;
#Override
protected void onCreate(Bundle icicle) {
// TODO Auto-generated method stub
super.onCreate(icicle);
setContentView(R.layout.map_layout);
Log.v(Constants.TAG, "In Map Controller");
fetchUI();
}
public void fetchUI() {
myLoc = new Location("Test");
mapLoc = new Location("Test");
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mField = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
myLat = (31.567615 * 1e6) / 1E6;
myLong = (74.360962d * 1e6) / 1E6;
mapLat = (MapPoint.getLatitudeE6()) / 1E6;
mapLong = (MapPoint.getLongitudeE6()) / 1E6;
myLoc.setLatitude(31.567615);
myLoc.setLongitude(74.360962);
mapLoc.setLatitude(mapLat);
mapLoc.setLongitude(mapLong);
}
protected void onResume() {
super.onResume();
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
mSensorManager.registerListener(this, mField, SensorManager.SENSOR_DELAY_UI);
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
#Override
protected boolean isRouteDisplayed() {
// TODO Auto-generated method stub
return false;
}
///Method to calculate the Distance between 2 Geo Points aroud the Globe
public double CalculationByDistance(GeoPoint StartP, GeoPoint EndP) {
double lat1 = StartP.getLatitudeE6() / 1E6;
double lat2 = EndP.getLatitudeE6() / 1E6;
double lon1 = StartP.getLongitudeE6() / 1E6;
double lon2 = EndP.getLongitudeE6() / 1E6;
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
double c = 2 * Math.asin(Math.sqrt(a));
double valueResult = Radius * c;
double km = valueResult / 1;
DecimalFormat newFormat = new DecimalFormat("####");
kmInDec = Integer.valueOf(newFormat.format(km));
meter = valueResult % 1000;
meterInDec = Integer.valueOf(newFormat.format(meter));
Log.i("Radius Value", "" + valueResult + " KM " + kmInDec + " Meter " + meterInDec);
return Radius * c;
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
if (myLoc == null) return;
float azimuth = event.values[0];
float baseAzimuth = azimuth;
GeomagneticField geoField = new GeomagneticField(Double
.valueOf(myLoc.getLatitude()).floatValue(), Double
.valueOf(myLoc.getLongitude()).floatValue(),
Double.valueOf(myLoc.getAltitude()).floatValue(),
System.currentTimeMillis());
azimuth -= geoField.getDeclination(); // converts magnetic north into true north
// Store the bearingTo in the bearTo variable
float bearTo = myLoc.bearingTo(mapLoc);
// If the bearTo is smaller than 0, add 360 to get the rotation clockwise.
if (bearTo < 0) {
bearTo = bearTo + 360;
}
//This is where we choose to point it
float direction = bearTo - azimuth;
// If the direction is smaller than 0, add 360 to get the rotation clockwise.
if (direction < 0) {
direction = direction + 360;
}
rotateImageView(compasView, R.drawable.app_icon, direction);
//Set the field
String bearingText = "N";
if ((360 >= baseAzimuth && baseAzimuth >= 337.5) || (0 <= baseAzimuth && baseAzimuth <= 22.5))
bearingText = "N";
else if (baseAzimuth > 22.5 && baseAzimuth < 67.5) bearingText = "NE";
else if (baseAzimuth >= 67.5 && baseAzimuth <= 112.5) bearingText = "E";
else if (baseAzimuth > 112.5 && baseAzimuth < 157.5) bearingText = "SE";
else if (baseAzimuth >= 157.5 && baseAzimuth <= 202.5) bearingText = "S";
else if (baseAzimuth > 202.5 && baseAzimuth < 247.5) bearingText = "SW";
else if (baseAzimuth >= 247.5 && baseAzimuth <= 292.5) bearingText = "W";
else if (baseAzimuth > 292.5 && baseAzimuth < 337.5) bearingText = "NW";
else bearingText = "?";
Distance.setText(kmInDec + " Km " + " " + meterInDec + " m");
}
////This is the method to Show the Image as Compass
private void rotateImageView(ImageView imageView, int drawable, float rotate) {
// Decode the drawable into a bitmap
Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(),
drawable);
// Get the width/height of the drawable
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = bitmapOrg.getWidth(), height = bitmapOrg.getHeight();
// Initialize a new Matrix
Matrix matrix = new Matrix();
// Decide on how much to rotate
rotate = rotate % 360;
// Actually rotate the image
matrix.postRotate(rotate, width, height);
// recreate the new Bitmap via a couple conditions
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmapOrg, 0, 0, width, height, matrix, true);
//BitmapDrawable bmd = new BitmapDrawable( rotatedBitmap );
//imageView.setImageBitmap( rotatedBitmap );
imageView.setImageDrawable(new BitmapDrawable(getResources(), rotatedBitmap));
imageView.setScaleType(ScaleType.CENTER);
}
}
use this guide:
Google Maps Tutorial
search for compass, try launching a new activity with your needs when pressing on the compass (an overlay)
anyway, the tutorial is very comprehensive, I believe it will solve most of your needs =).