Location
API Reference: Device.Location
Location allows capturing location-related events on the device
Android automatically picks a location provider unless you provide manually. This may lead undesired consequences; for instance, GPS provider might be selected in an indoor environment which will cause location update problems.
import PageSampleDesign from "generated/pages/page3";
import { Route, Router } from "@smartface/router";
import Application from "@smartface/native/application";
import Location from "@smartface/native/device/location";
import Permission from '@smartface/native/device/permission';
import System from "@smartface/native/device/system";
//You should create new Page from UI-Editor and extend with it.
export default class Sample extends PageSampleDesign {
constructor(private router?: Router, private route?: Route) {
super({});
}
getCurrentLocation(): void {
Location.start(Location.Android.Priority.HIGH_ACCURACY, 1000);
Location.onLocationChanged = (e): void => {
console.log(`Location latitude ${e.latitude} longitude ${e.longitude}`);
Location.stop();
};
}
// The page design has been made from the code for better
// showcase purposes. As a best practice, remove this and
// use WYSIWYG editor to style your pages.
centerizeTheChildrenLayout() {
this.dispatch({
type: "updateUserStyle",
userStyle: {
flexProps: {
flexDirection: 'ROW',
justifyContent: 'CENTER',
alignItems: 'CENTER'
}
}
})
}
onShow() {
super.onShow();
const { headerBar } = this;
Application.statusBar.visible = false;
headerBar.visible = false;
}
onLoad() {
super.onLoad();
this.centerizeTheChildrenLayout();
Location.android.checkSettings({
onSuccess: () => {
console.log("Location.checkSettings onSuccess");
Permission.android.requestPermissions(Permissions.ANDROID.ACCESS_COARSE_LOCATION).then((result) => {
if(result[0] === PermissionResult.GRANTED) {
this.getCurrentLocation();
}
})
},
onFailure: ({statusCode}) => {
console.log("Location.checkSettings onFailure");
if (statusCode == Location.Android.SettingsStatusCodes.DENIED) {
console.log("SettingsStatusCodes.DENIED");
} else {
// go to settings via Application.call
console.log(
"SettingsStatusCodes.OTHER" +
Location.Android.SettingsStatusCodes.OTHER
);
}
},
});
if (System.OS === System.OSType.IOS) {
this.getCurrentLocation();
}
}
}
Stop Location Updates
Consider the stop location updates whether your location no longer in use or your page is does not appear on screen. This can be handy to reduce power consumption, provided the app doesn't need to collect information even when it's running in the background. This section shows how you can stop location updates in page onHide.
function onHide(superOnHide) {
superOnHide && superOnHide();
Location.stop();
}
Location Permissions in Android
There are multiple permissions related to location in Android.
- ACCESS_COARSE_LOCATION -> used for approximate location access
- ACCESS_FINE_LOCATION -> used for precise location access
To better respect user privacy, it's recommended that you only request ACCESS_COARSE_LOCATION. You can fulfill most use cases even when you have access to only approximate location information.
Approximate Location
You can use ACCESS_COARSE_LOCATION permisison for approximate location access.
Permission.android.requestPermissions(Permissions.ANDROID.ACCESS_COARSE_LOCATION).then((result) => {
if (result[0] === PermissionResult.GRANTED) {
// get location
}
});
Precise Location
You can use ACCESS_FINE_LOCATION permisison for precise location access. But on Android 12 or higher, user can grant only approximate location even if ACCESS_FINE_LOCATION is requested. For this behaviour we should request both of the permissions (ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION).
Permission.android.requestPermissions([Permissions.ANDROID.ACCESS_FINE_LOCATION, Permissions.ANDROID.ACCESS_COARSE_LOCATION]).then((result) => {
if (result[0] === PermissionResult.GRANTED && result[1] === PermissionResult.GRANTED) {
console.log("User granted ACCESS_FINE_LOCATION");
// get location
} else if (result[0] === PermissionResult.DENIED && result[1] === PermissionResult.GRANTED) {
console.log("User granted ACCESS_COARSE_LOCATION");
// get location
} else {
console.log("User denied location permission");
}
})
The user can grant precise or approximate permissions, or deny both of the permissions. If the user has given approximate location permission and precise location access is required, you can request an upgrade to precise location permission.
To request an upgrade to precise location permission, you should explain to user why this permission is required, and then request both of the permissions again.
type LocationPermissionStatus = "precise" | "approximate" | "denied";
requestLocationPermission(): Promise<LocationPermissionStatus> {
return Permission.android.requestPermissions([Permissions.ANDROID.ACCESS_FINE_LOCATION, Permissions.ANDROID.ACCESS_COARSE_LOCATION]).then((result) => {
if (result[0] === PermissionResult.GRANTED && result[1] === PermissionResult.GRANTED) {
return "precise";
} else if (result[0] === PermissionResult.DENIED && result[1] === PermissionResult.GRANTED) {
return "approximate";
}
return "denied";
})
}
async getLocation() {
const locationPermissionStatus = await this.requestLocationPermission();
if(locationPermissionStatus === "approximate") {
//display the UI that explains why precise location permission is needed
const upgradeLocationPermissionStatus = await this.requestLocationPermission();
if(upgradeLocationPermissionStatus === "precise") {
// get location
}
}
}
In order to prevent redundant power consumption, location architecture on Android has been optimized. Before running Location.start, Android permissions must be checked.
Some native features might require specific permissions and published app to work on Smartface due to Smartface Android Emulator itself not having necessary permissions.
List of permissions disabled by the emulator:
- android.permission.ACCESS_BACKGROUND_LOCATION
You can add this permission to your AndroidManifest.xml file to enable the feature on your published app.