I am trying to create a map activity that displays the user current location that can be zoomed to street level but my app is not working properly, what do you think are the codes that I need to add?
public class Map_Activity extends FragmentActivity implements GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener,
com.google.android.gms.location.LocationListener{
private GoogleMap myMap;
private LocationClient myLocationClient;
private static final LocationRequest REQUEST = LocationRequest.create()
.setInterval(5000)
.setFastestInterval(16)
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map);
getMapReference();
}
#Override
protected void onResume(){
super.onResume();
getMapReference();
wakeUpLocationClient();
myLocationClient.connect();
}
#Override
public void onPause(){
super.onPause();
if (myLocationClient != null){
myLocationClient.disconnect();
}
}
private void gotoMyLocation(double lat, double lng) {
changeCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder().target(new LatLng(lat, lng))
.zoom(15.5f)
.bearing(0)
.tilt(25)
.build()
), new GoogleMap.CancelableCallback() {
#Override
public void onFinish() {
}
#Override
public void onCancel() {
}
});
}
private void wakeUpLocationClient(){
if(myLocationClient == null){
myLocationClient = new LocationClient(getApplicationContext(),this,this);
}
}
private void getMapReference(){
if(myMap==null){
myMap = ((SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
}
if (myMap != null){
myMap.setMyLocationEnabled(true);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_map, menu);
return true;
}
#Override
public void onConnected(Bundle bundle){
myLocationClient.requestLocationUpdates( REQUEST, this);
}
#Override
public void onDisconnected(){
}
#Override
public void onLocationChanged(Location location){
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult){
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private void changeCamera(CameraUpdate update, GoogleMap.CancelableCallback callback) {
myMap.moveCamera(update);
}
}
the app is running but the map is not showing and it is not showing me my current location :( i hope somebody could help me
Here are step by step for using GoogleMaps:
A.configured your project to work with GoogleMaps (your map may not appear if not properly configured):
in "build.graddle" add dependencies with proper version e.g. 6.5.87 or 8.1.0:
compile 'com.google.android.gms:play-services:8.1.0'
in "Android.Manifest" add permissions, GL and API Key (make sure to put your APIKey):
< uses-permission android:name="android.permission.WAKE_LOCK" />
< uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
< uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
< uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
< uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
< uses-permission android:name="android.permission.INTERNET" />
< uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
< uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
<!-- Google Maps Fragment API Key Data -->
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="YOUR API KEY" />
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
B. Code:
use OnMapReady :
add "OnMapReadyCallback" to your activity class:
public class Map_Activity extends FragmentActivity implements GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener,
com.google.android.gms.location.LocationListener,
OnMapReadyCallback
{
override onMapReady to enable location and have reference to GoogleMap:
#Override
public void onMapReady(GoogleMap map) {
map.setMyLocationEnabled(true);
googleMap = map;
}
in Activity-OnCrate call getMapAsync:
FragmentManager fm = getSupportFragmentManager();
SupportMapFragment mapFragment = (SupportMapFragment) fm.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
C. Remove/replace deprecated code:
-LocationClient
-replace "GooglePlayServicesClient" with GoogleApiClient
Related
Good Evening everybody,
I have a problem with Google Maps SDK on an Android App, I would like to show my-location-layer, I ask permission FINE_LOCATION and COARSE_LOCATION in MainActivity and declare it in Manifest File.
On APi < Marshmallow it's works because, I don't need to accept the permissions but with APi >= Marshmallow it's bad.
I don't see the my_location_layer for the first time when I start the App, I must restart my App for see it.
Below my code, if everyone could help me, thanks.
Manifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.mapsexample">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:dataExtractionRules="#xml/data_extraction_rules"
android:fullBackupContent="#xml/backup_rules"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:roundIcon="#mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="#style/Theme.MapsExample"
tools:targetApi="31">
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="#string/maps_api_key" />
<meta-data
android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version" />
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.java
#SuppressWarnings("all")
public class MainActivity extends AppCompatActivity implements
GoogleMap.OnMyLocationButtonClickListener,
GoogleMap.OnMyLocationClickListener,
OnMapReadyCallback {
private final int LOCATION_PERMISSION_REQUEST_CODE = 200;
private String[] PERMISSIONS;
private SupportMapFragment mapFragment;
private GoogleMap googleMap;
private Location currentLocation;
private FusedLocationProviderClient mFusedLocationClient;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
checkPermissions();
}
private void initData() {
PERMISSIONS = new String[]{
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
};
googleMap = null;
currentLocation = null;
mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}
private void checkPermissions() {
if (hasPermissions(this)) {
mapFragment.getMapAsync(this);
} else {
askLocationPermission();
}
}
private void getLastLocation() {
Task<Location> locationTask = mFusedLocationClient.getLastLocation();
locationTask.addOnSuccessListener(new OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
currentLocation = location;
zoomOnCurrentPlace();
}
});
}
private void askLocationPermission() {
if (ActivityCompat.checkSelfPermission(this, PERMISSIONS[1]) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, PERMISSIONS, LOCATION_PERMISSION_REQUEST_CODE);
} else {
mapFragment.getMapAsync(this);
}
}
private boolean hasPermissions(Context context) {
if (context != null && PERMISSIONS != null) {
for (String permission : PERMISSIONS) {
if (ActivityCompat.checkSelfPermission(context, permission) != PackageManager.PERMISSION_GRANTED) {
return false;
}
}
}
return true;
}
#Override
public void onMapReady(#NonNull GoogleMap googleMap) {
Toast.makeText(this, "Start OnMapReady", Toast.LENGTH_LONG).show();
this.googleMap = googleMap;
this.googleMap.setMapType(this.googleMap.MAP_TYPE_NORMAL);
this.googleMap.setMyLocationEnabled(true);
this.googleMap.setOnMyLocationButtonClickListener(this);
this.googleMap.setOnMyLocationClickListener(this);
this.googleMap.getUiSettings().setZoomControlsEnabled(true);
this.googleMap.setOnMapClickListener(latLng -> {
Toast.makeText(MainActivity.this, "Click on " + latLng, Toast.LENGTH_SHORT).show();
this.googleMap.addMarker(new MarkerOptions().position(latLng).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_AZURE)));
});
getLastLocation();
}
private void zoomOnCurrentPlace() {
LatLng currentPlace = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
// Move the camera to the this.googleMap coordinates and zoom in closer.
googleMap.addMarker(new MarkerOptions().position(currentPlace).title("Ma position"));
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentPlace, 17));
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
boolean permissionsAreAccepted = true;
if (requestCode == LOCATION_PERMISSION_REQUEST_CODE && grantResults.length > 0) {
for (int grantResult : grantResults) {
if (grantResult != PackageManager.PERMISSION_GRANTED) {
permissionsAreAccepted = false;
break;
}
}
if (permissionsAreAccepted) {
mapFragment.getMapAsync(this);
}else {
askLocationPermission();
}
}
}
#Override
public void onMyLocationClick(#NonNull Location location) {
Toast.makeText(this, "Current location:\n" + location, Toast.LENGTH_LONG)
.show();
}
#Override
public boolean onMyLocationButtonClick() {
Toast.makeText(this, "MyLocation button clicked", Toast.LENGTH_SHORT)
.show();
return false;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.map_options, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.normal_map:
googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
return true;
case R.id.hybrid_map:
googleMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
return true;
case R.id.satellite_map:
googleMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
return true;
case R.id.terrain_map:
googleMap.setMapType(GoogleMap.MAP_TYPE_TERRAIN);
return true;
}
return super.onOptionsItemSelected(item);
}
}
Thanks for your help :-)
I solved my problem, just follow, step by step:
create variable type LocationCallback, LocationRequest and long
private LocationRequest mLocationRequest = null;
private LocationCallback mLocationCallback = null;
private final Long LOCATION_REQUEST_INTERVAL = 5000L;
In Oncreate just init your FusedLocationProviderClient, LocationCallback and map
private void initData() {
PERMISSIONS = new String[]{
Manifest.permission.INTERNET,
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
};
googleMap = null;
currentLocation = null;
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
mLocationCallback = new LocationCallback() {
#Override
public void onLocationResult(#NonNull LocationResult locationResult) {
super.onLocationResult(locationResult);
currentLocation = locationResult.getLastLocation();
}
};
}
In OnCreate call function createLocationRequest
private void createLocationRequest() {
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(LOCATION_REQUEST_INTERVAL).setFastestInterval(LOCATION_REQUEST_INTERVAL);
// requestLocationUpdate();
}
Check your permissions ( Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION)
if you have permission call getLastLocation() with mFusedLocationClient
In getLastLocation when location != null then googleMap.setLocationSource()
googleMap.setLocationSource(new LocationSource() {
#Override
public void activate(#NonNull OnLocationChangedListener onLocationChangedListener) {
onLocationChangedListener.onLocationChanged(currentLocation);
zoomOnCurrentPlace();
}
#Override
public void deactivate() {
Toast.makeText(MainActivity.this, "LocationSource deactivated", Toast.LENGTH_SHORT).show();
}
});
IF YOU DON'T HAVE PERMISSIONS
If you don't have permission ask them with
private void askLocationPermission() {
ActivityCompat.requestPermissions(this, PERMISSIONS, LOCATION_PERMISSION_REQUEST_CODE);
}
Then in onRequestPermissionsResult if permissions are granted then
googleMap.setMyLocationEnabled(true);
requestLocationUpdate();
getLastLocation();
Elseif just callback askLocationPermission function, don't forgot to create requestLocationUpdate function
private void requestLocationUpdate() {
mFusedLocationClient.requestLocationUpdates(
mLocationRequest,
mLocationCallback,
Looper.myLooper()
);
I Hope it'll help someone :)
I want to zoom to the current location of user when activity started. I have two java class. One of is MapActivity.java and the other is MapFragment.java. I'm trying to do this job on MapFragment.java.
private Actvity activity;
private volatile GoogleMap googleMap;
GoogleApiClient mGoogleApiClient;
LocationRequest mLocationRequest;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activity = getActivity();
}
MapFragment.java/onMapReady ;
#Override
public void onMapReady(GoogleMap map) {
googleMap = map;
mGoogleApiClient=new GoogleApiClient.Builder(activity)
.addApi(LocationServices.API)
.addConnectionCallbacks(activity)
.addOnConnectionFailedListener(activity)
.build();
mGoogleApiClient.connect();
}
In this onMapReady, .addConnectionCallbacks(activity) and .addOnConnectionFailedListener(activity) are giving warning like in the image;
enter image description here
In the examples that I have analyzed before they are implementing GoogleApiClient.ConnectionCallbacks and GoogleApiCleint.OnConnectionFailedListener not casting. Without implementing, I couldn't get these functions;
#Override
public void onConnected(Bundle bundle) {
mLocationRequest=LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(1000);
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,mLocationRequest,this);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
And also I have to get LocationListeners's method;
#Override
public void onLocationChanged(Location location) {
if(location == null){
Toast.makeText(this,"Cant get current location",Toast.LENGTH_LONG).show();
}
else{
LatLng ll= new LatLng(location.getLatitude(),location.getLongitude());
CameraUpdate update= CameraUpdateFactory.newLatLngZoom(ll,15);
mGoogleMap.animateCamera(update);
}
}
If I implement them by hand in the fragment, does it cause any problem? What is the proper way to get current location in fragment activity?
If I implement them by hand in the fragment, does it cause any
problem?
No. All you need to do is implement ConnectionCallbacks and OnConnectionFailedListener.
What is the proper way to get current location in fragment activity?
public class MyFragment extends Fragment implements
ConnectionCallbacks, OnConnectionFailedListener {
// Create an instance of GoogleAPIClient.
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
protected void onStart() {
mGoogleApiClient.connect();
super.onStart();
}
protected void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
#Override
public void onConnected(Bundle connectionHint) {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
mGoogleApiClient); // this is your location
if (mLastLocation != null) {
mLatitudeText.setText(String.valueOf(mLastLocation.getLatitude()));
mLongitudeText.setText(String.valueOf(mLastLocation.getLongitude()));
}
}
}
Reference
I have implemented a Fragment in Activity and Location listener and MapReady is called in fragment to get current location. Refer the below code.
MainActivity.Java
public class MainActivity extends AppCompatActivity {
public static final String TAG = MainActivity.class.getSimpleName();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setFragment(new MapFragment());
}
// class for being re-used by several instances
protected void setFragment(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction =
fragmentManager.beginTransaction();
fragmentTransaction.replace(android.R.id.content, fragment);
fragmentTransaction.commit();
}
}
Activity_Main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">
<FrameLayout
android:id="#+id/frame_containerone"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="#+id/imagenext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_margin="16dp"
/>
</RelativeLayout>
MapFragment.Java
public class MapFragment extends Fragment implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener, OnMapReadyCallback {
private static final String TAG = "MapFragment";
MainActivity mActivity;
private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;
private GoogleMap mMap; // Might be null if Google Play services APK is not available.
SupportMapFragment mapFragment;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.map_fragment, null, true);
mActivity = ((MainActivity) getActivity());
initViews(view);
return view;
}
private void initViews(View view) {
mGoogleApiClient = new GoogleApiClient.Builder(mActivity)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
// Create the LocationRequest object
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(10 * 1000) // 10 seconds, in milliseconds
.setFastestInterval(1 * 1000); // 1 second, in milliseconds
mapFragment = (SupportMapFragment) this.getChildFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(GoogleMap map) {
mMap = map;
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if (ActivityCompat.checkSelfPermission(mActivity, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(mActivity, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (location == null) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
} else {
handleNewLocation(location);
}
}
private void handleNewLocation(Location location) {
Log.d(TAG, location.toString());
double currentLatitude = location.getLatitude();
double currentLongitude = location.getLongitude();
LatLng latLng = new LatLng(currentLatitude, currentLongitude);
MarkerOptions options = new MarkerOptions()
.position(latLng)
.title("I am here!");
mMap.addMarker(options);
mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
if (connectionResult.hasResolution()) {
try {
// Start an Activity that tries to resolve the error
connectionResult.startResolutionForResult(mActivity, CONNECTION_FAILURE_RESOLUTION_REQUEST);
/*
* Thrown if Google Play services canceled the original
* PendingIntent
*/
} catch (IntentSender.SendIntentException e) {
// Log the error
e.printStackTrace();
}
} else {
/*
* If no resolution is available, display a dialog to the
* user with the error.
*/
Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode());
}
}
#Override
public void onLocationChanged(Location location) {
handleNewLocation(location);
}
#Override
public void onResume() {
super.onResume();
setUpMapIfNeeded();
mGoogleApiClient.connect();
}
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.
mapFragment = (SupportMapFragment) this.getChildFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);// mapFragment.getMapAsync((OnMapReadyCallback) mActivity);
}
}
#Override
public void onPause() {
super.onPause();
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
mGoogleApiClient.disconnect();
}
}
}
map_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- <fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
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="388dp"
android:layout_weight="0.40" />
</LinearLayout>
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.theme.fragment">
<permission
android:name="com.theme.fragment.permission.MAPS_RECEIVE"
android:protectionLevel="signature" />
<uses-permission android:name="com.theme.fragment.permission.MAPS_RECEIVE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- Required to show current location -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="#string/app_name"
android:supportsRtl="true"
android:theme="#style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Goolge API Key -->
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="Your_Api key" />
</application>
</manifest>
build.grade
compile 'com.android.support:appcompat-v7:25.3.0'
compile 'com.android.support.constraint:constraint-layout:1.0.1'
compile 'com.google.android.gms:play-services:10.2.1'
AndroidManifest.xml
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<meta-data android:name="com.google.android.geo.API_KEY"
android:value="#string/str_map_key"/>
<meta-data android:name="com.google.android.gms.version"
android:value="#integer/google_play_services_version"/>
MainActivity.java
public class MainActivity extends AppCompatActivity
implements OnMapReadyCallback,
ActivityCompat.OnRequestPermissionsResultCallback,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private GoogleMap mGoogleMap;
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1;
private boolean mPermissionDenied = false;
private GoogleApiClient mGoogleApiClient;
private Location mLastLocation;
//TextView
TextView longitudeTextView;
TextView lattitudeTextView;
private LocationRequest mLocationRequest;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
MapFragment mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map_view);
mapFragment.getMapAsync(this);
longitudeTextView = (TextView) findViewById(R.id.main_longitude_text);
lattitudeTextView = (TextView) findViewById(R.id.main_lattitude_text);
}
#Override
protected void onStart() {
//when activity is create GoogleMapApiClient is build there under onCreate
//than on activity start we gonna connect it to Google
mGoogleApiClient.connect();
super.onStart();
}
#Override
protected void onStop() {
//when activity is stopped disconnect GoogleApiClient
super.onStop();
mGoogleApiClient.disconnect();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
enableMyLocation();
}
private void enableMyLocation() {
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
//Permission to access the location is missing
ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
LOCATION_PERMISSION_REQUEST_CODE);
} else {
//Access to location has been granted to app
mGoogleMap.setMyLocationEnabled(true);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode != LOCATION_PERMISSION_REQUEST_CODE) {
return;
}
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Enable the my location layer if the permission has been granted.
enableMyLocation();
} else {
// Display the missing permission error dialog when the fragments resume.
mPermissionDenied = true;
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
mLocationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(100);
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Location permission missing !!", Toast.LENGTH_LONG).show();
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
public void onLocationChanged(Location location) {
//displaying coordinates on screen for test purpose only
longitudeTextView.setText(String.valueOf(location.getLongitude()));
lattitudeTextView.setText(String.valueOf(location.getLatitude()));
LatLng latLng = new LatLng(location.getLongitude(), location.getLatitude());
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 15);
mGoogleMap.moveCamera(cameraUpdate);
}
}
Very Basic app to move camera to new coordinates.
onLocationChanged is called whenever location is changed . It should move camera to new coordinates but instead of this it starts pointing to somewhere in Barents sea. I have gone throw whole documentation more than 5 times still didn't get it.
On app start
https://s10.postimg.org/xywc61w2x/Screenshot_20170325-123853.png
Where i am actually
https://s10.postimg.org/d4ol1yr3d/Screenshot_20170325-132620.png
Tested on both Emulator and Real Device.
Those coordinates 75.8467264/30.862686 and 75.8467229/30.862678 are at the Barents sea.
Change
LatLng latLng = new LatLng(location.getLongitude(), location.getLatitude());
to
LatLng latLng = new LatLng(location.getLatitude, location.getLongitude()());
in onLocationChanged() to view northern India on the map.
I am having some prolems with my google maps app. For now the app was only suppost to get my location em zoom in it, but is not working. My location aways ends in the top of the map. Here is my code:
MainActivity:
public class MainActivity extends Activity implements LocationListener {
private GoogleMap googleMap;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (isGooglePlayOk()) {
setContentView(R.layout.activity_main);
setMap();
googleMap.setMyLocationEnabled(true);
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// TODO Auto-generated method stub
switch (item.getItemId()) {
case R.id.action_legalnotices:
startActivity(new Intent(this, LegalNoticeActivity.class));
return true;
default:
return false;
}
}
private boolean isGooglePlayOk() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (status == ConnectionResult.SUCCESS) {
return (true);
}
else {
((Dialog) GooglePlayServicesUtil.getErrorDialog(status, this, 10))
.show();
}
return (false);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void setMap() {
if (googleMap == null) {
googleMap = ((MapFragment) getFragmentManager().findFragmentById(
R.main.map)).getMap();
if (googleMap != null) {
}
googleMap.setMyLocationEnabled(true);
LocationManager la = (LocationManager) getSystemService(LOCATION_SERVICE);
String provider = la.getBestProvider(new Criteria(), true);
Location loc = la.getLastKnownLocation(provider);
if (provider != null) {
onLocationChanged(loc);
}
googleMap.setOnMapLongClickListener(onLongClickMapSettiins());
}
}
private OnMapLongClickListener onLongClickMapSettiins() {
// TODO Auto-generated method stub
return new OnMapLongClickListener() {
#Override
public void onMapLongClick(LatLng point) {
Toast.makeText(getApplicationContext(), "OK",
Toast.LENGTH_SHORT).show();
}
};
}
#Override
public void onLocationChanged(Location location) {
LatLng latlong = new LatLng(location.getLatitude(),
location.getLongitude());
googleMap.setMyLocationEnabled(true);
CameraPosition cp = new CameraPosition.Builder().target(latlong)
.zoom(15).build();
googleMap.moveCamera(CameraUpdateFactory.newCameraPosition(cp));
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// TODO Auto-generated method stub
}
}
activity_main:
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+main/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.google.android.gms.maps.MapFragment"/>
Manifest:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mapateste"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-feature
android:glEsVersion="0x00020000"
android:required="true" />
<!--
The following two permissions are not required to use
Google Maps Android API v2, but are recommended.
-->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<meta-data
android:name="com.google.android.maps.v2.API_KEY"
android:value="(My Api is working fine)" />
<activity
android:name="com.example.mapateste.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.example.mapateste.LegalNoticeActivity"
android:label="#string/title_activity_legal_notice" >
</activity>
</application>
I can only test in my device. The map is working fine but i cannot get my position on the center of the screen right away only clicking at the mylocationbutton. Somebody can help me?
Just declare a point where you want to center your point.
LatLng cur_Latlng = new LatLng(21.0000, 78.0000);
gm.moveCamera(CameraUpdateFactory.newLatLng(cur_Latlng));
gm.animateCamera(CameraUpdateFactory.zoomTo(4));
the desired zoom level is in the range of 2.0 to 21.0.
// try this
#Override
public void onLocationChanged(Location location) {
LatLng latlong = new LatLng(location.getLatitude(),
location.getLongitude());
googleMap.animateCamera(CameraUpdateFactory.newLatLng(latlong));
googleMap.animateCamera(CameraUpdateFactory.zoomBy(15));
}
Your min sdk is 8. You should use SupportMapFragment. Your class must extend FragmentActivtiy
Check the line above developers guide heading in the below link
https://developers.google.com/maps/documentation/android/reference/com/google/android/gms/maps/MapFragment
<fragment
class="com.google.android.gms.maps.SupportMapFragment"
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
Use SupportMapFragment
SupportMapFragment fm = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
GoogleMap mMap = fm.getMap();
Make sure you have added support library
Also make sure you imported the below
import android.support.v4.app.FragmentActivity;
import com.google.android.gms.maps.SupportMapFragment
To zoom
CameraUpdate update = CameraUpdateFactory.newLatLngZoom(latlong,20);
googleMap.moveCamera(update);
This is working Current Location with zoom for Google Map V2
double lat= location.getLatitude();
double lng = location.getLongitude();
LatLng ll = new LatLng(lat, lng);
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(ll, 20));
Note that the My Location layer does not return any data. If you wish to access location data programmatically, use the Location API.
In your MainActivity (onCreate Method)
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(MainActivity.this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
On method onMapReady
#Override
public void onMapReady(GoogleMap googleMap) {
GoogleMap mMap = googleMap;
// Set blue point on the map at your cuurent location
mMap.setMyLocationEnabled(true);
// Show zoon controls on the map layer
mMap.getUiSettings().setZoomControlsEnabled(true);
//Show My Location Button on the map
mMap.getUiSettings().setMyLocationButtonEnabled(true);
}
on method onConnected
#Override
public void onConnected(Bundle bundle) {
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if (mLastLocation != null) {
LocationListener.latlonInit= new LatLng(mLastLocation.getLatitude(),mLastLocation.getLongitude());
CameraPosition target = CameraPosition.builder().tilt(66.0f).target(LocationListener.latlonInit)
.zoom(MainActivity.ZOOM).build();
mMap.moveCamera(CameraUpdateFactory.newCameraPosition(target));
}
}
You class should extend Fragment Activity
public class MainActivity extends FragmentActivity {
//assign any arbitrary value to GPS_ERRODIALOG_REQUEST
private static final int GPS_ERRORDIALOG_REQUEST = 9001;
GoogleMap googlemap;
}
for Google Service Ok method I would do Following:
public boolean isGooglePlayOk(){
int isAvailable = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (isAvailable == ConnectionResult.SUCCESS) {
return true;
}
else if(GooglePlayServicesUtil.isUserRecoverableError(isAvailable)){
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(isAvailable, this, GPS_ERRORDIALOG_REQUEST);
dialog.show();
}
else {
Toast.makeText(this, "Can't connect to Goolge Play", Toast.LENGTH_SHORT).show();
}
return false;
}
In the .xml file, when you declare the fragment, you need to support Map Fragment since your min skd is 8:
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:maps="http://schemas.android.com/apk/res-auto"
android:id="#+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
activity_map.xml is for displaying map if condition is true for setMap else go to you regular activity_main.xml.
public class MainActivity extends FragmentActivity {
GoogleMap mMap;
if (isGooglePlayOk()) {
setContentView(R.layout.activity_map);
if (setMap()) {
mMap.setMyLocationEnabled(true);
}
else {
//your code
}
}
else {
setContentView(R.layout.activity_main);
}
method for setMap:
private boolean setMap() {
if (mMap == null) {
SupportMapFragment mapFrag =
(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mMap = mapFrag.getMap();
}
return (mMap != null);
}
If you want to automatically zoom to some point in google maps v2 u can do like this
private float previousZoomLevel = 13.00f;
LatLng zoomPoint = new LatLng(12.977286, 77.632720);
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(zoomPoint,previousZoomLevel));
here previousZoomLevel is level of zoom
First of all, I´ve been searching for an answer for this the whole evening. I have read many of the questions -probably all- asking why OnloCationChanged is not called... nothing helped me.
I have a Fragment that displays a map. I can add markers to it and it also shows the current location of the user correctly. Everything seems to be ok but, I want to zoom in the user´s location and that´s why I need the method "OnLocationChanged" to be called.
Also, locationManager.getLastKnownLocation(provider) returns always null.
I have tested this in a real device.
Here is my configuration, I hope somebody can point me in the right direction.
Thanks
Fragment Class
public class MapMainFragment extends BaseFragment implements LocationListener{
private SupportMapFragment fragment;
private GoogleMap map;
private LocationManager locationManager;
private static final long MIN_TIME = 500;
private static final float MIN_DISTANCE = 0;
String provider;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// LOCATION
locationManager = (LocationManager) mActivity.getSystemService(Context.LOCATION_SERVICE);
boolean enabledGPS = locationManager
.isProviderEnabled(LocationManager.GPS_PROVIDER);
boolean enabledWiFi = locationManager
.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
// Check if enabled and if not send user to the GSP settings
if (!enabledGPS && !enabledWiFi) {
Toast.makeText(mActivity, "GPS signal not found", Toast.LENGTH_LONG).show();
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
// Define the criteria how to select the location provider -> use
// default
Criteria criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, false);
Location location = locationManager.getLastKnownLocation(provider);
// Initialize the location fields
if (location != null) {
Toast.makeText(mActivity, "Selected Provider " + provider,
Toast.LENGTH_SHORT).show();
onLocationChanged(location);
}
locationManager.requestLocationUpdates(provider, MIN_TIME, MIN_DISTANCE, this);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.app_tab_b_second_screen, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
FragmentManager fm = getChildFragmentManager();
fragment = (SupportMapFragment) fm.findFragmentById(R.id.map);
if (fragment == null) {
fragment = SupportMapFragment.newInstance();
fm.beginTransaction().replace(R.id.map, fragment).commit();
}
}
#Override
public void onResume() {
super.onResume();
map = fragment.getMap();
// Enabling MyLocation Layer of Google Map
map.setMyLocationEnabled(true);
// Add Marker
final LatLng TEST_MARKER = new LatLng(50.34927, 6.26887);
map.addMarker(new MarkerOptions()
.position(TEST_MARKER)
.title("Title")
.snippet("Sheeps: 4,137,400")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN)));
}
#Override
public void onLocationChanged(Location location) {
Log.e("onLocationChanged", "called");
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 10);
map.animateCamera(cameraUpdate);
locationManager.removeUpdates(this);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) { }
#Override
public void onProviderEnabled(String provider) {
Toast.makeText(mActivity, "Enabled new provider " + provider,
Toast.LENGTH_SHORT).show();
}
#Override
public void onProviderDisabled(String provider) {
Toast.makeText(mActivity, "Disabled provider " + provider,
Toast.LENGTH_SHORT).show();
}
BaseFragment class
public class BaseFragment extends Fragment {
public AppMainTabActivity mActivity;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mActivity = (AppMainTabActivity) this.getActivity();
}
public boolean onBackPressed(){
return false;
}
public void onActivityResult(int requestCode, int resultCode, Intent data){
}
}
Manifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-feature
android:glEsVersion="0x00020000"
android:required="true"/>
I think in your onlocation change it runs but the you remove the updates and it doesn't run any more
Comment out this line in onlocationchanged
locationManager.removeUpdates(this);
And your getbestprovider method use true instead of false