This is more of a android design question. I am building an application that is going to consist of features such as P2P Connection, Location Receiving/Updates and a few others.
My applications current design is an activity consisting of two fragments in a viewpager and under a toolbar.
My first approach was to write different features all in separate classes (E.g Location receiver in its own class, a Google map generator in another) and then instantiate these objects where I needed them. I started to realize that that method wasn't working.
An idea I had was to implement everything I need in my fragments "onCreateView()" method but that just seems disorderly.
My question is where exactly do we implement certain features?
Here is an example of the fragment consisting of a map.
public class MapFragment extends Fragment implements OnMapReadyCallback{
SupportMapFragment mSupportMapFragment;
int radius = 20;
double mLatitude;
double mLongitude;
public double getLatitude() {
return mLatitude;
}
public double getLongitude() {
return mLongitude;
}
private GoogleMap maps;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mSupportMapFragment = SupportMapFragment.newInstance();
android.support.v4.app.FragmentManager sfm = getFragmentManager();
mSupportMapFragment.getMapAsync(this);
if(!mSupportMapFragment.isAdded())
sfm.beginTransaction().add(R.id.map_frag,mSupportMapFragment).commit();
else if(mSupportMapFragment.isAdded())
sfm.beginTransaction().hide(mSupportMapFragment).commit();
else
sfm.beginTransaction().show(mSupportMapFragment).commit();
LocationManager mLocationManager;
LocationListener mLocationListener;
mLocationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
if (location != null) {
/*
Updates to our map may need to be taken place here. Need to listen to other devices in the area.
*/
Log.e("Latitude: ", "" + location.getLatitude());
Log.e("Longitude: ", "" + location.getLongitude());
maps.clear(); //Clear the map of any existing markers
mLatitude = location.getLatitude();//Get coordinates stored into local variables
mLongitude = location.getLongitude();
LatLng latLng = new LatLng(mLatitude,mLongitude);//Create a "LatLng" object consisting of these coordinates
MarkerOptions mp1 = new MarkerOptions();//Instantiate a new "MarkerOptions" where we will be able to define a...
//...marker
mp1.position(new LatLng(location.getLatitude(),//Customizing marker...
location.getLongitude()));
mp1.title("You");
maps.addMarker(mp1);//Finally add the marker to the map
maps.moveCamera(CameraUpdateFactory.newLatLng(latLng));//Move camera to markers location using our "latLng" variable
maps.animateCamera(CameraUpdateFactory.zoomTo(20));// Zoom, (between 2.0 - 21.0) the higher, the more zoomed in
}
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
};
mLocationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,120000,radius,mLocationListener);
return inflater.inflate(R.layout.fragment_map, container, false);
}
#Override
public void onMapReady(GoogleMap map) {
maps = map;
}
}
In this fragment alone I have established location updates and a google map API. Everything seems to be working so far.
My only concern is the design.
Is cramming all these features (and more to come) in a single fragment considered bad practice?
Related
I have this EventActivity where I have a map with a marker:
public class EventActivity extends AppCompatActivity implements OnMapReadyCallback {
private double latitude;
private double longitude;
private GoogleMap eventMap;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event);
// Declares map fragment.
SupportMapFragment eventMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.activity_event_map);
eventMapFragment.getMapAsync(this);
// Gets latitude and longitude values from database.
// (things happen here and I get the values correctly)
latitude = 12.4567785
longitude = 25.7773665
}
#Override
public void onMapReady(GoogleMap googleMap) {
eventMap = googleMap;
// Sets map position.
LatLng position = new LatLng(latitude, longitude);
eventMap.addMarker(new MarkerOptions().position(position));
eventMap.moveCamera(CameraUpdateFactory.newLatLng(position));
}
}
On the OnCreate() I get the pair of double values correctly. I can even make a toast and it shows them.
The problem is, when I want to set them as the position for the marker of my map on the OnMapReady() it gets nothing or null.
How can I properly pass the values from OnCreate() to OnMapReady()?
EDIT: I'm using Firebase as my database.
Perhaps initialize the map fragment after assigning the lat/long values as such:
public class EventActivity extends AppCompatActivity implements OnMapReadyCallback {
private double latitude;
private double longitude;
private GoogleMap eventMap;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event);
// Gets latitude and longitude values from database.
// (things happen here and I get the values correctly)
latitude = 12.4567785
longitude = 25.7773665
// Declares map fragment.
SupportMapFragment eventMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.activity_event_map);
eventMapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
eventMap = googleMap;
// Sets map position.
LatLng position = new LatLng(latitude, longitude);
eventMap.addMarker(new MarkerOptions().position(position));
eventMap.moveCamera(CameraUpdateFactory.newLatLng(position));
}
}
I needed to solve a similar issue and currently have this solution working in my app. I wanted to add a new polyline from my location to the marker in question so wanted setOnMarkerListener to have access to my location. Here is how I solved it:
Step 1.
I created two global doubles as follows:
private Double myLatitude = -33.865143;
private Double myLongitude = 151.209900;
I gave them a default value of Sydney to avoid any NullPointerException error as I am adding polylines to an array of polylines.
Step 2.
In my onLocationChanged method I updated the values:
#Override
public void onLocationChanged(Location location) {
myLatitude = location.getLatitude();
myLongitude = location.getLongitude();
....
Now in Step 3 I wanted to create a new line from mylocation to the selected marker so used the following code:
mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker) {
marker.showInfoWindow();
areaText.setText(marker.getTitle());
distanceText.setText("0 Meters");
markerLatitude = marker.getPosition().latitude;
markerLongitude = marker.getPosition().longitude;
lines.add(mMap.addPolyline(new PolylineOptions()
.add(new LatLng(myLatitude, myLongitude),
new LatLng(marker.getPosition().latitude, marker.getPosition().longitude))
.width(10)
.color(Color.RED)));
if (lines.size() > 1)
lines.remove((lines.size()-1));
return true;
}
});
Hope this helps someone with the same issue.
I new in coding google map,
my question is how i control the user gestur drag , zoom in and zoom out.
because my code always back to the current location of user when i zoomin/out, nad when i drag/ scroll up, down, left, right. always back to the current possition .
its my code for current loc user
private GoogleMap.OnMyLocationChangeListener myLocationChangeListener = new GoogleMap.OnMyLocationChangeListener() {
#Override
public void onMyLocationChange(Location location) {
LatLng loc = new LatLng(location.getLatitude(), location.getLongitude());
mMarker = mMap.addMarker(new MarkerOptions().position(loc));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(loc, 16));
}
};
You can use a boolean to move the camera only the first time:
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleMap.OnMyLocationChangeListener {
private GoogleMap mMap;
private Marker mMarker;
private boolean firstTime = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
((SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map)).getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
mMap.setMyLocationEnabled(true);
mMap.setOnMyLocationChangeListener(this);
}
#Override
public void onMyLocationChange(Location location) {
LatLng loc = new LatLng(location.getLatitude(), location.getLongitude());
mMarker = mMap.addMarker(new MarkerOptions().position(loc));
if (firstTime) {
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(loc, 16));
firstTime = false;
}
}
}
NOTE: Take into account that this example uses GoogleMap.OnMyLocationChangeListener only because that is the method that you are using in your question, but it's deprecated and you must use the FusedLocationProviderApi according to the documentation:
public final void setOnMyLocationChangeListener
(GoogleMap.OnMyLocationChangeListener listener)
This method was deprecated. use
com.google.android.gms.location.FusedLocationProviderApi instead.
FusedLocationProviderApi provides improved location finding and power
usage and is used by the "My Location" blue dot. See the
MyLocationDemoActivity in the sample applications folder for example
example code, or the Location Developer Guide.
Guys I'm implementing google maps in my android app and instread of creating a marker i've placed a marker image in the middle of map. Now I want that whenever user drags the map i get the location at the centre of the map(where i've placed my image look like a marker).
My map activity is :
public class MapActivity extends FragmentActivity implements LocationListener {
private GoogleMap mMap; // Might be null if Google Play services APK is not available.
TextView Title;
FrameLayout goback;
Location myLocation;
LocationManager locationManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
setUpMapIfNeeded();
SupportMapFragment supportMapFragment =
(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mMap = supportMapFragment.getMap();
LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
Criteria criteria = new Criteria();
String bestProvider = locationManager.getBestProvider(criteria, true);
Location location = locationManager.getLastKnownLocation(bestProvider);
if (location != null) {
onLocationChanged(location);
}
locationManager.requestLocationUpdates(bestProvider, 20000, 0, this);
//try
Title=(TextView)findViewById(R.id.map_title);
Title.setText(getIntent().getExtras().getString("Header"));
goback=(FrameLayout)findViewById(R.id.frame_layout);
setUpMapIfNeeded();
// mMap.setMyLocationEnabled(true);
}
#Override
protected void onResume() {
super.onResume();
setUpMapIfNeeded();
}
private void setUpMapIfNeeded() {
// Do a null check to confirm that we have not already instantiated the map.
if (mMap == null) {
// Try to obtain the map from the SupportMapFragment.
mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map))
.getMap();
// Check if we were successful in obtaining the map.
if (mMap != null) {
setUpMap();
}
}
}
private void setUpMap() {
}
#Override
public void onLocationChanged(Location location) {
double latitude = location.getLatitude();
double longitude = location.getLongitude();
LatLng latLng = new LatLng(latitude, longitude);
BitmapDescriptor icon = BitmapDescriptorFactory.fromResource(R.drawable.marker);
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(5));
CameraPosition ll=mMap.getCameraPosition();
Toast.makeText(getApplicationContext(),""+ll,Toast.LENGTH_LONG).show();
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
please help me in doing so, thank you :)
First you can get referance of your map container, and calculate center point by dividing 2 width and height.
View containerView=findViewById(R.id.mapContainer);
LatLng centerPoint= this.map.getProjection().fromScreenLocation(new Point(((int)containerView.getWidth/2),((int)(containerView.getHeight/2)));
you can get the center this way:
mMap.getCameraPosition().target
where mMap is the GoogleMap instance from your activity. This will return a LatLng object which basically represents the center of the map. Note that the GeoPoint class is not anymore available.
According to http://developer.android.com/reference/com/google/android/gms/maps/model/CameraPosition.html
target is "The location that the camera is pointing at." (tested it with the sample code and it worked ok for me)
Let me know if this helped you.
Cheers!
You can use this method
MapView.getProjection().fromPixels(x, y)
Where x is half your map width and y is half the height. This should return you a coordinates object which in turn will give you your longitude and latitude of the center of your map
More information on it can be seen here
i have a problem with my code, in a fragment i have this code:
public class Logo extends Fragment implements GooglePlayServicesClient.ConnectionCallbacks, GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {
LocationManager lm;
Location mLastLocation;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private Location mCurrentLocation;
private TextView Lat;
private TextView Long;
String provider;
public Logo() {
}
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static Logo newInstance() {
Logo fragment = new Logo();
return fragment;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
lm = (LocationManager)getActivity().getSystemService(Context.LOCATION_SERVICE);
View view = inflater.inflate(R.layout.fragment_main, container, false);
Lat = (TextView) view.findViewById(R.id.Latitude);
Long = (TextView) view.findViewById(R.id.Longitude);
TextView Morad = (TextView) view.findViewById(R.id.Morada);
Criteria c=new Criteria();
provider=lm.getBestProvider(c, false);
mLastLocation=lm.getLastKnownLocation(provider);
Lat.setText("A obter");
Long.setText(" dados");
Morad.setText("Aguarde...");
if(mLastLocation!=null)
{
Lat.setText(String.valueOf(mLastLocation.getLatitude()));
Long.setText(String.valueOf(mLastLocation.getLongitude()));
}
else
{
Lat.setText("No connection");
Long.setText(" wait");
}
return view;
}
#Override
public void onConnected(Bundle bundle) {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient);
if (mLastLocation != null) {
Lat.setText(String.valueOf(mLastLocation.getLatitude()));
Long.setText(String.valueOf(mLastLocation.getLongitude()));
}
}
But never get the Lat and Longitude values, what i missed up.
I only want to return the Latitude and Longitude values and put in the 2 filds.
you need to decide if you are going to use the built in LocationManager or google play services Location APi because you are trying to use both and that will not work.
if you are trying to use the built in one then you never get a location because you dont have a last location and you never request location updates.
if you are trying to use the google play services location API well you need to do more work because you didnt really even implement it. I guess really in both cases you still have more work because you really didnt implement either correctly
I am just beginner on Android app developing. I have a few question. I am looking to create a location based simple reminder app. There are a lot tutorials but I am looking for a specific feature where a user creates reminder and it obtains current location and once it is created it is placed on the map (I dont know what type of object this would be, will it be a marker by calling the API) with its own unique geo-fence where the user can see it.
A user can make multiple reminders as it is saved in a database. I have currently implemented a simple GUI with Google maps by following a tutorial with a log in system so each reminder created will be unique to the user
When the user wants to create a reminder, you have to obtain his current location and place a marker in Google Maps with that location:
private LocationListener locationListener;
private LocationManager locationManager;
private Criteria criteria;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
initCriteria();
initLocationListener();
}
private void initCriteria() {
criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setPowerRequirement(Criteria.POWER_HIGH);
}
private void initLocationListener() {
locationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
placeMapMarkerInLocation(location);
}
#Override
public void onProviderDisabled(String provider) {
// Empty
}
#Override
public void onProviderEnabled(String provider) {
// Empty
}
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
// Empty
}
};
}
// User create reminder action
private void createReminder() {
locationManager.requestSingleUpdate(criteria, locationListener, null);
}
private void placeMapMarkerInLocation(Location location) {
map.addMarker(new MarkerOptions()
.position(new LatLng(location.getLatitude(), location.getLongitude()))
.title("Im here!"));
}
I cant get exactly what is your real question. But if its about how you'll get the remind markers into User's Google Map I think this link will point you in a good way: http://tips4php.net/2010/10/use-php-mysql-and-google-map-api-v3-for-displaying-data-on-map/.
And if you are using App Inventor I suggest you to follow this tutorial doing a few tweaks: http://appinventor.mit.edu/explore/ai2/android-wheres-my-car.html