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.
Related
I'm using the Google Fit Android API to retrieve fitness data and it all works like a charm. I want to also access the name of the currently logged in user , which should be accessible by GoogleSignInAccount .getDisplayName();
I already asked this question but unfortunately didn't get any replies, and I cant figure it out with the documentation.
Example code:
//Create a FitnessOptions instance, declaring the data types and access type (read and/or write) your app needs:
FitnessOptions fitnessOptions = FitnessOptions.builder()
.addDataType(DataType.TYPE_STEP_COUNT_DELTA, FitnessOptions.ACCESS_READ)
.addDataType(DataType.TYPE_SLEEP_SEGMENT, FitnessOptions.ACCESS_READ)
.addDataType(DataType.TYPE_HEART_RATE_BPM, FitnessOptions.ACCESS_READ)
.addDataType(DataType.AGGREGATE_HEART_RATE_SUMMARY, FitnessOptions.ACCESS_READ)
.build();
//Get an instance of the Account object to use with the API:
GoogleSignInAccount account = GoogleSignIn.getAccountForExtension(this, fitnessOptions);
GoogleSignInAccount acct = GoogleSignIn.getLastSignedInAccount(this);
if (acct != null) {
loggedInUser = account.getDisplayName();
}
The problem is acct.getDisplayname().getGrantedScopes works like a charm, and I see the granted scope. When I try to read .getDisplayName I always get NULL.
I decided to use another way of logging in...
I now use this to configure sign in options and access :
// Configure sign-in to request the user's ID, email address, and basic
// profile. ID and basic profile are included in DEFAULT_SIGN_IN.
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.requestProfile()
.build();
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
Then we start the sign in intent:
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
startActivityForResult(signInIntent, 000000);
And now we handle the result:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
if (requestCode == 000000) {
// The Task returned from this call is always completed, no need to attach
// a listener.
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
handleSignInResult(task);
}
}
private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
try {
GoogleSignInAccount account = completedTask.getResult(ApiException.class);
// Signed in successfully, show authenticated UI.
updateUI(account);
} catch (ApiException e) {
// The ApiException status code indicates the detailed failure reason.
// Please refer to the GoogleSignInStatusCodes class reference for more information.
Log.w(TAG, "signInResult:failed code=" + e.getStatusCode());
updateUI(null);
}
}
Tips: Make sure to use ApiException.class from Google and not AWS
If i run this code on console application:
static async Task Main(string[] _)
{
using var client = new WTelegram.Client();
var user = await client.LoginUserIfNeeded();
Console.WriteLine($"We are logged-in as {user.username ?? user.first_name + " " + user.last_name} (id {user.id})");
}
It will prompt interactively for App api_id and api_hash.
How can i Authorize user on winforms application?. So that i can input the api_id and api_hash through textbox
Edit: (Oct 2022) Latest version of the library has a simplified config system that makes it more easy to use in WinForms apps.
Please take a look at the example WinForms app provided in the repository that demonstrate how to proceed.
The original answer below is still valid but maybe more complex
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
First, you should read WTelegramClient FAQ #3:
3. How to use the library in a WinForms or WPF application
The library should work without a problem in a GUI application.
The difficulty might be in your Config callback when the user must enter the verification code or password, as you can't use Console.ReadLine here.
An easy solution is to call Interaction.InputBox("Enter verification code") instead.
This might require adding a reference (and using) to the Microsoft.VisualBasic assembly.
A more complex solution requires the use of a ManualResetEventSlim that you will wait for in Config callback,
and when the user has provided the verification_code through your GUI, you "set" the event to release your Config callback so it can return the code.
Here is an example solution for your Form class with a ManualResetEventSlim and textboxes:
using Microsoft.VisualBasic;
using TL;
private readonly ManualResetEventSlim _codeReady = new ManualResetEventSlim();
private WTelegram.Client _client;
private User _user;
string Config(string what)
{
switch (what)
{
case "api_id": return textBoxApiID.Text;
case "api_hash": return textBoxApiHash.Text;
case "phone_number": return textBoxPhone.Text;
case "verification_code":
_codeReady.Reset();
_codeReady.Wait();
return textBoxCode.Text;
case "password": return Interaction.InputBox("Enter 2FA password");
default: return null;
};
}
private void textBoxCode_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == '\r') // pressing Return in the textboxCode
{
_codeReady.Set();
e.Handled = true;
}
}
private async void buttonLogin_Click(object sender, EventArgs e)
{
buttonLogin.Enabled = false;
_client = new WTelegram.Client(Config);
_user = await _client.LoginUserIfNeeded();
MessageBox.Show("We are now connected as " + _user);
}
private async void buttonGetChats_Click(object sender, EventArgs e)
{
if (_user == null) { MessageBox.Show("You must complete the login first."); return; }
var chats = await _client.Messages_GetAllChats(null);
MessageBox.Show(string.Join("\n", chats.chats.Values.Where(c => c.IsActive)));
}
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:
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;
}
}
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