I've played around with Android app development before but I am now developing my first serious app for Android. I've got a first version of my ready, that our customer wants to test.
The app uses the location of the device and sends the location, along with other data to a server. To be allowed to send data, the device must have obtained a location. I've implemented the necessary functions to ask for the user for access & permission for the device's location. (I am using google play services for the location)
My problem is the following: In the emulator and every device I've tested, this works fine. The user opens the app, the app asks for permissions/access and the user is able to work with the app. Now I've build an .apk file for the customer to test (using Android Studio > Build > Build APK). My boss drove to the customer and installed the .apk on the device they provided (A Samsung Galaxy S5 Neo running Android 5.1.1). On this device, my app is not able to obtain the device's location. The app doesn't even ask for permissions or access for the location.
I am wondering what causes this problem. Other apps on that device (e.g. Google Maps) are able to access the location just fine. But my app is not able to.
I deployed the app to my test devices via Android Studio. Could that be the problem? Do I need to configure additional options before my app can be installed via a .apk and access the location of a device?
I've also installed the app via an .apk to a Sony device. There the app was able to retrieve the device's location. I also used Android Studio to deploy my app to the device (via Run) and then uninstalled it, before installing it again via the .apk.
Is the problem device specific or do I need to consider something else before being able to install my app via an apk file and have it working?
Edit: Some of my code ...
Permissions:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
The code where I am checking the location settings:
private void checkLocationSettings(PendingResult<LocationSettingsResult> result) {
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
@Override
public void onResult(@NonNull LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
// final LocationSettingsStates locationSettingsStates = locationSettingsResult.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
status.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
// Ignore the error;
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
break;
}
}
});
}
The code where I check for the permissions:
protected void startLocationUpdates() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, this.permissions, REQUEST_LOCATION_ID);
return;
}
LocationServices.FusedLocationApi.requestLocationUpdates(this.googleApiClient, this.locationRequest, this);
}
Edit 2: I've now got the device. When I am installing/running the app from Android Studio on the device, it correctly asks for the location permissions/settings.
After receiving another batch of phones that did not work with the app, I have finally found the solution to my problem: When the google play services of a device are out of date, my "ask for permissions" code would not be reached. But the onConnectionFailed method of my main activity got called.
So I've added the following code to resolve errors during connecting to the play services api (thanks to https://stackoverflow.com/a/22651625/5396040):
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Log.i(TAG, "Connection failed: ConnectionResult.getCollectionStatus() = " + connectionResult.getErrorCode());
GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
int status = googleApiAvailability.isGooglePlayServicesAvailable(this);
if (status != ConnectionResult.SUCCESS) {
if (googleApiAvailability.isUserResolvableError(status)) {
googleApiAvailability.getErrorDialog(this, status,
REQUEST_CODE_RECOVER_PLAY_SERVICES).show();
} else {
Toast.makeText(this, "This device is not supported.",
Toast.LENGTH_LONG).show();
finish();
}
}
}
Now my app informs the user that the google play services are out of date and prompts the user to update them. After the play services have been updated my app correctly asks for the location settings and/or permissions.