I am new to Android programming , your help is very much needed .
i tried to disable GPS by the code
Settings.Secure.setLocationProviderEnabled(getContentResolver(), LocationManager.GPS_PROVIDER, false);
also had set the permissions in AndroidManifest.xml file as
.
.
.
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
but in when i run the application it says
Not granting permission android.permission.WRITE_SECURE_SETTINGS to package .....
and my application crashes saying
ava.lang.SecurityException: Permission denial: writing to secure settings requires android.permission.WRITE_SECURE_SETTINGS
thx for help in advance :)
You can start the GPS by using
LocationManager locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
LocationListener locationListener = new CTLocationListener();
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 1.0f, locationListener);
To stop the gps provider use
locationManager.removeUpdates(locationListener);
If you're trying to actually disable the GPS chip then my understanding of the android system is that this isn't possible. You have to ask the user to enable or disable the GPS via the Setting menu.
See this question: How can I get the dreaded WRITE_SECURE_SETTINGS permission for my android app?
In the past it was possible and system level apps can use that permission, a normal app cannot take advantage of it.
I guess your users are complaining that your app can see their location.
For not showing that message when they install the app, you must remove:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
You may also try to use the getLastKnownLocation in order to save battery. It doesn't turn the GPS on and may use the network cell data (COARSE_LOCATION).
public Location getLocation() {
if (contextReference == null) {
return null;
}
Context context = contextReference.get();
if (context == null) {
return null;
}
Location location = null;
if (context
.checkCallingOrSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
LocationManager lm = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
} else if (context
.checkCallingOrSelfPermission(android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
LocationManager lm = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
location = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
return location;
}
Related
I want to access fine location from within my app and, for this, I declare an ActivityResultLauncherwith :
protected final ActivityResultLauncher<String[]> l = registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), isGranted -> {
if (isGranted .get(Manifest.permission.ACCESS_COARSE_LOCATION) & isGranted .get(Manifest.permission.ACCESS_FINE_LOCATION)) {
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, positionChangesListener);
} else {
Toast.makeText(this, getResources().getText(R.string.PermissionNotAllowed), Toast.LENGTH_LONG).show()
finish();
}
});
When I want to ask for this permission, I use :
l.launch(new String [] {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION});
Unfortunately, the panel asking the user to grant permission doesn't show up. This doesn't prevent the callback from being executed, but with permissions denied. My app then immediatly stops, informing the user it can't continue to work if fine location permission isn't granted.
Any idea which could solve my problem?
wait where are asking for permission shouldn't it be in else ? after that have you added <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> and <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
in your manifest
We have in-house tablets, that we control, and we have the requirement that their recorded location be as accurate as possible. I do everything I should to turn on real GNSS GPS, but getLastKnownLocation("gps") always returns null.
We use a Samsung Galaxy Tab A7, SM-T500, whose specifications swear it has a real GPS GNSS radio receiver. Google Maps identifies my secret lair correctly.
Our AndroidManifest.xml requests GPS permissions:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<activity
android:name=".MainActivity"
android:foregroundServiceType="location"
...
>
In the tablet's Settings, our app has Location permission "Only while app is in use," which is fine because our app dominates our tablet and is interactive. Our tablet is not used in a vehicle, so the location only needs to be accurate within the last 10 minutes or so.
locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) returns true, as does that call with PASSIVE_PROVIDER and NETWORK_PROVIDER. The "fused" provider is not available.
Then we call this, to pull every kind of location and return the most accurate one:
private static Location getLastKnownLocation(#NonNull LocationManager locationManager) {
List<String> providers = locationManager.getProviders(true);
Location bestLocation = null;
for (String provider : providers) {
Location l = locationManager.getLastKnownLocation(provider);
if (l == null)
continue;
if (bestLocation == null || l.getAccuracy() < bestLocation.getAccuracy())
bestLocation = l; // Found best last known location: %s", l);
}
return bestLocation;
}
All we get is "passive." Do GPS locations specifically require a round-trip thru locationManager.requestLocationUpdates(), or is getLastKnownLocation() good enough?
Similar answers are elsewhere but this thread deserves closure. It seems getLastKnownLocation() does not work with GPS and GNSS satellites, so as Phantom Lord prompted the correct fix is to enable my main activity for GPS:
public class MainActivity extends AppCompatActivity implements LocationListener {
Then in onCreate() turn on a listener:
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (locationManager != null) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return; // TODO spank user
}
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3000, 10, this);
}
Then catch the updates:
private Location gpsLocation = null;
#Override
public void onLocationChanged(Location location) {
gpsLocation = location;
}
Now a new question: Why is the passive location accuracy ~5 meters while the GPS location accuracy is ~14 meters? This is a naive tablet, so it certainly doesn't know my home address and such. According to my internet spam, my IP address is in a nearby city...
Lastly I ran into problem that, I can't scan for beacons because of lack of ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION.
I tried to fix it by using code found here, but it actually help me partially.
When this view appears
I click allow. After that I doesn't get this java.lang.SecurityException: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION permission to get scan results error anymore, but I can't still see my beacons and when I open settings view the location is turned off like on picture bellow.
When I turn on location by finger everything works ok, so I can see my beacons and app works as it should. And here is the question is these some kind of bug or I missed something to turn on location from code behind after access to device location is turned on?
For developing I use Nexus 5x with android 7.1.1.
EDITED:
Code is copied from tutorial linked above, the fragment with button which starts beacon scanner:
public void onBleClicked(View view)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){
if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("This app needs location access");
builder.setMessage("Please grant location access so this app can detect beacons.");
builder.setPositiveButton(android.R.string.ok, null);
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
}
}
});
builder.show();
}
BleManager bleManager = new BleManager(this);
bleManager.tryToTurnOnBle();
}
Fragment of manifest where permissions are declared:
<!-- app only for phones -->
<uses-feature android:name="android.hardware.telephony"/>
<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" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
The bluetooth permissions are apparently in library.
What I found right now is fact that there is similar question to mine here.
But this solution with redirecting user to location option screen is not seems to be clean one for me.
Location can be determined by two ways:
1.Using NETWORK_PROVIDER
2.Using GPS_PROVIDER
NETWORK_PROVIDER: It determines the location of the users using cell towers,wifi access points. It is commonly used for determining location inside the rooms or buildings. Here the GPS coordinates are not able to be obtained.
You can specify either
<uses-permission android:name=”android.permission.ACCESS_COARSE_LOCATION” />
or
<uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION” />
in order to get location using the NETWORK_PROVIDER.
GPS_PROVIDER:
It determines the location of the users using satellites. For this, the GPS coordinates are obtained and used for positioning. The GPS receiver in the smartphone receives the signals from satellites. These signals are processed and precise locations are determined.It works better in outdoors – direct sky/satellite views and communication occurs.
You need specify the permission
<uses-permission android:name=”android.permission.ACCESS_FINE_LOCATION” />
in order to use location from GPS_PROVIDER.
Fine locations:
It gives better and accurate locations. So, that I recommend you to use this to get your beacon locations. It gives permission for using both GPS_PROVIDER and NETWORK_PROVIDER or GPS_PROVIDER only for determining the position.
Coarse locations:
It provides less accurate locations.It gives permission for using NETWORK_PROVIDER only for determining the position.
Now, come to the implementation.
- Declare the above said two permissions in the AnroidManifest.xml file:
- In the java part, do the following:
Request the permission if it not granted yet:
private void requestPermission(Activity activity) {
ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.CALL_PHONE}, MainActivity.PERMISSION_REQUEST_CODE_LOCATION);
}
When the above method is called, a dialog asking permission will appear. On selecting Allow or Deny, the below callback gets triggered.
In the onRequestPermissionsResult
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case PERMISSION_REQUEST_CODE_LOCATION:
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
boolean isGpsProviderEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
boolean isNetworkProviderEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
//Location permission is given. Check if the providers are available and start location updates.
if (isGpsProviderEnabled && isNetworkProviderEnabled) {
startLocationUpdates();
} else {
Log.d(TAG, "GPS and Network providers are disabled");
}
} else if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_DENIED) {
boolean should = ActivityCompat.shouldShowRequestPermissionRationale(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION);
if (should) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MainActivity.PERMISSION_REQUEST_CODE_LOCATION);
} else {
promptSettings();
}
}
}
}
In the promptSettings() method, let the user to enable location from the Settings screen.
private void promptSettings() {
AlertDialog.Builder builder;
builder = new AlertDialog.Builder(MainActivity.this);
builder.setTitle(getResources().getString(R.string.unable_to_find_location));
builder.setMessage(getResources().getString(R.string.message_denied_location_permission));
builder.setCancelable(false);
builder.setPositiveButton(getResources().getString(R.string.go_to_settings), (dialog, which) -> {
dialog.dismiss();
builder = null;
if (!checkPermission(MainActivity.this)) {
goToSettings();
}
});
builder.show();
}
In the check permissions method:
public boolean checkPermission(Context context) {
int result = ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION);
return result == PackageManager.PERMISSION_GRANTED;
}
The goToSettings() allows the user to go to Settings screen:
private void goToSettings() {
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivityForResult(intent, 1);
}
Note: You need to give the below permissions in the manifest to scan the beacons. I hope you are doing that, if not please do it.
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
As of Android Marshmallow (6.0), Location must be turned on in settings for apps to scan for Bluetooth LE devices including beacons. This requirement is in addition to the requirement that apps get dynamic permissions. You can see code below to query for location services being turned on and to prompt the user to turn it on if needed.
private void verifyLocationServices() {
final LocationManager manager = (LocationManager) getSystemService(this.LOCATION_SERVICE);
if (!manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage("This app requires that location services be enabled. Please enable location in settings.")
.setCancelable(false)
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
public void onClick(final DialogInterface dialog, final int id) {
startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
}
});
final AlertDialog alert = builder.create();
alert.show();
}
}
I want to get current latitude and longitude of device even when it is not in movement.
Tried both requestLocationUpdates() and requestSingleUpdate() but my location is still null. LocationManager.onLocationChanged() seems to be called only when location gets changed. I want to post this location details but fails with NullPointerException every time.
Here are my code samples:
Activity:
startButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, myLocationListener);
if (location == null) {
try {
locationManager.requestSingleUpdate(LocationManager.GPS_PROVIDER, myLocationListener, Looper.myLooper());
} catch (SecurityException e) {
}
}
//MyLocationListener
public void onLocationChanged(Location location) {
activity.setLocation(location);
}
}
}
Manifest:
<uses-permission android:name="android.permission.ACCESS_GPS" />
<uses-permission android:name="android.permission.ACCESS_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
If the user has not used GPS for a while, there will be no last known location, hence the GPS provider will not update at all unless you move outside. Its better to use the new FusedLocationApi to get updates as it selects the best source for you and gives you the best possible location.
https://developer.android.com/training/location/receive-location-updates.html
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient, mLocationRequest, this);
Trying putting your code in AsyncTask.
I've a TI OMAP platform running Kitkat 4.4.4. The platform doesn't have Wifi/GPS/Cellular connection but it has ethernet. I use eth1 to access internet.
Is there anyway to determine the coarse geographical location of the device based on eth1. I tried the sample code below, but it fails for ethernet connection.
/** Check if we can get our location */
public void checkLocation(){
// Get the location manager
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
String locationProvider = LocationManager.NETWORK_PROVIDER;
try{
// Define a listener that responds to location updates
locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
Log.d(TAG,"Latitude: " + location.getLatitude() + ", Longitude = " + location.getLongitude());
}
public void onStatusChanged(String provider, int status, Bundle extras) {Log.d(TAG,"location found 1");}
public void onProviderEnabled(String provider) {Log.d(TAG,"location found 2");}
public void onProviderDisabled(String provider) {Log.d(TAG,"location found 3");}
};
locationManager.requestLocationUpdates(locationProvider, 0, 0, locationListener);
}catch(Exception e){
Log.e(TAG, "Location Exception: " + e.getMessage());
}
}
Above code throws provider doesn't exist: network exception for ethernet. Works OK on a device with wifi/GPS.
I've also set the following permissions in manifest file.
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Any ideas how to determine location if the device has on ethernet connectivity?
Thanks
You can use
locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
and
locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
to check the availability of your network or gps. If these two return false to you, then you might not be able to use the locationManager to find location.