4

Android Fusedlocationproviderclient not working with APN Sim (which means private internet, not all can access ) it's working with Wifi or ordinary internet (which means global mobile internet) and I also try Location manager (Play service does not enable those devices).

Activity class

    import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.Location;
//import android.location.LocationListener;
import android.location.LocationManager;

import android.location.LocationProvider;
import android.os.PowerManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationAvailability;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.tasks.OnCanceledListener;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.SuccessContinuation;
import com.google.android.gms.tasks.Task;


import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;

import java.util.Locale;

public class LocationActivity extends AppCompatActivity implements LocationListener {


    private FusedLocationProviderClient mFusedLocationClient;

    private double wayLatitude = 0.0, wayLongitude = 0.0;
    private LocationRequest locationRequest;
    private LocationCallback locationCallback;
    private Button btnLocation;
    private TextView txtLocation;
    private Button btnContinueLocation;
    private TextView txtContinueLocation;
    private StringBuilder stringBuilder;
    private boolean isContinue = false;
    private int LOCATION_REQUEST = 1000;

    GPSTracker gps;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_location);
        this.txtContinueLocation = (TextView) findViewById(R.id.txtContinueLocation);
        this.btnContinueLocation = (Button) findViewById(R.id.btnContinueLocation);
        this.txtLocation = (TextView) findViewById(R.id.txtLocation);
        this.btnLocation = (Button) findViewById(R.id.btnLocation);


        try {


            locationRequest = LocationRequest.create();
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            locationRequest.setInterval(10 * 1000); // 10 seconds
            locationRequest.setFastestInterval(5 * 1000); // 5 seconds
            locationCallback = new LocationCallback() {

                @Override
                public void onLocationAvailability(LocationAvailability locationAvailability) {
                    super.onLocationAvailability(locationAvailability);
                    try {
                        if (!locationAvailability.isLocationAvailable()) {
                        GoogleApiAvailability api = GoogleApiAvailability.getInstance();
                        Task<Void> task = api.makeGooglePlayServicesAvailable(LocationActivity.this);
                        task.addOnCompleteListener(LocationActivity.this, new OnCompleteListener<Void>() {
                            @Override
                            public void onComplete(@NonNull Task<Void> task) {
                              //  getLocation();
                              //  mFusedLocationClient.removeLocationUpdates(this);
                                gps = new GPSTracker(LocationActivity.this);

                                // Check if GPS enabled
                                if (gps.canGetLocation()) {

                                    wayLatitude = gps.getLatitude();
                                    wayLongitude = gps.getLongitude();

                                    // \n is for new line
                                    Toast.makeText(getApplicationContext(), "Your Location is - \nLat: " + wayLatitude + "\nLong: " + wayLongitude, Toast.LENGTH_LONG).show();
                                } else {
                                    Toast.makeText(getApplicationContext(), "No location", Toast.LENGTH_LONG).show();
                                }
                            }
                        });

                        task.addOnFailureListener(LocationActivity.this, new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                Toast.makeText(LocationActivity.this, "Playservice failure", Toast.LENGTH_LONG).show();
                            }
                        });
                    }
                               //init();


                   //     }
                    } catch (SecurityException e) {

                    }
                }

                @Override
                public void onLocationResult(LocationResult locationResult) {
                    if (locationResult == null) {
                        return;
                    }
                    for (Location location : locationResult.getLocations()) {
                        if (location != null) {
                            wayLatitude = location.getLatitude();
                            wayLongitude = location.getLongitude();
//                        if (!isContinue) {
//                            txtLocation.setText(String.format(Locale.US, "%s - %s", wayLatitude, wayLongitude));
//                        } else {
//                            stringBuilder.append(wayLatitude);
//                            stringBuilder.append("-");
//                            stringBuilder.append(wayLongitude);
//                            stringBuilder.append("\n\n");
//                            txtContinueLocation.setText(stringBuilder.toString());
                            Toast.makeText(LocationActivity.this, wayLatitude + " _ " + wayLongitude, Toast.LENGTH_LONG).show();
                            // }
//                        if (mFusedLocationClient != null) {
//                            mFusedLocationClient.removeLocationUpdates(locationCallback);
//                        }
                        }
                    }
                }

            };


            btnLocation.setOnClickListener(v -> {
                // checkGooglePlayServices();

                getLocation();
            });

            btnContinueLocation.setOnClickListener(v -> {
                //  checkGooglePlayServices();
//                PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
//                boolean isPowerSaveMode = pm.isPowerSaveMode();
//                Log.e("TAG", "Mode " + isPowerSaveMode);
//
                //  init();
                getLocation();
                //  _getLocation();
            });
            //   getLocation();
            mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
        } catch (Exception e) {
            Log.e("TAG", e.getMessage());
        }

    }

    private void getLocation() {
        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, new String[]{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION},
                    LOCATION_REQUEST);

        } else {
            getLatLang();

            // init();
        }
    }

    public void getLatLang() {
        try {

            mFusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, null);
            mFusedLocationClient.getLastLocation().addOnSuccessListener(this, new OnSuccessListener<Location>() {
                @Override
                public void onSuccess(Location location) {

                    if (location != null) {
                        wayLatitude = location.getLatitude();
                        wayLongitude = location.getLongitude();
                        Toast.makeText(LocationActivity.this, wayLatitude + " _ " + wayLongitude, Toast.LENGTH_LONG).show();
                    } else {
                        Toast.makeText(LocationActivity.this, "Location not get Fused client", Toast.LENGTH_LONG).show();
                    }
                }
            });
            mFusedLocationClient.getLastLocation().addOnFailureListener(this, new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    wayLatitude = 0.0;
                    wayLongitude = 0.0;
                    Toast.makeText(LocationActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();

                }
            });
            mFusedLocationClient.getLastLocation().addOnCanceledListener(this, new OnCanceledListener() {
                @Override
                public void onCanceled() {
                    Log.e("TAG", "loc cancel");
                }
            });
        } catch (Exception e) {
            Log.e("TAG", "loc exce" + e.getMessage());
        }
    }

    @SuppressLint("MissingPermission")
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case 1000: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    getLatLang();
                    //   init();
                } else {
                    Toast.makeText(this, "Permission denied", Toast.LENGTH_SHORT).show();
                }
                break;
            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK) {

        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //  mFusedLocationClient.removeLocationUpdates(locationCallback);
//        if(locMgr!=null)
//            locMgr.removeUpdates();
    }

    @Override
    public void onLocationChanged(Location location) {
        if (location != null) {
            wayLatitude = location.getLatitude();
            wayLongitude = location.getLongitude();
            Toast.makeText(LocationActivity.this, wayLatitude + " _ " + wayLongitude + "  CHANGE", Toast.LENGTH_LONG).show();
        } else {
            Toast.makeText(LocationActivity.this, "Location not get Fused client chnage locATION", Toast.LENGTH_LONG).show();
        }
    }
    }

HELPER - if the location does not gets then we try all three providers if anyone provider gives result then we skip the other providers.

public class GPSTracker extends Service implements LocationListener {
    private final Context mContext;
    // flag for GPS status
    boolean isGPSEnabled = false;

    boolean isPassive = false;
    // flag for network status
    boolean isNetworkEnabled = false;
    // flag for GPS status
    boolean canGetLocation = false;
    Location location; // location
    double latitude; // latitude
    double longitude; // longitude
    // The minimum distance to change Updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 1; // 10 meters
    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1000 * 1; // 1 minute
    // Declaring a Location Manager
    protected LocationManager locationManager;

    public GPSTracker(Context context) {
        this.mContext = context;
        getLocation();
    }

    @SuppressLint("MissingPermission")
    public Location getLocation() {
        try {
            locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);
            // getting GPS status
            isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            // getting network status
            isNetworkEnabled = locationManager
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);
            isPassive = locationManager
                    .isProviderEnabled(LocationManager.PASSIVE_PROVIDER);

            if (!isGPSEnabled && !isNetworkEnabled && !isPassive) {
                // no network provider is enabled
            } else {
                this.canGetLocation = true;
                // First get location from Network Provider

                if (isPassive) {
                    // if (location == null) {
                    locationManager.requestLocationUpdates(
                            LocationManager.PASSIVE_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    Toast.makeText(mContext, "Location Try Passive Provider", Toast.LENGTH_SHORT);
                    Log.e("Passive Enabled", "Passive Enabled");
                    if (locationManager != null) {
                        location = locationManager
                                .getLastKnownLocation(LocationManager.PASSIVE_PROVIDER);

                        if (location != null) {
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                        } else {
                            Toast.makeText(mContext, "Location Not get Passive Provider", Toast.LENGTH_SHORT);
                        }
                    }
                }
                // }.

                // if GPS Enabled get lat/long using GPS Services
                if (isGPSEnabled) {
                    if (location == null) {
                        locationManager.requestLocationUpdates(
                                LocationManager.GPS_PROVIDER,
                                MIN_TIME_BW_UPDATES,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        Toast.makeText(mContext, "Location Try GPS Provider", Toast.LENGTH_SHORT);
                        Log.e("GPS Enabled", "GPS Enabled");
                        if (locationManager != null) {
                            location = locationManager
                                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);

                            if (location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                                Log.e("TAG", "GPS " + latitude + " vjhg " + longitude);
                            } else {
                                Toast.makeText(mContext, "Location Not get GPS Provider", Toast.LENGTH_SHORT);
                            }
                        }
                    }
                }

                if (isNetworkEnabled) {
                    if (location == null) {
                        locationManager.requestLocationUpdates(
                                LocationManager.NETWORK_PROVIDER,
                                MIN_TIME_BW_UPDATES,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

                        Log.e("Network", "Network Enabled");
                        Toast.makeText(mContext, "Location Try Network Provider", Toast.LENGTH_SHORT);
                        if (locationManager != null) {
                            location = locationManager
                                    .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

                            if (location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                            } else {
                                Toast.makeText(mContext, "Location Not get Network Provider", Toast.LENGTH_SHORT);
                            }
                        }
                    }
                }


            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return location;
    }

    /**
     * Stop using GPS listener
     * Calling this function will stop using GPS in your app
     */
    public void stopUsingGPS() {
        if (locationManager != null) {
            locationManager.removeUpdates(GPSTracker.this);
        }
    }

    /**
     * Function to get latitude
     */
    public double getLatitude() {
        if (location != null) {
            latitude = location.getLatitude();
        }
        // return latitude
        return latitude;
    }

    /**
     * Function to get longitude
     */
    public double getLongitude() {
        if (location != null) {
            longitude = location.getLongitude();
        }
        // return longitude
        return longitude;
    }

    /**
     * Function to check GPS/wifi enabled
     *
     * @return boolean
     */
    public boolean canGetLocation() {
        return this.canGetLocation;
    }

    /**
     * Function to show settings alert dialog
     * On pressing Settings button will lauch Settings Options
     */
    public void showSettingsAlert() {
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
        // Setting Dialog Title
        alertDialog.setTitle("GPS is settings");
        // Setting Dialog Message
        alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");
        // On pressing Settings button
        alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                mContext.startActivity(intent);
            }
        });

        // on pressing cancel button
        alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });

        // Showing Alert Message
        alertDialog.show();
    }

    @Override
    public void onLocationChanged(Location location) {
        if (location != null) {
            latitude = location.getLatitude();
            longitude = location.getLongitude();
            Log.e("TAG", "Change " + latitude + " ``` " + longitude);
        }
    }

    @Override
    public void onProviderDisabled(String provider) {
    }

    @Override
    public void onProviderEnabled(String provider) {
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }
}

Manifest

<uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <!--    <uses-permission android:name="android.permission.ACCESS_" />-->
    <uses-feature
        android:name="android.hardware.location.gps"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.location.network"
        android:required="false" />

    <application
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:largeHeap="true"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:screenOrientation="portrait"
        android:supportsRtl="true">

This is my sample code. Once I connected my wifi its works but my point we want to work with APN sim.

RDY
  • 613
  • 1
  • 9
  • 25
  • 1
    You should define what you mean by "ordinary internet" if it is not wifi. You should also explain or link to what you mean by "APN Sim" as mobile network all have a Access Point Name that needs configuring. – Morrison Chang Jan 14 '20 at 14:00
  • added. please check it. – RDY Jan 14 '20 at 14:09
  • 1
    As `Fused Location Provider` is a **Google Play Services API**, does your private internet allow for communications with Google servers? – Morrison Chang Jan 14 '20 at 17:18
  • How can I check or provide (ex: any urls) – RDY Jan 16 '20 at 07:22
  • 1
    See: [What DNS and ports needs to be configured for a private network with restricted access to allow Firebase notifications and Android updates?](https://stackoverflow.com/q/44685860/295004) OR don't use Google Services in your app on a private network. – Morrison Chang Jan 16 '20 at 14:47
  • if I don't use Google Services in your app how can I get Lat & Long or how can I get Lat & Long without Internet(Offline) – RDY Jan 17 '20 at 09:48
  • GPS still works, its just slower to get a location and works best outdoors. AGPS (assisted GPS) requires a mobile connection to help GPS location. If you want location indoors you'll need an external service that uses [Hybrid Positioning](https://en.wikipedia.org/wiki/Hybrid_positioning_system) which uses Wi-Fi, Bluetooth, possibly cell towers? but would probably require connection to external service as location database is constantly updated (i.e. WiFi hotspots change) so same problem as accessing Google Services on private network. – Morrison Chang Jan 17 '20 at 19:24
  • 1
    You should update your question for what kind of answer you seek given the comment thread. Also details about why is the business using a APN Sim (private network) may be helpful. – Morrison Chang Jan 18 '20 at 18:21
  • APN Sim (a private network) used for only whitelisted URLs only can access. – RDY Jan 20 '20 at 07:16
  • GPS not working all the time. What is the google URLs I need to whitelist? – RDY Jan 20 '20 at 07:22
  • If my answer isn't adequate you should update your question with why so that others can provide an appropriate answer (if available). – Morrison Chang Jan 28 '20 at 04:47

1 Answers1

3

Answer: Google Location Services uses Google's hybrid location data to get a faster fix on a device's location.

From: Do network location provider need internet to determine location? and the Google IO 2019 video: Seamless and Smooth Location Everywhere with the new FusedLocationProvider which provides details on FusedLocationProvider.

GPS still works, its just slower to get a location and works best outdoors. AGPS (Assisted GPS) requires a mobile connection to help GPS location. If you want location indoors or in a urban environment you'll need an external service that uses Hybrid Positioning which uses Wi-Fi, Bluetooth, possibly cell towers? but would require at least some frequent connection to an external service as location database is constantly updated (i.e. WiFi hotspots change, new construction can change radio patterns) so same problem as accessing Google Services on private network.

What is the google URLs I need to whitelist [for Google Services]?

From: FCM ports and your firewall:

For outgoing connections, FCM doesn't provide specific IPs because our IP range changes too frequently and your firewall rules could get out of date impacting your users' experience. Ideally, you will whitelist ports 5228-5230 with no IP restrictions. However, if you must have an IP restriction, you should whitelist all of the IP addresses in the IPv4 and IPv6 blocks listed in Google's ASN of 15169. This is a large list and you should plan to update your rules monthly. Problems caused by firewall IP restrictions are often intermittent and difficult to diagnose.

Ports to open for incoming messages:

5228

5229

5230

Ports to allow outgoing connections:

One of these (option #1 is preferred):

  1. No IP restrictions
  2. All IP addresses contained in the IP blocks listed in Google's ASN of 15169. Don't forget to update this at least once a month.

While Google Services isn't Firebase Cloud Messaging its on the same constantly changing global infrastructure so a reasonable match without specific documentation stating otherwise.

Also given that Google Maps isn't Google Location Services see the Google Maps related resources in this question: Using google maps api behind firewall

Alternatives

Another alternative is not to use Google Services for your hybrid location provider. There are third party vendors like HERE which appears to have there own premium Advanced Positioning by HERE service. You would have to check what plan would be appropriate for your usage and contact them for what IP addresses/domains would need to be whitelisted if not covered by What IP-addresses do I need to allow the firewall to access geocoder.api.here.com?

There are probably other providers like Skyhook to investigate to see if they match your needs. I would see if the APN Sim provider has a service. Or if all of the devices are by a single manufacturer see if the manufacturer has a proprietary (non-Google) location service.

Can't do any of the above

If the business isn't able to allow the above options, then the app is limited to the slower to fix GPS when GPS is available. GPS is free, but getting faster time to location fix or improved urban/indoor location requires some third-party service to tell the device where it is.

Morrison Chang
  • 11,691
  • 3
  • 41
  • 77