Is there a better way to get this value from compass? - java

I need to get values from a compass and do it in rxJava.
So I've made this code:
private void goCompass()
{
Observable.create(new Observable.OnSubscribe<SensorEventListener>()
{
SensorEventListener listener = null;
#Override
public void call(final Subscriber<? super SensorEventListener> subscriber)
{
Sensor gsensor;
Sensor msensor;
final float[] mGravity = new float[3];
final float[] mGeomagnetic = new float[3];
listener = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent event) {
final float alpha = 0.97f;
Float azimuth = 0f;
synchronized (this) {
if(switchChecked == false) {
subscriber.onNext(listener);
subscriber.onCompleted();
}
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
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];
// mGravity = event.values;
// Log.e(TAG, Float.toString(mGravity[0]));
}
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
// mGeomagnetic = event.values;
mGeomagnetic[0] = alpha * mGeomagnetic[0] + (1 - alpha)
* event.values[0];
mGeomagnetic[1] = alpha * mGeomagnetic[1] + (1 - alpha)
* event.values[1];
mGeomagnetic[2] = alpha * mGeomagnetic[2] + (1 - alpha)
* event.values[2];
// Log.e(TAG, Float.toString(event.values[0]));
}
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);
azimuth = (float) Math.toDegrees(orientation[0]); // orientation
azimuth = (azimuth + 360) % 360;
Log.d("obs", "azimuth (rad): " + azimuth);
layout.setRotation(azimuth);
imageView.setRotation(-azimuth);
contlayout.setRotation(azimuth);
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
sensorManager = (SensorManager) getActivity()
.getSystemService(Context.SENSOR_SERVICE);
gsensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
msensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
sensorManager.registerListener(listener, gsensor,
SensorManager.SENSOR_DELAY_FASTEST);
sensorManager.registerListener(listener, msensor,
SensorManager.SENSOR_DELAY_FASTEST);
}
}).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<SensorEventListener>() {
#Override
public void onCompleted()
{
}
#Override
public void onError(Throwable e)
{
}
#Override
public void onNext(SensorEventListener listener)
{
sensorManager.unregisterListener(listener);
}
});
}
and it works. However, I'm at the beginning of rxJava and I want to know if there are better ways to do this things:
I've tried to get the azimuth value in onNext() method any times, but it doesn't work
I want to make it asynchronously but I couldn't because registerListener works only in the mainThread() and so if I use Schedulers.io() I need also to do runOnUiThread() method.
There are other ways to do it?
Thank you for help

Related

onSensorChanged , Compare sensor data every 10 seconds

My code :
#Override
public void onSensorChanged(SensorEvent event) {
float f1 = event.values[0];
float f2 = event.values[1];
float f3 = event.values[2];
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Toast.makeText(context,"10 second",Toast.LENGTH_SHORT).show();
new Handler().postDelayed(this, 10000);
}
}, 10000);
this.LastX = event.values[0];
this.LastY = event.values[1];
this.LastZ = event.values[2];
float f4 = Math.abs(this.LastX - f1);
float f5 = Math.abs(this.LastY - f2);
float f6 = Math.abs(this.LastZ - f3);
if(f4<0.003 && f5<0.003 && f6<0.003){
MainActivity.LockState = true;
// Toast.makeText(context,"Düz zemin",Toast.LENGTH_LONG).show();
}
}
I'm trying to compare sensor data every 10 second but postDelayed function does only work first time.After this the toast message is spamming.
You can simply get timestamp from SensorEvent and check if there is 10 seconds difference between the last and current timestamps.
For example:
private SensorEventListener sensorEventListener = new SensorEventListener() {
private long lastTimestamp;
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
long currentTimestamp = sensorEvent.timestamp;
if (currentTimestamp - lastTimestamp >= TimeUnit.SECONDS.toNanos(10)) {
lastTimestamp = currentTimestamp;
Toast.makeText(mContext, "10 seconds", Toast.LENGTH_SHORT).show();
//Here you can compare sensor data
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
};

Android - Pinch-zoomable Android frame layout

I used this to perform pinch zoom and drag.
public class ZoomLayout extends FrameLayout implements ScaleGestureDetector.OnScaleGestureListener {
private enum Mode {
NONE,
DRAG,
ZOOM
}
private static final String TAG = "ZoomLayout";
private static final float MIN_ZOOM = 1.0f;
private static final float MAX_ZOOM = 4.0f;
private Mode mode = Mode.NONE;
private float scale = 1.0f;
private float lastScaleFactor = 0f;
// Where the finger first touches the screen
private float startX = 0f;
private float startY = 0f;
// How much to translate the canvas
private float dx = 0f;
private float dy = 0f;
private float prevDx = 0f;
private float prevDy = 0f;
public ZoomLayout(Context context) {
super(context);
init(context);
}
public ZoomLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public ZoomLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
final ScaleGestureDetector scaleDetector = new ScaleGestureDetector(context, this);
this.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "DOWN");
if (scale > MIN_ZOOM) {
mode = Mode.DRAG;
startX = motionEvent.getX() - prevDx;
startY = motionEvent.getY() - prevDy;
}
break;
case MotionEvent.ACTION_MOVE:
if (mode == Mode.DRAG) {
dx = motionEvent.getX() - startX;
dy = motionEvent.getY() - startY;
}
break;
case MotionEvent.ACTION_POINTER_DOWN:
mode = Mode.ZOOM;
break;
case MotionEvent.ACTION_POINTER_UP:
mode = Mode.DRAG;
break;
case MotionEvent.ACTION_UP:
Log.i(TAG, "UP");
mode = Mode.NONE;
prevDx = dx;
prevDy = dy;
break;
}
scaleDetector.onTouchEvent(motionEvent);
if ((mode == Mode.DRAG && scale >= MIN_ZOOM) || mode == Mode.ZOOM) {
getParent().requestDisallowInterceptTouchEvent(true);
float maxDx = (child().getWidth() - (child().getWidth() / scale)) / 2 * scale;
float maxDy = (child().getHeight() - (child().getHeight() / scale))/ 2 * scale;
dx = Math.min(Math.max(dx, -maxDx), maxDx);
dy = Math.min(Math.max(dy, -maxDy), maxDy);
Log.i(TAG, "Width: " + child().getWidth() + ", scale " + scale + ", dx " + dx
+ ", max " + maxDx);
applyScaleAndTranslation();
}
return true;
}
});
}
// ScaleGestureDetector
#Override
public boolean onScaleBegin(ScaleGestureDetector scaleDetector) {
Log.i(TAG, "onScaleBegin");
return true;
}
#Override
public boolean onScale(ScaleGestureDetector scaleDetector) {
float scaleFactor = scaleDetector.getScaleFactor();
Log.i(TAG, "onScale" + scaleFactor);
if (lastScaleFactor == 0 || (Math.signum(scaleFactor) == Math.signum(lastScaleFactor))) {
scale *= scaleFactor;
scale = Math.max(MIN_ZOOM, Math.min(scale, MAX_ZOOM));
lastScaleFactor = scaleFactor;
} else {
lastScaleFactor = 0;
}
return true;
}
#Override
public void onScaleEnd(ScaleGestureDetector scaleDetector) {
Log.i(TAG, "onScaleEnd");
}
private void applyScaleAndTranslation() {
child().setScaleX(scale);
child().setScaleY(scale);
child().setTranslationX(dx);
child().setTranslationY(dy);
}
private View child() {
return getChildAt(0);
}
}
The problem that I am having with this is that when I zoom in, then drag, it snaps to the middle of the screen. I think the problem lies at:
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "DOWN");
if (scale > MIN_ZOOM) {
mode = Mode.DRAG;
startX = motionEvent.getX() - prevDx;
startY = motionEvent.getY() - prevDy;
}
break;
I am not sure how to fix this, can anyone please help me?
I fixed it by changing onScale to:
public boolean onScale(ScaleGestureDetector scaleDetector) {
float scaleFactor = scaleDetector.getScaleFactor();
Log.i(TAG, "mode:" + this.mode + ", onScale:" + scaleFactor);
if (this.lastScaleFactor == 0.0f || Math.signum(scaleFactor) == Math.signum(this.lastScaleFactor)) {
this.scale *= scaleFactor;
this.scale = Math.max(MIN_ZOOM, Math.min(this.scale, MAX_ZOOM));
this.lastScaleFactor = scaleFactor;
} else {
this.lastScaleFactor = 0.0f;
}
if (this.mSurfaceView != null) {
int orgWidth = getWidth();
int _width = (int) (((float) orgWidth) * this.scale);
int _height = (int) (((float) getHeight()) * this.scale);
LogUtil.b(new StringBuilder(String.valueOf(_width)).append(", ").append(_height).toString());
LayoutParams params = (LayoutParams) this.mSurfaceView.getLayoutParams();
params.height = _height;
params.width = _width;
this.mSurfaceView.setLayoutParams(params);
child().setScaleX(this.scale);
child().setScaleY(this.scale);
}
return true;
}

Android: azimuth issue depending initial device tilt

I'm currently programming an Android AR application and I have an issue with my Azimuth calculation depending of the initial device tilt.
I use the ROTATION_VECTOR sensor to get Azimuth, Altitude and Tilt.
When I launch my application and the phone is perpendicular with ground, I have the good azimuth from the North. When I launch the application and the phone is parallel to the ground, I have bad values. I have also strange values when I change device tilt.
This is my code :
public void onSensorChanged(SensorEvent event)
{
if (event.sensor.getType() == sensor.TYPE_ROTATION_VECTOR)
{
SensorManager.getRotationMatrixFromVector(rotationVectorMatrix, event.values);
SensorManager.remapCoordinateSystem(rotationVectorMatrix, SensorManager.AXIS_X, SensorManager.AXIS_Z, rotationMatrix);
SensorManager.getOrientation(rotationMatrix, orientation);
...
}
}
To get azimuth, you can use an accelerometer and magnetic field sensors. You can use following code to log azimuth value.
public class MainActivity extends AppCompatActivity {
private int mAzimuth = 0; // degree
private SensorManager mSensorManager = null;
private Sensor mAccelerometer;
private Sensor mMagnetometer;
boolean haveAccelerometer = false;
boolean haveMagnetometer = false;
#Override
protected void onCreate( Bundle savedInstanceState ) {
super.onCreate(savedInstanceState);
mSensorManager = (SensorManager) getSystemService(Service.SENSOR_SERVICE);
this.mAccelerometer = this.mSensorManager.getDefaultSensor( Sensor.TYPE_ACCELEROMETER );
this.haveAccelerometer = this.mSensorManager.registerListener( mSensorEventListener, this.mAccelerometer, SensorManager.SENSOR_DELAY_GAME );
this.mMagnetometer = this.mSensorManager.getDefaultSensor( Sensor.TYPE_MAGNETIC_FIELD );
this.haveMagnetometer = this.mSensorManager.registerListener( mSensorEventListener, this.mMagnetometer, SensorManager.SENSOR_DELAY_GAME );
if ( haveAccelerometer && haveMagnetometer ) {
// ready to go
} else {
// unregister and stop
}
}
private SensorEventListener mSensorEventListener = new SensorEventListener() {
float[] gData = new float[3]; // accelerometer
float[] mData = new float[3]; // magnetometer
float[] rMat = new float[9];
float[] iMat = new float[9];
float[] orientation = new float[3];
public void onAccuracyChanged(Sensor sensor, int accuracy ) {}
#Override
public void onSensorChanged( SensorEvent event ) {
float[] data;
switch ( event.sensor.getType() ) {
case Sensor.TYPE_ACCELEROMETER:
gData = event.values.clone();
break;
case Sensor.TYPE_MAGNETIC_FIELD:
mData = event.values.clone();
break;
default: return;
}
if ( SensorManager.getRotationMatrix( rMat, iMat, gData, mData ) ) {
mAzimuth= (int) ( Math.toDegrees( SensorManager.getOrientation( rMat, orientation )[0] ) + 360 ) % 360;
Log.d("AzimuthTag", "Azimuth:"+mAzimuth);
}
}
};
}
Source

Rotate Marker and Move Animation on Map like Uber Android

I am working on a project similar to UBER, Lyft or OLA ie. Map on the home with available moving Cars.
I'm looking for some kind of Library which can make Cars move and take turn smoothly just like UBER. For now I was able to move car smoothly from one lat-long to another with the below code. But tricky part is Taking turn and make sure the car face to front when moving to direction.
Smooth Moving Car Code:
final LatLng SomePos = new LatLng(12.7796354, 77.4159606);
try {
if (googleMap == null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
googleMap = ((MapFragment) getFragmentManager().findFragmentById(R.id.map)).getMap();
}
}
googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
googleMap.setMyLocationEnabled(true);
googleMap.setTrafficEnabled(false);
googleMap.setIndoorEnabled(false);
googleMap.setBuildingsEnabled(true);
googleMap.getUiSettings().setZoomControlsEnabled(true);
googleMap.moveCamera(CameraUpdateFactory.newLatLng(SomePos));
googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder()
.target(googleMap.getCameraPosition().target)
.zoom(17)
.bearing(30)
.tilt(45)
.build()));
myMarker = googleMap.addMarker(new MarkerOptions()
.position(SomePos)
.icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_launcher))
.title("Hello world"));
googleMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker arg0) {
final LatLng startPosition = myMarker.getPosition();
final LatLng finalPosition = new LatLng(12.7801569, 77.4148528);
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final Interpolator interpolator = new AccelerateDecelerateInterpolator();
final float durationInMs = 3000;
final boolean hideMarker = false;
handler.post(new Runnable() {
long elapsed;
float t;
float v;
#Override
public void run() {
// Calculate progress using interpolator
elapsed = SystemClock.uptimeMillis() - start;
t = elapsed / durationInMs;
LatLng currentPosition = new LatLng(
startPosition.latitude * (1 - t) + finalPosition.latitude * t,
startPosition.longitude * (1 - t) + finalPosition.longitude * t);
myMarker.setPosition(currentPosition);
// Repeat till progress is complete.
if (t < 1) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
if (hideMarker) {
myMarker.setVisible(false);
} else {
myMarker.setVisible(true);
}
}
}
});
return true;
}
});
} catch (Exception e) {
e.printStackTrace();
}
I recently came across the same use-case. Here is my solution on it.
First, I would like to thank #VipiN for sharing "The Smooth Moving Car Code". It works smoothly.
The second part is to place car-marker in the right direction and rotate it according to turns. To achieve this I calculated the bearing or heading angle between two successive points(i.e. location updates you receive from device/server). This link will help you understand the maths behind it.
The following code will give you bearing between two locations:
private double bearingBetweenLocations(LatLng latLng1,LatLng latLng2) {
double PI = 3.14159;
double lat1 = latLng1.latitude * PI / 180;
double long1 = latLng1.longitude * PI / 180;
double lat2 = latLng2.latitude * PI / 180;
double long2 = latLng2.longitude * PI / 180;
double dLon = (long2 - long1);
double y = Math.sin(dLon) * Math.cos(lat2);
double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
* Math.cos(lat2) * Math.cos(dLon);
double brng = Math.atan2(y, x);
brng = Math.toDegrees(brng);
brng = (brng + 360) % 360;
return brng;
}
Finally, we need to rotate the car-marker by the angle that we get from above method.
private void rotateMarker(final Marker marker, final float toRotation) {
if(!isMarkerRotating) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final float startRotation = marker.getRotation();
final long duration = 1000;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
#Override
public void run() {
isMarkerRotating = true;
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed / duration);
float rot = t * toRotation + (1 - t) * startRotation;
marker.setRotation(-rot > 180 ? rot / 2 : rot);
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
isMarkerRotating = false;
}
}
});
}
}
Cheers!
Here is my code to move marker like uber. i have shown two ways to move marker .
Important Note: To move car on proper road [like ola,uber] you need to use road api provided by google
1.By static latitude and longitude
2.By Real time Latitude and longitude
package com.gangsofcoder.googlemapdemo;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.PersistableBundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.animation.LinearInterpolator;
import android.widget.Button;
import android.widget.Toast;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.loopj.android.http.AsyncHttpResponseHandler;
import com.loopj.android.http.RequestParams;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import cz.msebera.android.httpclient.Header;
public class MoveCar extends AppCompatActivity {
private GoogleMap googleMap;
SupportMapFragment mapFragment;
Marker marker;
private boolean isMarkerRotating = false;
ArrayList<LatLng> listOfPoints = new ArrayList<>();
int currentPt = 0;
LatLng finalPosition;
Marker mMarker;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setUpMapIfNeeded();
//new location details
listOfPoints.add(new LatLng(30.701623, 76.684220));
listOfPoints.add(new LatLng(30.702486, 76.685487));
listOfPoints.add(new LatLng(30.703135, 76.684891));
listOfPoints.add(new LatLng(30.703256, 76.685000));
listOfPoints.add(new LatLng(30.703883, 76.685941));
listOfPoints.add(new LatLng(30.703413, 76.685190));
}
private void setUpMapIfNeeded() {
if (mapFragment == null) {
mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
if (mapFragment != null) {
mapFragment.getMapAsync(new OnMapReadyCallback() {
#Override
public void onMapReady(GoogleMap googleMap) {
loadMap(googleMap);
}
});
}
}
}
private void loadMap(GoogleMap map) {
googleMap = map;
mMarker = googleMap.addMarker(new MarkerOptions().position(new LatLng(30.701623, 76.684220)).icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_car)));
final Handler handler = new Handler();
//Code to move car along static latitude and longitude
/* handler.postDelayed(new Runnable() {
#Override
public void run() {
if (currentPt < listOfPoints.size()) {
//post again
Log.d("tess", "inside run ");
Location targetLocation = new Location(LocationManager.GPS_PROVIDER);
targetLocation.setLatitude(listOfPoints.get(currentPt).latitude);
targetLocation.setLongitude(listOfPoints.get(currentPt).longitude);
animateMarkerNew(targetLocation, mMarker);
handler.postDelayed(this, 3000);
currentPt++;
} else {
Log.d("tess", "call back removed");
//removed callbacks
handler.removeCallbacks(this);
}
}
}, 3000);*/
//Here move marker along real time updates
final RequestParams params = new RequestParams();
params.put("source_lattitude", "lat");
params.put("source_longitude", "long");
params.put("date", "date");
//new handler
handler.postDelayed(new Runnable() {
#Override
public void run() {
LoopjHttpClient.post(getString(R.string.default_upload_website), params, new AsyncHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
try {
JSONObject jsonObject = new JSONObject(new String(responseBody));
String status = jsonObject.getString("status");
String text = jsonObject.getString("text");
//reading json array
JSONArray jsonArray = jsonObject.getJSONArray("result");
String source = jsonArray.getJSONObject(0).getString("source");
String[] latLong = source.split(",");
Location location = new Location(LocationManager.GPS_PROVIDER);
location.setLatitude(Double.parseDouble(latLong[0]));
location.setLongitude(Double.parseDouble(latLong[1]));
//calling method to animate marker
animateMarkerNew(location, mMarker);
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
Log.d("onFailure", "onFailure");
}
});
handler.postDelayed(this, 3000);
}
}, 3000);
}
private void animateMarkerNew(final Location destination, final Marker marker) {
if (marker != null) {
final LatLng startPosition = marker.getPosition();
final LatLng endPosition = new LatLng(destination.getLatitude(), destination.getLongitude());
final float startRotation = marker.getRotation();
final LatLngInterpolatorNew latLngInterpolator = new LatLngInterpolatorNew.LinearFixed();
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(3000); // duration 3 second
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
try {
float v = animation.getAnimatedFraction();
LatLng newPosition = latLngInterpolator.interpolate(v, startPosition, endPosition);
marker.setPosition(newPosition);
googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder()
.target(newPosition)
.zoom(15.5f)
.build()));
marker.setRotation(getBearing(startPosition, new LatLng(destination.getLatitude(), destination.getLongitude())));
} catch (Exception ex) {
//I don't care atm..
}
}
});
valueAnimator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
// if (mMarker != null) {
// mMarker.remove();
// }
// mMarker = googleMap.addMarker(new MarkerOptions().position(endPosition).icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_car)));
}
});
valueAnimator.start();
}
}
private interface LatLngInterpolatorNew {
LatLng interpolate(float fraction, LatLng a, LatLng b);
class LinearFixed implements LatLngInterpolatorNew {
#Override
public LatLng interpolate(float fraction, LatLng a, LatLng b) {
double lat = (b.latitude - a.latitude) * fraction + a.latitude;
double lngDelta = b.longitude - a.longitude;
// Take the shortest path across the 180th meridian.
if (Math.abs(lngDelta) > 180) {
lngDelta -= Math.signum(lngDelta) * 360;
}
double lng = lngDelta * fraction + a.longitude;
return new LatLng(lat, lng);
}
}
}
//Method for finding bearing between two points
private float getBearing(LatLng begin, LatLng end) {
double lat = Math.abs(begin.latitude - end.latitude);
double lng = Math.abs(begin.longitude - end.longitude);
if (begin.latitude < end.latitude && begin.longitude < end.longitude)
return (float) (Math.toDegrees(Math.atan(lng / lat)));
else if (begin.latitude >= end.latitude && begin.longitude < end.longitude)
return (float) ((90 - Math.toDegrees(Math.atan(lng / lat))) + 90);
else if (begin.latitude >= end.latitude && begin.longitude >= end.longitude)
return (float) (Math.toDegrees(Math.atan(lng / lat)) + 180);
else if (begin.latitude < end.latitude && begin.longitude >= end.longitude)
return (float) ((90 - Math.toDegrees(Math.atan(lng / lat))) + 270);
return -1;
}
}
Since its been bit confusing for SO users to look for working code in two different posts. Here is the working code for Rotate and Move Marker which seamlessly worked for me.
in MainActivity.java
public void rotateMarker(final Marker marker, final float toRotation, final float st) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final float startRotation = st;
final long duration = 1555;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
#Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed / duration);
float rot = t * toRotation + (1 - t) * startRotation;
marker.setRotation(-rot > 180 ? rot / 2 : rot);
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
}
}
});
}
public void animateMarker(final LatLng toPosition,final boolean hideMarke) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
Projection proj = googleMap.getProjection();
Point startPoint = proj.toScreenLocation(m.getPosition());
final LatLng startLatLng = proj.fromScreenLocation(startPoint);
final long duration = 5000;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
#Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed
/ duration);
double lng = t * toPosition.longitude + (1 - t)
* startLatLng.longitude;
double lat = t * toPosition.latitude + (1 - t)
* startLatLng.latitude;
m.setPosition(new LatLng(lat, lng));
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
} else {
if (hideMarke) {
m.setVisible(false);
} else {
m.setVisible(true);
}
}
}
});
}
Finally wrote the code that works exactly in the similar manner that OLA CABS does...
Here it is -
Put your google maps fragment in a Relative layout and put the marker(as image view ) in the center -
In your fragment's code once you have setup all the google maps basic working write the following code for the onMapReady(GoogleMap googleMap) function-
My Code is as follows -
//Step 1 -
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MapsActivity_for_request_pages" />
<ImageView
android:layout_width="30sp"
android:layout_height="30sp"
android:layout_centerInParent="true"
android:id="#+id/central_marker"
android:src="#drawable/marker_pic"/>
</RelativeLayout>
//Step 2 -
#Override
public void onMapReady(GoogleMap googleMap) {
central_marker = (ImageView)v.findViewById(R.id.central_marker);
int init_loc = 0,final_loc = -300;
mMap = googleMap;
final CountDownTimer timer = new CountDownTimer(300,300) {
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
init_loc = 0;
ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(central_marker, "translationY", final_loc, init_loc);
objectAnimatorY.setDuration(200);
objectAnimatorY.start();
}
};
mMap.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() {
#Override
public void onCameraMoveStarted(int i) {
System.out.println("Camera started moving worked");
timer.cancel();
ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(central_marker, "translationY", init_loc, final_loc);
objectAnimatorY.setDuration(200);
objectAnimatorY.start();
init_loc = -300;
}
});
mMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
#Override
public void onCameraIdle() {
System.out.println("Camera idle worked");
if(initial_flag!=0)
{
System.out.println("Camera Setting timer now");
timer.cancel();
timer.start();
}
initial_flag++;
System.out.println("Camera Value of initial_flag ="+initial_flag);
}
});
}
Firstly,I would like to thank you both #Vipin Negi & #Prasad for such a good & awesomely working code.Since there are many pending queries above, I want to make all the above stuff a little simpler. Guys, just follow the following steps to achieve the marker rotation.
1. Define below two methods in your MainActivity.java file
private double bearingBetweenLocations(LatLng latLng1, LatLng latLng2) {
double PI = 3.14159;
double lat1 = latLng1.latitude * PI / 180;
double long1 = latLng1.longitude * PI / 180;
double lat2 = latLng2.latitude * PI / 180;
double long2 = latLng2.longitude * PI / 180;
double dLon = (long2 - long1);
double y = Math.sin(dLon) * Math.cos(lat2);
double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
* Math.cos(lat2) * Math.cos(dLon);
double brng = Math.atan2(y, x);
brng = Math.toDegrees(brng);
brng = (brng + 360) % 360;
return brng;
}
&
private void rotateMarker(final Marker marker, final float toRotation) {
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final float startRotation = marker.getRotation();
final long duration = 1000;
final Interpolator interpolator = new LinearInterpolator();
handler.post(new Runnable() {
#Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float t = interpolator.getInterpolation((float) elapsed / duration);
float rot = t * toRotation + (1 - t) * startRotation;
marker.setRotation(-rot > 180 ? rot / 2 : rot);
if (t < 1.0) {
// Post again 16ms later.
handler.postDelayed(this, 16);
}
}
});
}
2. After this, add the following lines to the code where you want your marker to rotate.
double bearing = bearingBetweenLocations(m.getPosition(), updatedLatLng);
rotateMarker(m, (float) bearing);
Note that "m" is your marker object that you want to rotate.
And, you're done!!!
If you want marker animation related help,you can use this code.
Try google default rotation or see the detail explanation Markers Rotation
private void updateCamera(LatLng currentLatLng, Location location) {
//googleMap.clear();
if (marker == null) {
MarkerOptions options = new MarkerOptions();
options.position(currentLatLng);
options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_driver_car_pin_v));
options.flat(true);
options.anchor(0.5f, 0.5f);
marker = googleMap.addMarker(options);
} else {
marker.setPosition(currentLatLng);
marker.setRotation(location.getBearing());
}
CameraPosition cameraPosition = new CameraPosition.Builder(googleMap.getCameraPosition())
.target(currentLatLng).zoom(18).build();
googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}

Java Android App

i need your help as fast as possible.
I need to create an java android app,that will switch on the music when shaking a phone.
So at the initial position the sound is switched off and when shaking it, it starts to play.
But when stopping shaking it, the sound switches off. The .mp3 file is already in the project. What's wrong am I doing?
package com.authorwjf;
public class Main extends Activity implements SensorEventListener {
private float mLastX, mLastY, mLastZ;
private boolean mInitialized;
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private final float NOISE = (float) 2.0;
//music
MediaPlayer logoMusic;
boolean paused = true;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//music
logoMusic = MediaPlayer.create(Main.this, R.raw.music);
logoMusic.setVolume(0, 1);
//
//
setContentView(R.layout.main);
mInitialized = false;
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometer , SensorManager.SENSOR_DELAY_NORMAL);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// can be safely ignored for this demo
}
#Override
public void onSensorChanged(SensorEvent event) {
TextView tvX= (TextView)findViewById(R.id.x_axis);
TextView tvY= (TextView)findViewById(R.id.y_axis);
TextView tvZ= (TextView)findViewById(R.id.z_axis);
ImageView iv = (ImageView)findViewById(R.id.image);
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
if (!mInitialized) {
mLastX = x;
mLastY = y;
mLastZ = z;
tvX.setText("0.0");
tvY.setText("0.0");
tvZ.setText("0.0");
mInitialized = true;
} else {
float deltaX = Math.abs(mLastX - x);
float deltaY = Math.abs(mLastY - y);
float deltaZ = Math.abs(mLastZ - z);
if (deltaX < NOISE) deltaX = (float)0.0;
if (deltaY < NOISE) deltaY = (float)0.0;
if (deltaZ < NOISE) deltaZ = (float)0.0;
mLastX = x;
mLastY = y;
mLastZ = z;
tvX.setText(Float.toString(deltaX));
tvY.setText(Float.toString(deltaY));
tvZ.setText(Float.toString(deltaZ));
iv.setVisibility(View.VISIBLE);
if (deltaX > deltaY) {
iv.setImageResource(R.drawable.horizontal);
} else if (deltaY > deltaX) {
iv.setImageResource(R.drawable.vertical);
} else {
iv.setVisibility(View.INVISIBLE);
}
logoMusic.start();
}
}
public void pauseMusic( View v ) {
if (paused)
{
logoMusic.start();
paused = true;
}
else
{
logoMusic.pause();
paused = false;
}
}
protected void onResume() {
super.onResume();
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
logoMusic.start();
}
protected void onPause() {
mSensorManager.unregisterListener(this);
super.onPause();
logoMusic.pause();
}
You defined your media player, but you never started it. To start it:
logoMusic.start();

Categories

Resources