Setting a mock location programmatically in FusedLocationProviderClient - android

I am trying to use mock locations in my app for testing. To receive location updates I used the latest android developer documentation here:
https://developer.android.com/training/location/receive-location-updates
This tutorial uses FusedLocationProviderClient and locationClient.requestLocationUpdates(createLocationRequest(), locationCallback, null) as example.
The issue is that I can no longer use permission:
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
because I get the error "Permission is only granted to system apps" (I tried also in debug mode)
So I tried the following code, but it doesn't work:
locationClient.setMockMode(true);
String[] tokens = location.split(",");
Location newLocation = new Location(LocationManager.GPS_PROVIDER);
newLocation.setLatitude(Float.parseFloat(tokens[0]));
newLocation.setLongitude(Float.parseFloat(tokens[1]));
newLocation.setAccuracy(3.0f);
newLocation.setTime(System.currentTimeMillis());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
newLocation.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
}
locationClient.setMockLocation(newLocation);
Does anyone have an idea how to solve this?

It seems that adding the
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
permission to debug android manifest works even though Android Studio says "Permission is only granted to system apps".
So the solution is that, after adding it, run the application, then go to Settings / Developer options / Select mock location app -> here my app appears and I can select it.
I hope others can confirm and use this!

Related

Android 10 not working with BLE Bluetooth scanning

I am working on BLE Bluetooth scanning is working on all devices except the Android 10. Android 10 is not working, anyone please answer the question for the version 10 issues for scanning BLE Bluetooth
To make BLE scanning work on Android apps targeting Android 10 you need to ask the user for
ACCESS_BACKGROUND_LOCATION
along with ACCESS_FINE_LOCATION and also don't forget to add the permission in the manifest:
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
Here's the explanation why:
Android 10 (API level 29) introduces a number of features and behavior changes to better protect users' privacy. These changes extend the transparency and control that users have over their data and the capabilities they give to apps.
Your problem in short:
Access to device location in the background requires permission
To support the additional control that users have over an app's access to location information, Android 10 introduces the ACCESS_BACKGROUND_LOCATION permission.
Unlike the ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions, the ACCESS_BACKGROUND_LOCATION permission only affects an app's access to location when it runs in the background. An app is considered to be accessing location in the background unless one of the following conditions is satisfied:
An activity belonging to the app is visible.
The app is running a foreground service that has declared a foreground service type of location.
To declare the foreground service type for a service in your app, set your app's targetSdkVersion or compileSdkVersion to 29 or higher. Learn more about how foreground services can continue user-initiated actions that require access to location.
Hope this fixes your problem :)
You need to have location enabled to perform a BLE scan on android 10.
To check if location is enabled and ask user to enable location service (Kotlin):
val lm = getSystemService(Context.LOCATION_SERVICE) as LocationManager
if (!LocationManagerCompat.isLocationEnabled(lm)) {
// Start Location Settings Activity, you should explain to the user why he need to enable location before.
startActivity(Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS))
}
LocationManagerCompat class is available in androidx.appcompat:appcompat:1.1.0 dependency, if you don't use androidx, you can use instead :
lm.isLocationEnabled()
Adding the following permissions to AndroidManifest.xml is not enough
android.permission.ACCESS_FINE_LOCATION,
android.permission.ACCESS_COARSE_LOCATION,
android.permission.ACCESS_BACKGROUND_LOCATION.
Add permissions to MainActivity such as
ActivityCompat.requestPermissions(
this,
new String[]
{
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION,
Manifest.permission.READ_EXTERNAL_STORAGE
}, 0);
I faced the same problem, and I have just fixed it using cordova-plugin-android-permissions.
Android 10 (SDK 29) requires ACCESS_FINE_LOCATION, while previous versions require only ACCESS_COARSE_LOCATION. (more info in this Android Developers page)
Unlike some other answers state, the ACCESS_BACKGROUD_LOCATION is not required. It's better not to require it unless you really need it. Play Store considers background location a dangerous permission, and will ask you to fill in some forms to justify why do you need it.
Old plugins would ask only ACCESS_COARSE_LOCATION permission, which was enough for Android 9 (SDK 28) and older versions. The best solution is to update the plugin. But if it is hard to do, there is an easy workaround.
Add cordova-plugin-android-permissions (npm link) to your project, and use it to ask ACCESS_FINE_LOCATION permission.
Add this code to your "device ready" function to check if your app already has this permission or not:
permissions = cordova.plugins.permissions;
permissions.checkPermission(permissions.ACCESS_FINE_LOCATION, checkPermissionSuccessCallback, checkPermissionErrorCallback);
And then create the following callback function to ask user permission:
function checkPermissionSuccessCallback(status) {
if (status.hasPermission) {
console.log("Permission OK");
} else {
console.log("Permission not OK");
// ask user permission
permissions.requestPermission(permissions.ACCESS_FINE_LOCATION, requestPermissionSuccessCallback, requestPermissionErrorCallback);
}
}
You don't need to add anything to your "config.xml" to get this permission.
try this
//gradle
dependencies {
implementation 'no.nordicsemi.android.support.v18:scanner:1.4.3'
}
//import
import no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerCompat;
import no.nordicsemi.android.support.v18.scanner.ScanCallback;
import no.nordicsemi.android.support.v18.scanner.ScanResult;
import no.nordicsemi.android.support.v18.scanner.ScanSettings;
//init scan setting
final ScanSettings settings = new ScanSettings.Builder().setReportDelay(1000).setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
//start scan
scanner.startScan(null, settings, scanCallback);
//scan callback
private final ScanCallback scanCallback = new ScanCallback() {
#Override
public void onScanResult(final int callbackType, #NonNull final ScanResult result) {
super.onScanResult(callbackType, result);
}
public void onBatchScanResults(#NonNull final List<ScanResult> results) {
for (final ScanResult result : results) {
//result.getDevice() is scanned device
}
}
#Override
public void onScanFailed(final int errorCode) {
// should never be called
}
};
For me it is working if i use fine permission in AndroidManifest. Switch on the location in Settings of the phone manually, and set app permission to location.
I suppose in android 10 having just the location permission is not enough. Your location service should be turned on while you are scanning for your device. So, ask the user for turning on the location service if it is turned off.
Alternative Solution:
You can use Companion device pairing for android 8 and higher. Mind you, In my opinion, it is not well documented, and it might be a bit unstable. For example, when I assigned a scan filter (BLE Service UUID) the Companion device pairing crashed, but without that filter, it worked.
Try setting the callbackType to CALLBACK_TYPE_ALL_MATCHES, it solves the problem for me.
val scanSettings = ScanSettings.Builder()
scanSettings.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
scanSettings.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
scanSettings.setMatchMode(ScanSettings.MATCH_MODE_AGGRESSIVE)
val filter = ScanFilter.Builder()
filter.setServiceUuid(ParcelUuid(Service_UUID))
bluetooth.bluetoothLeScanner.startScan(mutableListOf<ScanFilter>(filter.build()), scanSettings.build(), callback)
User need to allow "Location" - (GPS) on Device

Flutter - Android doesn't ask for permissions

I'm trying to get the current location of the device using the plugin location but Android never asks for permissions. I get this error:
Exception has occurred. PlatformException
(PlatformException(PERMISSION_DENIED_NEVER_ASK, Location permission
denied forever- please open app settings, null))
I have added the line below in every `AndroidManifest.xml´ file that I could find in the Android folder (no idea which one I should use actually, I found 3 of them)
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
I tried the plugin permission_handler to request them manually but still, no pop-up.
I'm completely lost and I find nothing similar on the net. Here is the code :
Future<LocationData> _getLocation() async {
LocationData currentLocation;
// returns a map with unreadable numbers which make no sense
var t = await PermissionHandler()
.requestPermissions([PermissionGroup.location]);
// returns false
var test = await location.requestPermission();
try {
currentLocation = await location.getLocation();
} catch (e) {
currentLocation = null;
}
return currentLocation;
}
Edit: I tried this on my device (OnePlus 6) and on an emulator (Pixel XL API 28). I've also tried to uninstall/reinstall the app.
After asking on the git of location plugin, I did this :
flutter clean
And I got the pop up asking for permissions.
Thank to this guy.
You can handle this kind of permission behavior in your code. Even if you never had installed your app on emulator this behavior can happen and you must handle this in your code because this can happen when your app are in final user hands.
This exception means that you're getting PermissionStatus.denied from checkPermissionStatus permission handler plugin method and this can happen when user hits Never ask again checkbox in android permission dialog and deny the request.
What is the most simple way to handle this?
If you get PermissionStatus.denied from checkPermissionStatus method you can show a dialog telling to the user that your app needs of that permission to provide a better experience and in this dialog you can redirect the user to Android permission settings where the user can enable the requested permission manually.
You can do this using openAppSettings() method from permission handler plugin.
Maybe you should read this article, it's a little bit old but it shows the correct flow about how to ask and handle user permissions in android. This article doesn't talks about the new permissions changes in newer Android Q.
The error message tries to make it clear: Your device (you or someone else on the device you are testing on) has selected Never when Android asked for the permission previously.
This means that Android will not ask for the permission again.
Just try it on a different device or uninstall the app again.
add this
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

Location permission doesn't switch on the service ionic cordova

In my Ionic 1 app I implemented Geolocation service by following
https://www.joshmorony.com/integrating-google-maps-with-an-ionic-application/ tutorial using cordova-plugin-geolocation
As the documentation says after the installing my AndroidManifest.xml file includes both of the following lines for the permission request
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
When I test the app on my mobile it asks for the permission. But when I Allow it, it doesn't switch on location service on my mobile. I have to manually switch on it. Why is that ? What is that I'm missing ?
EDIT : When I switch on the service manually I can see the map and I'm getting the exact location. But Allowing the permission request doesn't switch on the service on my phone
Asking for a permission does not necessarily imply that the feature/service will be enabled automatically. If the permission is granted, the application is able to use the protected features. Protected features may or may not be enabled.
You need to check to see if the location service is enabled, if not send the user to device's setting to enable the location service.
Here is an android example, you have to do something similar with your ionic app
How to prompt user to enable GPS_PROVIDER and/or NETWORK_PROVIDER?

Android Program request permissions

I am trying to use GPS in android but it gives me this error:
I put in manifest these permission
<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"/>
can anyone help me please
As the hint suggests : The user may deny permission. In that case this call will throw error...
Right now, android asks for the user to accept all the permissions an app asks for in the manifest on installation. In the upcoming M release, android will switch over to the iOS style of permissions with an "on needed" basis.
Call this method to see if permission is granted or not. If not, you need to handle that situation.
context.checkCallingPermission(permission)
Declaring permission in manifest only means that you are requesting permission. In new releases it will not guarantee that user will give you that permission.
In older releases the user has to accept all or reject all permissions
This is not an error actually but a heads-up by the Lint and which may cause an issue!
Hope you are aware about the new permission model is introduced in Android 6.0 (Marshmallow), through which user may not permit to use GPS or Network or anything else and so it may cause an issue in your application!
Now, as per the lint analysis, so before implementing particular functionality, you should check whether permission for the same is available or not!
Since SDK 23, you should/need to check the permission using checkSelfPermission
http://developer.android.com/reference/android/support/v4/content/ContextCompat.html
for example
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
This condition checks user allowed to access the permission to read the location
if(checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION)== PackageManager.PERMISSION_GRANTED||checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER,meter,mill,new locationlist(this));
}

Why doesn't this code work on android 6 marshmallow Api 23?

Why doesn't this code work on android 6 marshmallow Api 23? It does not throw an Exception but the code within callStateListener does not work.
TelephonyManager telephonyManager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
PhoneStateListener callStateListener = new PhoneStateListener() {
#Override
public void onCallStateChanged(int state, String incomingNumber) {
//if(logAtive) Log.i(LOG_TAG,incomingNumber + " " + state);
if(state==TelephonyManager.CALL_STATE_RINGING){
Toast.makeText(getApplicationContext(),"Hey, receive your call. Phone is ringing.",
Toast.LENGTH_LONG).show();
}
if(state==TelephonyManager.CALL_STATE_OFFHOOK){
Toast.makeText(getApplicationContext(),"You are in a call. ",
Toast.LENGTH_LONG).show();
}
if(state==TelephonyManager.CALL_STATE_IDLE){
Toast.makeText(getApplicationContext(),"You are in idle state… ",
Toast.LENGTH_LONG).show();
}
}
};
telephonyManager.listen(callStateListener, PhoneStateListener.LISTEN_CALL_STATE);
Permissions:
<uses-feature android:name="android.hardware.telephony" android:required="true" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.PROCESS_INCOMING_CALLS" />
It works perfectly in Android 5.1.1 but not in 6 (API Level 23)
I just ran into this and figured it out. It's because you are targeting android SDK 23. If you change your manifest file to target API 22 then it will start working even when installed and running on a Marshmallow device.
If you still want to target API 23 then you have to use the new runtime permission API to request permission usage first, otherwise it will simply be denied.
https://developer.android.com/training/permissions/requesting.html
You may not have any permissions to access the TelephonyManager (for example READ_PHONE_STATE).
According to the documentation, when you have not requested or have not been granted permission, but are still trying to access it, the result will be empty, rather than an exception like in the past:
If a user turns off permissions for a legacy app, the system silently disables the appropriate functionality. When the app attempts to perform an operation that requires that permission, the operation will not necessarily cause an exception. Instead, it might return an empty data set, signal an error, or otherwise exhibit unexpected behavior. For example, if you query a calendar without permission, the method returns an empty data set.
You need to ask the user to grant the appropriate permission, and handle cases when the user has already denied or has revoked that permission etc. There's a detailed description of how to employ this here.
I observed the very same behavior. Our app works perfectly well on Lollipop and down, but not on Marshmallow. It has nothing to do with permissions. Actually with the test app I wrote, I just went into Settings and gave the permissions beforehand. The problem in our app was with a phone number itself, that came from external source. If Android thinks it's not valid, you won't get onCallStateChanged called on Marshmallow. Just use a fake number 1234567890,,2# ("invalid") vs 1234567890 ("valid") to validate it. I don't know how to "fix" the number yet, as part of the numbers with extensions work.
Edit: bug report I've opened at 16 Dec. 15
Please, post your AndroidManifest, as well as check the following documeetation:
Note that access to some telephony information is permission-protected. Your application won't receive updates for protected information unless it has the appropriate permissions declared in its manifest file. Where permissions apply, they are noted in the appropriate LISTEN_ flags.
(Source:) incoming call phone number. If application does not have READ_PHONE_STATE permission, an empty string will be passed as an argument.

Categories

Resources