setMyLocationEnabled on Marshmallow - google-maps

I started programming recently and im trying to make a basic map aplication with the location button enabled, in android 6.0 Marshmallow.
I think i have understood how works the new permission model. When i run the app, it asks me to give location permission but, when i give it, the location button doesn´t appears. If i restart the app it already appears.
I will put the code of my onMapReady method:
#Override
public void onMapReady(GoogleMap map) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
map.setMyLocationEnabled(true);
} else {
// Show rationale and request permission.
Toast toast = Toast.makeText(this, "need permission", Toast.LENGTH_LONG);
toast.show();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 0);
}
}
map.setMyLocationEnabled(true);
}
I've tried to change the last setMyLocationEnabled inside the else but it didn't work. I know that it's a little silly question but i don't know how to solve it.
Hope someone can help me. Thanks in advance

You may add the code below.
In earlier version of Android, at installation time, it shows users the permission dialog and they were granted the defined permission in your manifest file to the application.
This changed in Marshmallow. Now, each application should have to ask permission from user to access the it.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M)
{
System.out.println("CHECK_RUN_TIME_PERMISSION_IF_MARSHMELLOW");
if(!checkPermission()) {
requestPermission();
}else {
System.out.println("CHECK_RUN_TIME_PERMISSION_IF_MARSHMELLOW++");
}
}
private boolean checkPermission(){
int result = ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION);
if (result == PackageManager.PERMISSION_GRANTED){
return true;
} else {
return false;
}
}
private void requestPermission(){
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this,Manifest.permission.ACCESS_FINE_LOCATION)){
Toast.makeText(MainActivity.this,"GPS permission allows us to access location data. Please allow in App Settings for additional functionality.",Toast.LENGTH_LONG).show();
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},PERMISSION_REQUEST_CODE);
} else {
ActivityCompat.requestPermissions(MainActivity.this,new String[]{Manifest.permission.ACCESS_FINE_LOCATION},PERMISSION_REQUEST_CODE);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case PERMISSION_REQUEST_CODE:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(MainActivity.this,"Permission Granted, Now you can access location data.",Toast.LENGTH_LONG).show();
} else {
Toast.makeText(MainActivity.this,"Permission Denied, You cannot access location data.",Toast.LENGTH_LONG).show();
}
break;
}
}

Related

Current Location is not display above Api 23

I am displaying Map using Map view and before API 23 my App is Working fine and showing current location but when I run on 23 and above it's not showing current location.My code is as follow:
mMap = googleMap;
mMap.getUiSettings().setMapToolbarEnabled(false);
LatLng loc = new LatLng(currentLatitude, currentLongitude);
//mMap.addMarker(new MarkerOptions().position(loc).title(currentLocation + ", none"));
//mMap.moveCamera(CameraUpdateFactory.newLatLng(loc));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(loc, 14.0f));
if (ActivityCompat.checkSelfPermission(MapClass.this.getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(MapClass.this.getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
mMap.setMyLocationEnabled(true);
help me?
I might be a little late, but this answer will help people, who are having the same issue and want to run their app on both the versions. The catch is that for API's more than 21, you need to ask for Run time permission.
Firstly, I created a function named gettingLocationBasedOnApiVersion(mMap) in which I put all the code for which I used user's location. But beforehand, in the onMapReady()I checked for the API version and if the API version is more than 21, I asked for permissions.
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
if(Build.VERSION.SDK_INT <= 21){
gettingLocationBasedOnApiVersion(mMap);
Toast.makeText(getApplicationContext(), "APK less than 21", Toast.LENGTH_LONG).show();
}else{
Log.i("SDK Version", "SDK more than 21 will require permissions on run time");
Toast.makeText(getApplicationContext(), "APK greater than 21", Toast.LENGTH_LONG).show();
enableMyLocation();
}
}
Then In the enable function I asked for the run time permissions.
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1;
private boolean mPermissionDenied = false;
private void enableMyLocation() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Permission to access the location is missing.
PermissionUtils.requestPermission(this, LOCATION_PERMISSION_REQUEST_CODE,
Manifest.permission.ACCESS_FINE_LOCATION, true);
} else if (mMap != null) {
// Access to the location has been granted to the app.
mMap.setMyLocationEnabled(true);
gettingLocationBasedOnApiVersion(mMap);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode != LOCATION_PERMISSION_REQUEST_CODE) {
return;
}
if (PermissionUtils.isPermissionGranted(permissions, grantResults,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// 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
protected void onResumeFragments() {
super.onResumeFragments();
if (mPermissionDenied) {
// Permission was not granted, display error dialog.
showMissingPermissionError();
mPermissionDenied = false;
}
}
/**
* Displays a dialog with error message explaining that the location permission is missing.
*/
private void showMissingPermissionError() {
PermissionUtils.PermissionDeniedDialog
.newInstance(true).show(getSupportFragmentManager(), "dialog");
}
For better understanding, use you can refer the Places Class on my github page.
PS. Don't forget to add the PermissionUtils Class in your app folder.
Checking the document about Requesting Permissions at Run Time it is stated that:
Beginning in Android 6.0 (API level 23), users grant permissions to apps while the app is running, not when they install the app. This approach streamlines the app install process, since the user does not need to grant permissions when they install or update the app. It also gives the user more control over the app's functionality; for example, a user could choose to give a camera app access to the camera but not to the device location. The user can revoke the permissions at any time, by going to the app's Settings screen.
If the device is running Android 6.0 or higher, and your app's target SDK is 23 or higher: The app has to list the permissions in the manifest, and it must request each dangerous permission it needs while the app is running. The user can grant or deny each permission, and the app can continue to run with limited capabilities even if the user denies a permission request
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode != LOCATION_PERMISSION_REQUEST_CODE) {
return;
}
if (PermissionUtils.isPermissionGranted(permissions, grantResults,
Manifest.permission.ACCESS_FINE_LOCATION)) {
// 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;
}
}
The ApiDemos repository on GitHub includes samples that demonstrate the use of location on a map:
MyLocationDemoActivity: Using the My Location layer, including runtime permissions
LocationSourceDemoActivity: Using a custom LocationSource
Hope this helps.

Google Drive Auth Always returns 0

I am using the code as shown in this https://developers.google.com/drive/android/auth#connecting_and_authorizing_the_google_drive_android_api
In my app I click to connect to Drive, but it results in this line being executed
connectionResult.startResolutionForResult(this, 1);
As the connection fails.
Then it opens an account menu for me to choose an account. When I click it then the dialog dismisses and I still can not connect to Google Drive because everytime the result code is 0
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
switch (requestCode) {
case 1:
if (resultCode == RESULT_OK) {
mGoogleApiClient.connect();
}
break;
}
}
I would assume the code is correct, but does anyone know what I need to do to prevent is canceling? I believe I set up my credentials correctly for the OA Auth
I tried using the Drive demo code by Google here and I was able to run the android sample.
Check their implementation of authentication and try to compare it with yours. Here's the relevant part:
#Override
protected void onResume() {
super.onResume();
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(Drive.API)
.addScope(Drive.SCOPE_FILE)
.addScope(Drive.SCOPE_APPFOLDER) // required for App Folder sample
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
}
mGoogleApiClient.connect();
}
/**
* Handles resolution callbacks.
*/
#Override
protected void onActivityResult(int requestCode, int resultCode,
Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_RESOLUTION && resultCode == RESULT_OK) {
mGoogleApiClient.connect();
}
}
I was able to login successfully and tried out some of the features.
If you're going to use this sample, don't forget to setup your Credentials like Oauth CliendID and indicate the correct package name indicated in the Getting Started guide.
Here's what it looks like:

Authorization scope does not appear

I created a new app and the authentication part for GoogleFit is a complete copy/paste of another app that works perfectly. The window to choose an account appears but after that I'm expecting to see the window that showing needed scope but nothing.
Is there someone who already encountered this issue ?
I can post my code if needed.
Thanks a lot !
Edit
This is my code to connect to Google Fit:
private void buildFitnessClient() {
// Create the Google API Client
mFitClient = new GoogleApiClient.Builder(this)
.addApi(Fitness.HISTORY_API)
.addApi(Fitness.RECORDING_API)
.addApi(Fitness.CONFIG_API)
.addScope(new Scope(Scopes.FITNESS_LOCATION_READ_WRITE))
.addScope(new Scope((Scopes.FITNESS_NUTRITION_READ_WRITE)))
.addScope(new Scope(Scopes.FITNESS_BODY_READ_WRITE))
.addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
#Override
public void onConnected(Bundle bundle) {
Log.i(TAG, "Connected to Fitness API!!!");
// Now you can make calls to the Fitness APIs.
// Put application specific code here.
// Once connected go the Main2Activity
Intent start_google_plus = new Intent(GoogleFitAuthentication.this, MainActivity.class);
startActivity(start_google_plus);
finish();
}
#Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "onConnectionSuspend");
// If your connection to the sensor gets lost at some point,
// you'll be able to determine the reason and react to it here.
if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_NETWORK_LOST) {
Log.i(TAG, "Connection lost. Cause: Network Lost.");
} else if (i == GoogleApiClient.ConnectionCallbacks.CAUSE_SERVICE_DISCONNECTED) {
Log.i(TAG, "Connection lost. Reason: Service Disconnected");
}
}
}
)
.addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
// Called whenever the API client fails to connect.
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i(TAG, "Connection failed. Cause: " + result.toString());
if (!result.hasResolution()) {
// Show the localized error dialog
GooglePlayServicesUtil.getErrorDialog(result.getErrorCode(),
GoogleFitAuthentication.this, 0).show();
return;
}
// The failure has a resolution. Resolve it.
// Called typically when the app is not yet authorized, and an
// authorization dialog is displayed to the user.
if (!authInProgress) {
try {
Log.i(TAG, "Attempting to resolve failed connection");
authInProgress = true;
result.startResolutionForResult(GoogleFitAuthentication.this, REQUEST_OAUTH);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
}
}
}
)
.build();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "Processing onActivityResult...");
if (requestCode == REQUEST_OAUTH) {
Log.d(TAG, "requestCode == REQUEST_OAUTH");
authInProgress = false;
if (resultCode == RESULT_OK) {
Log.d(TAG, "resultCode == RESULT_OK");
// Make sure the app is not already connected or attempting to connect
if (!mFitClient.isConnecting() && !mFitClient.isConnected()) {
mFitClient.connect();
}
}
}else{
Log.d(TAG, "Impossible to process onActivityResult...");
}
}
#Override
protected void onStart() {
super.onStart();
// Connect to the Fitness API
Log.i(TAG, "Connecting...");
if(mFitClient!=null){
mFitClient.connect();
}
}
#Override
protected void onStop() {
super.onStop();
Log.i(TAG, "onStop...");
if (mFitClient!=null && mFitClient.isConnected()) {
mFitClient.disconnect();
}
}
#Override
protected void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(AUTH_PENDING, authInProgress);
}
When you authorized the scopes , the browser will store your session. So if you again authorize the app in the same browser, you will only shows the scope as Have offline access.

How to verify Google Play Services

Im trying to figure that out for a few days now, but i can't find some good example about the problem. I think i have founded good code example, but i dont know where/how to use it.
About the problem: whenever app comes from foreground i would like to check if the Google play services are avalable. So for that i want use this code:
static final int REQUEST_CODE_RECOVER_PLAY_SERVICES = 1001;
private boolean checkPlayServices() {
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
if (status != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(status)) {
showErrorDialog(status);
} else {
Toast.makeText(this, "This device is not supported.",Toast.LENGTH_LONG).show();
finish();
}
return false;
}
return true;
}
void showErrorDialog(int code) {
GooglePlayServicesUtil.getErrorDialog(code, this,REQUEST_CODE_RECOVER_PLAY_SERVICES).show();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CODE_RECOVER_PLAY_SERVICES:
if (resultCode == RESULT_CANCELED) {
Toast.makeText(this, "Google Play Services must be installed.",Toast.LENGTH_SHORT).show();
finish();
}
return;
}
super.onActivityResult(requestCode, resultCode, data);
}
now i would like to check the services with
if (checkPlayServices()) {
System.out.println("ok");
}
but where? I have tryed to use that code in class that extends the game, but then
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
path cant be found. On the other hand, when i place it in separate activity
public class AuthActivity extends Activity {
//all previous code
}
path is ok. Does someone have any idea how to work that out?
Answer: Because this is Android-specific code, you must use that code in the Android module (containing the Activity class), not in the Core module (containing the class that extends Game).
Reason: If you put that function in the Core module, there is no library dependency of GooglePlayServicesUtil for the Core module, hence you cannot refer to the class GooglePlayServicesUtil. Read more on this link for using Android-specific code.

Embedded Google Map can't get current location in WebView

I followed this tutorial: http://android-er.blogspot.com/2013/03/embed-google-map-in-webview.html
I'm trying to just use the Google Map in the WebView, but it can't get my current location. I've enabled JavaScript on the WebView. What else do I have to enable?
Does anyone know why that might be? Shouldn't it prompt me to use my current location?
Note that I am not interested in using a MapView as an alternative whatsoever. I'm trying to find out what I need to set on the WebView or maybe on the device's location services?
You should permit the web view to access your location by overriding the method onGeolocationPermissionsShowPrompt like this:
webView.setWebChromeClient(new WebChromeClient(){
#Override
public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
callback.invoke(origin, true, false);
}
});
On API 5.x and below, you will need
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
in your AndroidManifest.xml.
But to allow permissions for geolocation on API 6.0+, you have to request the permission at runtime.
To do this, use
private String mGeolocationOrigin;
private GeolocationPermissions.Callback mGeolocationCallback;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// other setup
myWebView.setWebChromeClient(new MyWebChromeClient());
}
private WebChromeClient mWebChromeClient = new WebChromeClient() {
#Override
public void onGeolocationPermissionsShowPrompt(String origin,
GeolocationPermissions.Callback callback) {
// Geolocation permissions coming from this app's Manifest will only be valid for devices with API_VERSION < 23.
// On API 23 and above, we must check for permission, and possibly ask for it.
final String permission = Manifest.permission.ACCESS_FINE_LOCATION;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M ||
ContextCompat.checkSelfPermission(MainActivity.this, permission) == PackageManager.PERMISSION_GRANTED) {
// we're on SDK < 23 OR user has already granted permission
callback.invoke(origin, true, false);
} else {
if (ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, permission)) {
// user has denied this permission before and selected [/] DON'T ASK ME AGAIN
// TODO Best Practice: show an AlertDialog explaining why the user could allow this permission, then ask again
} else {
// ask the user for permissions
ActivityCompat.requestPermissions(MainActivity.this, new String[] {permission}, RP_ACCESS_LOCATION);
mGeolocationOrigin = origin;
mGeolocationCallback = callback;
}
}
}
}
and receive the result:
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case RP_ACCESS_LOCATION:
boolean allow = false;
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// user has allowed these permissions
allow = true;
}
if (mGeolocationCallback != null) {
mGeolocationCallback.invoke(mGeolocationOrigin, allow, false);
}
break;
}
}
in your activity.
You can try GreenDroid with Google Maps.
Checkt it out: https://github.com/cyrilmottier/GreenDroid
You'd have to enable android.permission.ACCESS_FINE_LOCATION and android.permission.INTERNET,
Create a LocationManager instance and LocationListener instance
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationListener locationListener = new MyLocationListener();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 10, locationListener);
and add onLocationChanged(Location loc) method that inside of it have your loc generate the longitude and latitude (String long = loc.getLongitude(); String lat = loc.getLatitude();)
and now use long, lat to generate your mapPath string and continue to generate the WebView
You can use this for ref: http://www.rdcworld-android.blogspot.in/2012/01/get-current-location-coordinates-city.html