Summary of Android's acquisition of location information

I. Overview:

1.1 Android natively has a positioning API, but the stability and accuracy are far from enough, so it is usually necessary to obtain location information with the help of a third-party SDK

1.2 Domestic SDKs have many choices. Baidu, Tencent, AutoNavi and other positioning apis all need to build applications on the platform and configure keys, including basic positioning.

1.3 The google positioning api and google map are widely used in foreign countries. Google positioning is free, but the map needs a key, including the geocoding webapi interface.

1.4 Let’s not talk about domestic ones, there is basically no restriction, you can use any manufacturer’s SDK, we mainly talk about the solution that does not use domestic SDKs

2. Android native positioning

2.1 Positioning generally adopts network positioning or GPS positioning, and the difference between the two is relatively large

GPS positioning accuracy is high; but it can only be used outdoors, the speed of obtaining positioning information is slow, and consumes battery.
Network positioning can be used indoors and outdoors, with fast positioning speed and low power consumption; but the accuracy is not very high

2.2 Native Positioning Practice

public class AndroidLocationActivity extends Activity {
    private static final String TAG = "MainActivity";
    private Button btnLocation;
    private TextView tvResult;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_location);
        btnLocation = (Button) findViewById(R.id.btn_location);
        tvResult = (TextView) findViewById(R.id.tv_result);

        btnLocation.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                checkLocationServiceOpen();
            }
        });
    }

    //检查定位服务是否开启
    private void checkLocationServiceOpen() {
        if (isLocServiceEnable(this) && isLocServiceEnable(this, 1)) {
            initLocation();
        } else {
            Intent intent = new Intent();
            intent.setAction(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            startActivityForResult(intent, LOCATION_SERVICCE);
        }
    }


    /**
     * 手机是否开启位置服务,如果没有开启那么所有app将不能使用定位功能
     */
    private final static int LOCATION_SERVICCE = 1;// 定位
    private final int REQUEST_CHECK_SETTINGS = 2;//google权限设置

    public boolean isLocServiceEnable(Context context) {
        int locationMode = 0;
        String locationProviders;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            try {
                locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);
            } catch (Settings.SettingNotFoundException e) {
                e.printStackTrace();
                return false;
            }
            return locationMode != Settings.Secure.LOCATION_MODE_OFF;
        } else {
            locationProviders = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
            return !TextUtils.isEmpty(locationProviders);
        }
    }


    /**
     * 手机是否开启位置服务,如果没有开启那么所有app将不能使用定位功能
     */
    public boolean isLocServiceEnable(Context context, int type) {
        LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        boolean gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        boolean network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        if (gps || network) {
            return true;
        }
        return false;
    }


    public void initLocation() {
        AndPermission.with(this)
                .runtime()
                .permission(Permission.Group.LOCATION)
                .onGranted(new Action<List<String>>() {
                    @Override
                    public void onAction(List<String> permissions) {
                        Log.e(TAG, "onAction: " + "开始定位");
                        startLocation();
                    }
                })
                .onDenied(new Action<List<String>>() {
                    @Override
                    public void onAction(@NonNull List<String> permissions) {
                        Log.e(TAG, "onAction: " + "定位失败");
                        startLocation();
//                        // 判断用户是不是不再显示权限弹窗了,若不再显示的话进入权限设置页
//                        if (AndPermission.hasAlwaysDeniedPermission(mContext, permissions)) {
//                            // 打开权限设置页
//                            AndPermission.permissionSetting(mContext).start();
//                            return;
//                        }
                    }
                })
                .start();
    }


    private LocationManager locationManager;
    public void startLocation() {
        try {
            if (locationManager == null) {
                locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
            }
            Criteria criteria = new Criteria();
            criteria.setAltitudeRequired(true);
            String bestProvider = locationManager.getBestProvider(criteria, false);
            Log.e(TAG, "最佳的定位方式:" + bestProvider);
            //最佳定位方式LocationManager.GPS_PROVIDER LocationManager.NETWORK_PROVIDER
            locationManager.requestLocationUpdates(bestProvider, 0, 0, myLocationListener);
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }


    private LocationListener myLocationListener = new LocationListener() {
        @Override
        public void onLocationChanged(final Location location) {
            locationManager.removeUpdates(myLocationListener);
            setLocationResult(location);
        }

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

        @Override
        public void onProviderEnabled(String provider) {

        }

        @Override
        public void onProviderDisabled(String provider) {

        }
    };

    private void setLocationResult(Location location) {
        if (location == null) {
            tvResult.setText("定位失败");
            return;
        }
        long time = location.getTime();
        float accuracy = location.getAccuracy();//获取精确位置
        double altitude = location.getAltitude();//获取海拔
        double latitude = location.getLatitude();//获取纬度,平行
        double longitude = location.getLongitude();//获取经度,垂直
        StringBuffer sb = new StringBuffer();
        sb.append("time : ");
        sb.append(time);
        sb.append("\nlatitude : ");
        sb.append(latitude);
        sb.append("\nlontitude : ");
        sb.append(longitude);
        Log.e(TAG, "Android定位:\n"+sb.toString() + "\n\n");
        tvResult.setText("Android定位:\n"+sb.toString() + "\n\n");
        geocoderAddress(location);

    }

    //获取地址信息:城市、街道等信息
    public void geocoderAddress(Location location) {
        try {
            if (location != null) {
                Geocoder gc = new Geocoder(this, Locale.getDefault());
                List<Address> result = gc.getFromLocation(location.getLatitude(),
                        location.getLongitude(), 1);
                Log.e(TAG, "获取地址信息:" + result.toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


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


        if (requestCode == LOCATION_SERVICCE) {//开启定位服务
            if (isLocServiceEnable(this) && isLocServiceEnable(this, 1)) {
                checkLocationServiceOpen();
            }
        } else if (requestCode == REQUEST_CHECK_SETTINGS) {
            switch (resultCode) {
                case Activity.RESULT_OK:
                    // All required changes were successfully made
                    Log.e("locationSettingCallback", "RESULT_OK");
                    startLocation();
                    break;
                case Activity.RESULT_CANCELED:
                    Log.e("locationSettingCallback", "RESULT_CANCELED");
                    // The user was asked to change settings, but chose not to
//                    googleLocationStar();
//                    checkLocationPermission();
                    break;
                default:
                    break;
            }
        }
    }
}

Notice:

Use of Geocoder

1. Geocoder This class is used to obtain the forward encoding and reverse encoding of the geographic location. The forward encoding is to obtain the latitude and longitude according to the address; the reverse encoding is to obtain the corresponding detailed address according to the latitude and longitude

2. Geocoder requests a background service, but this service is not included in the standard android framework, so if the current device does not contain location services, the address or latitude and longitude returned by Geocoder is empty. Most mobile phones may not be usable, and those that do not support will flash back, and handle exceptions well

Listening settings
After the setting is successful, you need to cancel the monitoring, otherwise the location will not be updated after downloading and relocating.
locationManager.removeUpdates(myLocationListener);

Three google positioning practice

3.1 There are relatively large restrictions on using Google

  • First of all, mobile phones must support Google services, but domestic mobile phones are basically not equipped with Google services by default due to the serious customization of various manufacturers.
  • The mobile network needs a VPN, otherwise you can't use foreign services

3.2 Ways to work around limitations

Install the google three-piece set, google service framework, store and google account management program, the method can be searched by yourself. At the same time, install the flipping tool, and search for this by yourself

3.2 Examples

Module-level build.gradle adds location dependencies

implementation 'com.google.android.gms:play-services-location:18.0.0'

Add permission to manifest file

   <!-- 位置信息 -->
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />

 java source code

public class GoogleLocationActivity extends Activity {
    private static final String TAG = "MainActivity";
    private Button btnLocation;
    private TextView tvResult;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_location);
        btnLocation = (Button) findViewById(R.id.btn_location);
        tvResult = (TextView) findViewById(R.id.tv_result);

        btnLocation.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                checkLocationServiceOpen();
            }
        });
    }

    //检查定位服务是否开启
    private void checkLocationServiceOpen() {
        if (isLocServiceEnable(this) && isLocServiceEnable(this, 1)) {
            initLocation();
        } else {
            Intent intent = new Intent();
            intent.setAction(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            startActivityForResult(intent, LOCATION_SERVICCE);
        }
    }


    /**
     * 手机是否开启位置服务,如果没有开启那么所有app将不能使用定位功能
     */
    private final static int LOCATION_SERVICCE = 1;// 定位
    private final int REQUEST_CHECK_SETTINGS = 2;//google权限设置

    public boolean isLocServiceEnable(Context context) {
        int locationMode = 0;
        String locationProviders;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            try {
                locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);
            } catch (Settings.SettingNotFoundException e) {
                e.printStackTrace();
                return false;
            }
            return locationMode != Settings.Secure.LOCATION_MODE_OFF;
        } else {
            locationProviders = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
            return !TextUtils.isEmpty(locationProviders);
        }
    }


    /**
     * 手机是否开启位置服务,如果没有开启那么所有app将不能使用定位功能
     */
    public boolean isLocServiceEnable(Context context, int type) {
        LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        boolean gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        boolean network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        if (gps || network) {
            return true;
        }
        return false;
    }


    public void initLocation() {

        AndPermission.with(this)
                .runtime()
                .permission(Permission.Group.LOCATION)
                .onGranted(new Action<List<String>>() {
                    @Override
                    public void onAction(List<String> permissions) {
                        Log.e(TAG, "onAction: " + "开始定位");
                        initGooglePlayService();
                    }
                })
                .onDenied(new Action<List<String>>() {
                    @Override
                    public void onAction(@NonNull List<String> permissions) {
                        Log.e(TAG, "onAction: " + "定位失败");
                        initGooglePlayService();
//                        // 判断用户是不是不再显示权限弹窗了,若不再显示的话进入权限设置页
//                        if (AndPermission.hasAlwaysDeniedPermission(mContext, permissions)) {
//                            // 打开权限设置页
//                            AndPermission.permissionSetting(mContext).start();
//                            return;
//                        }
                    }
                })
                .start();
    }

    //连接google服务
    private void initGooglePlayService() {
        GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(new GoogleApiClient.ConnectionCallbacks() {
                    @Override
                    public void onConnected(@Nullable Bundle bundle) {
                        Log.e(TAG, "onConnected");
                        initGoogleLocation();
                    }

                    @Override
                    public void onConnectionSuspended(int i) {
                        Log.e(TAG, "onConnectionSuspended" + "---i");
                        //startBaiduLocation();
                    }
                })
                .addOnConnectionFailedListener(new GoogleApiClient.OnConnectionFailedListener() {
                    @Override
                    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
                        Log.e(TAG, "onConnectionFailed---" + connectionResult.getErrorCode() + "---" + connectionResult.getErrorMessage());
                        //startBaiduLocation();
                    }
                })
                .build();
        mGoogleApiClient.connect();
    }



    private LocationRequest locationRequest;

    private void initGoogleLocation() {
        try {
            locationRequest = LocationRequest.create();
//            locationRequest.setInterval(20000);
//            locationRequest.setFastestInterval(10000);
//            locationRequest.setNumUpdates(1);
//            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                    .addLocationRequest(locationRequest);
            SettingsClient client = LocationServices.getSettingsClient(this);
            Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());
            task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
                @Override
                public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
                    Log.e(TAG, "onSuccess");
                    startLocation();

                }
            });

            task.addOnFailureListener(this, new OnFailureListener() {
                @Override
                public void onFailure(@NonNull Exception e) {
                    Log.e(TAG, "onFailure");
                    if (e instanceof ResolvableApiException) {
                        // Location settings are not satisfied, but this can be fixed
                        // by showing the user a dialog.
                        try {
                            // Show the dialog by calling startResolutionForResult(),
                            // and check the result in onActivityResult().
                            ResolvableApiException resolvable = (ResolvableApiException) e;
                            resolvable.startResolutionForResult(GoogleLocationActivity.this,
                                    REQUEST_CHECK_SETTINGS);
                        } catch (IntentSender.SendIntentException sendEx) {
                            // Ignore the error.
                        }
                    }
                }
            });
        } catch (Exception e) {

        }
    }


    private Location lastKnownLocation;
    private FusedLocationProviderClient locationProviderClient;

    private void startLocation() {
        // Construct a FusedLocationProviderClient.
        if (locationProviderClient == null) {
            locationProviderClient = LocationServices.getFusedLocationProviderClient(this);
        }

        /*
         * Get the best and most recent location of the device, which may be null in rare
         * cases when a location is not available.
         */
        try {
            Task<Location> locationResult = locationProviderClient.getLastLocation();
            locationResult.addOnCompleteListener(this, new OnCompleteListener<Location>() {
                @Override
                public void onComplete(Task<Location> task) {
                    if (task.isSuccessful()) {
                        // Set the map's camera position to the current location of the device.
                        lastKnownLocation = task.getResult();
                        if(lastKnownLocation!=null){
                            updateLocation();
                        }else {
                            startNewLocation();
                        }

                    } else {
                        Log.d(TAG, "Current location is null. Using defaults.");
                        Log.e(TAG, "Exception: %s", task.getException());
                    }
                }
            });
        } catch (SecurityException e) {
            Log.e(TAG, e.getMessage());
        }
    }


    //开始google定位

    private void startNewLocation() {

        if (locationProviderClient == null) {
            locationProviderClient = LocationServices.getFusedLocationProviderClient(this);
        }

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }

        Log.e(TAG, "startGoogleLocation11: " + "开始Google定位");
        locationProviderClient.requestLocationUpdates(locationRequest,
                locationCallback,
                Looper.getMainLooper())
                .addOnSuccessListener(new OnSuccessListener<Void>() {
            @Override
            public void onSuccess(Void unused) {
                Log.e(TAG, "onSuccess: ");
            }
        });
    }

    //定期接受位置信息
    LocationCallback locationCallback = new LocationCallback() {
        @Override
        public void onLocationResult(LocationResult locationResult) {
            locationProviderClient.removeLocationUpdates(locationCallback);
            lastKnownLocation=locationResult.getLastLocation();
            updateLocation();
        }

        @Override
        public void onLocationAvailability(@NonNull LocationAvailability locationAvailability) {
            super.onLocationAvailability(locationAvailability);
            Log.e(TAG, "数量3:"+locationAvailability.isLocationAvailable());
        }
    };

    private void updateLocation(){
        if (lastKnownLocation != null) {
            StringBuffer sb = new StringBuffer();
            sb.append("time : ");
            sb.append(lastKnownLocation.getTime());
            sb.append("\nlatitude : ");
            sb.append(lastKnownLocation.getLatitude());
            sb.append("\nlontitude : ");
            sb.append(lastKnownLocation.getLongitude());
            Log.e(TAG, "google定位:\n"+sb.toString() + "\n\n");
            tvResult.setText("google定位:\n"+sb.toString() + "\n\n");
        }
    }

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


        if (requestCode == LOCATION_SERVICCE) {//开启定位服务
            if (isLocServiceEnable(this) && isLocServiceEnable(this, 1)) {
                checkLocationServiceOpen();
            }
        } else if (requestCode == REQUEST_CHECK_SETTINGS) {
            switch (resultCode) {
                case Activity.RESULT_OK:
                    // All required changes were successfully made
                    Log.e("locationSettingCallback", "RESULT_OK");
                    startLocation();
                    break;
                case Activity.RESULT_CANCELED:
                    Log.e("locationSettingCallback", "RESULT_CANCELED");
                    // The user was asked to change settings, but chose not to
//                    googleLocationStar();
//                    checkLocationPermission();
                    break;
                default:
                    break;
            }
        }
    }
}

3.3 Note:

In the process, you can first adjust the native Android -> then adjust the last location of Google -> update the location without the last location to ensure that the location information can be obtained.

3.4 Be sure to request the location permission first, otherwise it will report no permission

 3.5 The positioning accuracy can be removed, and if you try to add it, the indoor loading will always fail

locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

Four summary

Any one in China can be used, and the original one can be shared with Google abroad. After all, Google has many restrictions. If the positioning requirements are not high, you can use the original one. If you have high requirements, you can only use Google positioning.

Guess you like

Origin blog.csdn.net/qq_29848853/article/details/129636031