Làm cách nào để có được vị trí GPS hiện tại theo chương trình trong Android?


716

Tôi cần có được vị trí hiện tại của mình bằng cách sử dụng GPS theo chương trình. Làm thế nào tôi có thể đạt được nó?

Câu trả lời:


432

Tôi đã tạo một ứng dụng nhỏ với mô tả từng bước để có tọa độ GPS của vị trí hiện tại.

Mã nguồn ví dụ hoàn chỉnh nằm trong tọa độ Vị trí hiện tại, Tên thành phố - trong Android .


Xem làm thế nào nó hoạt động:

  • Tất cả những gì chúng ta cần làm là thêm quyền này vào tệp kê khai:

    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
  • Và tạo một cá thể LocationManager như thế này:

    LocationManager locationManager = (LocationManager)
    getSystemService(Context.LOCATION_SERVICE);
  • Kiểm tra xem GPS có được bật hay không.

  • Và sau đó triển khai LocationListener và nhận tọa độ:

    LocationListener locationListener = new MyLocationListener();
    locationManager.requestLocationUpdates(
    LocationManager.GPS_PROVIDER, 5000, 10, locationListener);
  • Đây là mã mẫu để làm như vậy


/*---------- Listener class to get coordinates ------------- */
private class MyLocationListener implements LocationListener {

    @Override
    public void onLocationChanged(Location loc) {
        editLocation.setText("");
        pb.setVisibility(View.INVISIBLE);
        Toast.makeText(
                getBaseContext(),
                "Location changed: Lat: " + loc.getLatitude() + " Lng: "
                    + loc.getLongitude(), Toast.LENGTH_SHORT).show();
        String longitude = "Longitude: " + loc.getLongitude();
        Log.v(TAG, longitude);
        String latitude = "Latitude: " + loc.getLatitude();
        Log.v(TAG, latitude);

        /*------- To get city name from coordinates -------- */
        String cityName = null;
        Geocoder gcd = new Geocoder(getBaseContext(), Locale.getDefault());
        List<Address> addresses;
        try {
            addresses = gcd.getFromLocation(loc.getLatitude(),
                    loc.getLongitude(), 1);
            if (addresses.size() > 0) {
                System.out.println(addresses.get(0).getLocality());
                cityName = addresses.get(0).getLocality();
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        String s = longitude + "\n" + latitude + "\n\nMy Current City is: "
            + cityName;
        editLocation.setText(s);
    }

    @Override
    public void onProviderDisabled(String provider) {}

    @Override
    public void onProviderEnabled(String provider) {}

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


36
Điều này có nghĩa là bạn phải di chuyển trước khi có cập nhật vị trí? Tại sao nó không hiển thị vị trí hiện tại của bạn trong lần thử đầu tiên sau khi cài đặt?
Nii Laryea

15
@NiiLaryea vì tôi nhận được Địa điểm bằng cách sử dụng phương thức " onLocationChanged () " cung cấp cho mỗi lần vị trí mới trong khi bạn di chuyển, nhưng nếu bạn muốn chỉ một lần, bạn cần gọi " getLastKnownLocation () "
swiftBoy

Nếu chỉ có một địa chỉ trong adressesdòng bắt đầu bằng cityName =sẽ không có ngoại lệ. Sử dụng niềng răng sẽ sửa chữa nó.
Carrotman42

2
Tôi đã nghe người ta nói getLastKnownLocation()là một địa điểm "cũ" hơn - tại sao lại thế này? Có phải cuộc gọi getLastKnownLocation()không nhận được GPS mới nhất của điện thoại GPS?
Don Cheadle

9
@mmcrae Không, không. GPS không phải lúc nào cũng chạy. getLastKnownLocation không bật nó lên. Nó có được vị trí cuối cùng từ lần cuối cùng. mũ có thể thực sự tươi, một giờ tuổi, hoặc thậm chí vô giá trị.
Gabe Sechan

139

Dưới đây là thông tin bổ sung cho các câu trả lời khác.

Vì Android có

GPS_PROVIDER and NETWORK_PROVIDER

bạn có thể đăng ký cả hai và bắt đầu tìm nạp các sự kiện onLocationChanged(Location location)từ hai người cùng một lúc. Càng xa càng tốt. Bây giờ câu hỏi chúng ta cần hai kết quả hay chúng ta nên làm tốt nhất. Theo tôi biết GPS_PROVIDERkết quả có độ chính xác tốt hơn NETWORK_PROVIDER.

Hãy xác định Locationtrường:

private Location currentBestLocation = null;

Trước khi chúng tôi bắt đầu lắng nghe về thay đổi vị trí, chúng tôi sẽ thực hiện phương pháp sau. Phương pháp này trả về vị trí đã biết cuối cùng, giữa GPS và mạng. Đối với phương pháp này mới hơn là tốt nhất.

/**
 * @return the last know best location
 */
private Location getLastBestLocation() {
    Location locationGPS = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
    Location locationNet = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

    long GPSLocationTime = 0;
    if (null != locationGPS) { GPSLocationTime = locationGPS.getTime(); }

    long NetLocationTime = 0;

    if (null != locationNet) {
        NetLocationTime = locationNet.getTime();
    }

    if ( 0 < GPSLocationTime - NetLocationTime ) {
        return locationGPS;
    }
    else {
        return locationNet;
    }
}

Mỗi lần chúng tôi lấy lại một vị trí mới, chúng tôi sẽ so sánh nó với kết quả trước đó của chúng tôi.

...
static final int TWO_MINUTES = 1000 * 60 * 2;
...

Tôi thêm một phương thức mới vào onLocationChanged:

@Override
public void onLocationChanged(Location location) {

    makeUseOfNewLocation(location);

    if(currentBestLocation == null){
        currentBestLocation = location;
    }

    ....
}


/**
 * This method modify the last know good location according to the arguments.
 *
 * @param location The possible new location.
 */
void makeUseOfNewLocation(Location location) {
    if ( isBetterLocation(location, currentBestLocation) ) {
        currentBestLocation = location;
    }
}

....

/** Determines whether one location reading is better than the current location fix
 * @param location  The new location that you want to evaluate
 * @param currentBestLocation  The current location fix, to which you want to compare the new one.
 */
protected boolean isBetterLocation(Location location, Location currentBestLocation) {
    if (currentBestLocation == null) {
        // A new location is always better than no location
        return true;
    }

    // Check whether the new location fix is newer or older
    long timeDelta = location.getTime() - currentBestLocation.getTime();
    boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
    boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
    boolean isNewer = timeDelta > 0;

    // If it's been more than two minutes since the current location, use the new location,
    // because the user has likely moved.
    if (isSignificantlyNewer) {
        return true;
        // If the new location is more than two minutes older, it must be worse.
    } else if (isSignificantlyOlder) {
        return false;
    }

    // Check whether the new location fix is more or less accurate
    int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
    boolean isLessAccurate = accuracyDelta > 0;
    boolean isMoreAccurate = accuracyDelta < 0;
    boolean isSignificantlyLessAccurate = accuracyDelta > 200;

    // Check if the old and new location are from the same provider
    boolean isFromSameProvider = isSameProvider(location.getProvider(),
                                                currentBestLocation.getProvider());

    // Determine location quality using a combination of timeliness and accuracy
    if (isMoreAccurate) {
        return true;
    } else if (isNewer && !isLessAccurate) {
        return true;
    } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
        return true;
    }
    return false;
}

// Checks whether two providers are the same
private boolean isSameProvider(String provider1, String provider2) {
    if (provider1 == null) {
        return provider2 == null;
    }
    return provider1.equals(provider2);
}

....

Xin chào, đó là một ví dụ hay..nhưng bạn có thể vui lòng cho tôi một ví dụ đầy đủ hơn không? Tôi gặp khó khăn khi tích hợp nó vào mã hiện tại của tôi. Ngoài ra, tôi chỉ sử dụng GPS là nhà cung cấp.
bia

1
@quantumstates Tôi nghĩ nó khá hoàn chỉnh. Chỉ cần tạo trường private Location currentBestLocation = null;và thêm phương thức `makeUseOfNewLocation (location);` vào onLocationChanged (..)
Maxim Shoustin

Cảm ơn Maxim. Tôi có một câu hỏi. Bạn sử dụng phương thức 'getLastBestLocation' ở đâu?
SeyedPooya Soofbaf

@SeyyedPuyaSoustbaf Nói chung, vị trí mới chúng tôi nhận được sau khoảng 30 giây. Nếu chúng tôi đăng ký cho cả hai Người quản lý, chúng tôi có thể ngay lập tức nhận được 2 địa điểm được biết đến cuối cùng và quyết định phù thủy là địa điểm mới hơn.
Maxim Shoustin

Tôi không nhận ra rằng sự khác biệt giữa getLastBestLocation và isBetterLocation là gì? Hai phương pháp này đã được sử dụng để so sánh hai địa điểm.
SeyedPooya Soofbaf

84

Bạn có thể tìm vị trí bằng cách GPS_PROVIDER or NETWORK_PROVIDER.

Tổng quan về dịch vụ định vị trong Android.

Đây là một ví dụ cố gắng tìm vị trí bằng GPS. Nếu GPS của bạn không khả dụng thì hãy thử sử dụng mạng để tìm vị trí.

GPSTracker.java

 public class GPSTracker extends Service implements LocationListener {

    private final Context mContext;

    // Flag for GPS status
    boolean isGPSEnabled = 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 = 10; // 10 meters

    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute

    // Declaring a Location Manager
    protected LocationManager locationManager;

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

    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);

            if (!isGPSEnabled && !isNetworkEnabled) {
                // No network provider is enabled
            } else {
                this.canGetLocation = true;
                if (isNetworkEnabled) {
                    locationManager.requestLocationUpdates(
                            LocationManager.NETWORK_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    Log.d("Network", "Network");
                    if (locationManager != null) {
                        location = locationManager
                                .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        if (location != null) {
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                        }
                    }
                }
                // If GPS enabled, get latitude/longitude using GPS Services
                if (isGPSEnabled) {
                    if (location == null) {
                        locationManager.requestLocationUpdates(
                                LocationManager.GPS_PROVIDER,
                                MIN_TIME_BW_UPDATES,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        Log.d("GPS Enabled", "GPS Enabled");
                        if (locationManager != null) {
                            location = locationManager
                                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            if (location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                            }
                        }
                    }
                }
            }
        }
        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/Wi-Fi enabled
     * @return boolean
     * */
    public boolean canGetLocation() {
        return this.canGetLocation;
    }


    /**
     * Function to show settings alert dialog.
     * On pressing the Settings button it will launch 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 the 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 the 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) {
    }


    @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;
    }
}

Hoạt động -AndroidGPSTrackingActivity.java

    public class AndroidGPSTrackingActivity extends Activity {

    Button btnShowLocation;

    // GPSTracker class
    GPSTracker gps;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btnShowLocation = (Button) findViewById(R.id.btnShowLocation);

        // Show location button click event
        btnShowLocation.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View arg0) {
                // Create class object
                gps = new GPSTracker(AndroidGPSTrackingActivity.this);

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

                    double latitude = gps.getLatitude();
                    double longitude = gps.getLongitude();

                    // \n is for new line
                    Toast.makeText(getApplicationContext(), "Your Location is - \nLat: " + latitude + "\nLong: " + longitude, Toast.LENGTH_LONG).show();
                } else {
                    // Can't get location.
                    // GPS or network is not enabled.
                    // Ask user to enable GPS/network in settings.
                    gps.showSettingsAlert();
                }
            }
        });
    }
}

Bố cục- tệp chính

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <Button android:id="@+id/btnShowLocation"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Show Location"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"/>
</RelativeLayout>

AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />

4
Tôi nghĩ rằng có một vấn đề với ví dụ này, bạn dường như không bao giờ sử dụng trình nghe vị trí. Nó luôn luôn sử dụng GetLastKnownLocation () có thể không phải là mới nhất
Madhur Ahuja

16
Phải downvote cho đánh giá cao. Mã của họ ở đây là tốt, nhưng nó được sử dụng bởi rất nhiều người không hiểu nó và nó có một số sai sót trong việc sử dụng getLastKnownLocation - chúng tôi nhận được rất nhiều câu hỏi từ những người sử dụng nó và nhận được các vị trí cũ, không biết họ đã cũ. Ngoài ra, giá trị canGetLocation là sai, bạn đặt giá trị đó dựa trên việc nhà cung cấp có được bật hay không nhưng không kiểm tra xem getLastKnownLocation có trả về giá trị thực hay không - bạn chỉ cho rằng nó sẽ như vậy. Tôi nghĩ rằng điều này có thể được thực hiện tốt, nhưng tôi sẽ không đề nghị bất cứ ai sử dụng nó như vậy.
Gabe Sechan

1
Quyền ACCESS_FINE_LOCATION là đủ theo tài liệu Android: Nếu bạn đang sử dụng cả NETWORK_PROVIDER và GPS_PROVIDER, thì bạn chỉ cần yêu cầu quyền ACCESS_FINE_LOCATION, vì nó bao gồm quyền cho cả hai nhà cung cấp. (Quyền cho ACCESS_COARSE_LOCATION chỉ bao gồm quyền cho NETWORK_PROVIDER.)
Anh. Samer T

Tôi đã thử mã này và đưa ra vị trí không chính xác.
misha312

Đây không phải là phiên bản chính xác của mã mà nó không cung cấp vị trí chính xác
Moeez 17/2/2017

45

Đã có nhiều câu trả lời ở đó nhưng tôi muốn chỉ ra cách mới nhất để có được vị trí bằng Google API, vì vậy các lập trình viên mới có thể sử dụng phương pháp mới:

Tôi đã viết hướng dẫn chi tiết về vị trí hiện tại trong Android tại blog của tôi demuts.com Bạn cũng có thể tìm thấy mã nguồn đầy đủ được phát triển với studio android.

Trước hết, đặt nó trong tập tin gradle

 compile 'com.google.android.gms:play-services:9.0.2'

sau đó thực hiện các giao diện cần thiết

public class MainActivity  extends BaseActivitiy implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, com.google.android.gms.location.LocationListener

khai báo

  private GoogleApiClient mGoogleApiClient;
  private Location mLocation;
  private LocationManager locationManager;
  private LocationRequest mLocationRequest;

đặt cái này vào onCreate()

 mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

Cuối cùng, ghi đè các phương thức cần thiết

 @Override
    public void onConnected(Bundle bundle) {
        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;
        } startLocationUpdates();
        mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        if(mLocation == null){
            startLocationUpdates();
        }
        if (mLocation != null) {
            double latitude = mLocation.getLatitude();
            double longitude = mLocation.getLongitude();
        } else {
            // Toast.makeText(this, "Location not Detected", Toast.LENGTH_SHORT).show();
        }
    }

    protected void startLocationUpdates() {
        // Create the location request
        mLocationRequest = LocationRequest.create()
                .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
                .setInterval(UPDATE_INTERVAL)
                .setFastestInterval(FASTEST_INTERVAL);
        // Request location updates
        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;
        }
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient,
                mLocationRequest, this);
        Log.d("reque", "--->>>>");
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.i(TAG, "Connection Suspended");
        mGoogleApiClient.connect();
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.i(TAG, "Connection failed. Error: " + connectionResult.getErrorCode());
    }

    @Override
    public void onStart() {
        super.onStart();
        mGoogleApiClient.connect();
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mGoogleApiClient.isConnected()) {
            mGoogleApiClient.disconnect();
        }
    }
    @Override
    public void onLocationChanged(Location location) {

    }

Đừng quên khởi động GPS trong thiết bị của bạn trước khi chạy ứng dụng.


Tôi đã sử dụng phương pháp của bạn để hiển thị tọa độ nhưng tôi không thể thấy tọa độ, bạn có thể vui lòng xem xét câu hỏi của tôi không?
Moeez

1
mLocationluôn luôn cho null. Tôi đã thử giống như đã đề cập
dharanbro

Truy cập liên kết này: demuts.com/2016/12/30/get-civerse-gps-location-android-studio và tải mã nguồn từ đó và kiểm tra xem mã nguồn có hoạt động trong máy tính của bạn hay không
Parsania Hardik

5
Đây phải là câu trả lời được chấp nhận. Và để gọn nhẹ, bạn có thể sử dụng compile 'com.google.android.gms:play-services-location:11.0.4'thay vì thêm tất cả các dịch vụ google play vào ứng dụng của mình.
Morris Franken

37

Vì tôi không thích một số mã trong các câu trả lời khác, đây là giải pháp đơn giản của tôi. Giải pháp này có nghĩa là có thể sử dụng được trong Hoạt động hoặc Dịch vụ để theo dõi vị trí. Nó đảm bảo rằng nó không bao giờ trả lại dữ liệu quá cũ trừ khi bạn yêu cầu rõ ràng dữ liệu cũ. Nó có thể được chạy trong chế độ gọi lại để nhận các bản cập nhật khi chúng tôi nhận được chúng, hoặc trong chế độ thăm dò ý kiến ​​để thăm dò thông tin gần đây nhất.

Giao diện LocationTracker chung. Cho phép chúng tôi có nhiều loại trình theo dõi vị trí và dễ dàng cắm loại phù hợp:

package com.gabesechan.android.reusable.location;

import android.location.Location;

public interface LocationTracker {
    public interface LocationUpdateListener{
        public void onUpdate(Location oldLoc, long oldTime, Location newLoc, long newTime);
    }

    public void start();
    public void start(LocationUpdateListener update);

    public void stop();

    public boolean hasLocation();

    public boolean hasPossiblyStaleLocation();

    public Location getLocation();

    public Location getPossiblyStaleLocation();

}

Nhà cung cấpLocationTracker- lớp này sẽ theo dõi vị trí cho GPS hoặc NETWORK.

package com.gabesechan.android.reusable.location;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

public class ProviderLocationTracker implements LocationListener, LocationTracker {

    // The minimum distance to change Updates in meters
    private static final long MIN_UPDATE_DISTANCE = 10; 

    // The minimum time between updates in milliseconds
    private static final long MIN_UPDATE_TIME = 1000 * 60; 

    private LocationManager lm;

    public enum ProviderType{
        NETWORK,
        GPS
    };    
    private String provider;

    private Location lastLocation;
    private long lastTime;

    private boolean isRunning;

    private LocationUpdateListener listener;

    public ProviderLocationTracker(Context context, ProviderType type) {
        lm = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
        if(type == ProviderType.NETWORK){
            provider = LocationManager.NETWORK_PROVIDER;
        }
        else{
            provider = LocationManager.GPS_PROVIDER;
        }
    }

    public void start(){
        if(isRunning){
            //Already running, do nothing
            return;
        }

        //The provider is on, so start getting updates.  Update current location
        isRunning = true;
        lm.requestLocationUpdates(provider, MIN_UPDATE_TIME, MIN_UPDATE_DISTANCE, this);
        lastLocation = null;
        lastTime = 0;
        return;
    }

    public void start(LocationUpdateListener update) {
        start();
        listener = update;

    }


    public void stop(){
        if(isRunning){
            lm.removeUpdates(this);
            isRunning = false;
            listener = null;
        }
    }

    public boolean hasLocation(){
        if(lastLocation == null){
            return false;
        }
        if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
            return false; //stale
        }
        return true;
    }

    public boolean hasPossiblyStaleLocation(){
        if(lastLocation != null){
            return true;
        }
        return lm.getLastKnownLocation(provider)!= null;
    }

    public Location getLocation(){
        if(lastLocation == null){
            return null;
        }
        if(System.currentTimeMillis() - lastTime > 5 * MIN_UPDATE_TIME){
            return null; //stale
        }
        return lastLocation;
    }

    public Location getPossiblyStaleLocation(){
        if(lastLocation != null){
            return lastLocation;
        }
        return lm.getLastKnownLocation(provider);
    }

    public void onLocationChanged(Location newLoc) {
        long now = System.currentTimeMillis();
        if(listener != null){
            listener.onUpdate(lastLocation, lastTime, newLoc, now);
        }
        lastLocation = newLoc;
        lastTime = now;
    }

    public void onProviderDisabled(String arg0) {

    }

    public void onProviderEnabled(String arg0) {

    }

    public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
    }
}

Đó là FallbackLocationTracker, sẽ theo dõi bằng cả GPS và NETWORK, và sử dụng bất kỳ vị trí nào chính xác hơn.

package com.gabesechan.android.reusable.location;

import android.content.Context;
import android.location.Location;
import android.location.LocationManager;

public class FallbackLocationTracker  implements LocationTracker, LocationTracker.LocationUpdateListener {


    private boolean isRunning;

    private ProviderLocationTracker gps;
    private ProviderLocationTracker net;

    private LocationUpdateListener listener;

    Location lastLoc;
    long lastTime;

    public FallbackLocationTracker(Context context) {
        gps = new ProviderLocationTracker(context, ProviderLocationTracker.ProviderType.GPS);
        net = new ProviderLocationTracker(context, ProviderLocationTracker.ProviderType.NETWORK);
    }

    public void start(){
        if(isRunning){
            //Already running, do nothing
            return;
        }

        //Start both
        gps.start(this);
        net.start(this);
        isRunning = true;
    }

    public void start(LocationUpdateListener update) {
        start();
        listener = update;
    }


    public void stop(){
        if(isRunning){
            gps.stop();
            net.stop();
            isRunning = false;
            listener = null;
        }
    }

    public boolean hasLocation(){
        //If either has a location, use it
        return gps.hasLocation() || net.hasLocation();
    }

    public boolean hasPossiblyStaleLocation(){
        //If either has a location, use it
        return gps.hasPossiblyStaleLocation() || net.hasPossiblyStaleLocation();
    }

    public Location getLocation(){
        Location ret = gps.getLocation();
        if(ret == null){
            ret = net.getLocation();
        }
        return ret;
    }

    public Location getPossiblyStaleLocation(){
        Location ret = gps.getPossiblyStaleLocation();
        if(ret == null){
            ret = net.getPossiblyStaleLocation();
        }
        return ret;
    }

    public void onUpdate(Location oldLoc, long oldTime, Location newLoc, long newTime) {
        boolean update = false;

        //We should update only if there is no last location, the provider is the same, or the provider is more accurate, or the old location is stale
        if(lastLoc == null){
            update = true;
        }
        else if(lastLoc != null && lastLoc.getProvider().equals(newLoc.getProvider())){
            update = true;
        }
        else if(newLoc.getProvider().equals(LocationManager.GPS_PROVIDER)){
            update = true;
        }
        else if (newTime - lastTime > 5 * 60 * 1000){
            update = true;
        }

        if(update){
            if(listener != null){
                listener.onUpdate(lastLoc, lastTime, newLoc, newTime);                  
            }
            lastLoc = newLoc;
            lastTime = newTime;
        }

    }
}

Vì cả hai đều thực hiện giao diện LocationTracker, bạn có thể dễ dàng thay đổi suy nghĩ về việc nên sử dụng giao diện nào. Để chạy lớp trong chế độ thăm dò ý kiến, chỉ cần gọi start (). Để chạy nó trong chế độ cập nhật, hãy gọi bắt đầu (Listener).

Ngoài ra hãy xem bài viết trên blog của tôi về mã


Đối với bất kỳ ai tò mò - lý do tôi không sử dụng thời gian được tích hợp vào đối tượng Vị trí là vì API không tồn tại cho đến API 17. Vì tôi muốn giữ khả năng tương thích với 14, tôi chỉ sử dụng thời gian hiện tại. Đó cũng là lý do tại sao tôi không gọi getLastKnownLocation sớm - bởi vì chúng ta không thể có thời gian từ đó và xem nó có cũ không.
Gabe Sechan

Mã của bạn là giải pháp tốt nhất và đầy đủ nhất tôi đã tìm thấy trong hai ngày tìm kiếm về chủ đề này. Nó hoạt động mà không có bất kỳ lỗi nào và giống như một sự quyến rũ, ấn tượng của nó. Chỉ có một điều, tôi đã thay đổi FallbackLocationTracker (Ngữ cảnh, loại Nhà cung cấp), thành FallbackLocationTracker (Ngữ cảnh ngữ cảnh) vì chúng tôi không cần gửi nhà cung cấp đến lớp này, tôi có tính đến cả GPS và Mạng không?
zeeshan

@zeeshan Bạn đã đúng, và tôi đã cập nhật mã ở đây. Tôi sẽ làm điều đó trên blog của mình vào lần tới khi tôi tìm thấy một chút thời gian (rất khó để có được tài nguyên cho tôi những ngày này). Như bạn có thể đoán, tôi đã tạo ra dự phòng bằng cách sao chép dán từ lớp khác và không bao giờ thực hiện việc dọn dẹp đó.
Gabe Sechan

12
giải pháp tốt nhất..nhưng chỉ thiếu một điều ... Một người mới bắt đầu không thể thực hiện nó..cũng nên là một ví dụ sử dụng trong đó ..
Zaffar Saffee

1
xin chào @GabeSechan Tôi đã triển khai phương pháp của bạn, nhưng mỗi khi tôi bật GPS trong cài đặt trên thiết bị Android của mình và bật Mạng, nó luôn trả về null trên phương thức getLocation. FallbackLocationTracker fallbackLocationTracker = new FallbackLocationTracker(mContext); fallbackLocationTracker.start(); if (fallbackLocationTracker.hasLocation()) { return fallbackLocationTracker.getLocation(); }
neteot

18

Nhận vị trí của gps bằng cách -

LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

LocationListener locationListener = new LocationListener() 
{

            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onProviderEnabled(String provider) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onProviderDisabled(String provider) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onLocationChanged(Location location) {
                // TODO Auto-generated method stub
                double latitude = location.getLatitude();
                double longitude = location.getLongitude();
                double speed = location.getSpeed(); //spedd in meter/minute
                speed = (speed*3600)/1000;      // speed in km/minute               Toast.makeText(GraphViews.this, "Current speed:" + location.getSpeed(),Toast.LENGTH_SHORT).show();
            }
        };

        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);

}

2
Mục tiêu luôn là mã ít chính xác hơn và không lạm dụng kiểm tra vị trí đơn giản như rất nhiều câu trả lời khác. Cảm ơn bạn đã thực sự trả lời câu hỏi đã được hỏi.
SmulianJulian

Cách nhận vị trí cứ sau 1 giây
Ruchir Baronia

Cảm ơn cách đơn giản để có GPS, nó hoạt động! Một con bọ rùa: location.getSpeed()trả về tốc độ tính bằng mét / giây (không phải mét / phút).
Spectorsky

16

Bạn cần sử dụng mới nhất / mới nhất

GoogleApiClient Api

Về cơ bản những gì bạn cần làm là:

private GoogleApiClient mGoogleApiClient;
mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

Sau đó

@Override
    public void onConnected(Bundle connectionHint) {
        mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
                mGoogleApiClient);
        if (mLastLocation != null) {
            mLatitudeText.setText(String.valueOf(mLastLocation.getLatitude()));
            mLongitudeText.setText(String.valueOf(mLastLocation.getLongitude()));
        }
    }

cho vị trí chính xác và đáng tin cậy nhất. Xem bài viết của tôi ở đây:

https://stackoverflow.com/a/33599228/2644905

Không sử dụng LocationListener không chính xác và có phản hồi chậm. Thành thật mà nói điều này là dễ thực hiện hơn. Đồng thời đọc tài liệu: https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient


1
Đây là câu trả lời tốt nhất cho API mới nhất.
kịch

1
Đúng. Đây là cách đúng đắn để làm điều đó, những ngày này. @nickfox cung cấp một số liên kết tốt trong câu trả lời thứ hai của anh ấy cho câu hỏi này , từ những người tạo ban đầu của API Dịch vụ vị trí, rất đáng để kiểm tra.
gMale

11
class MyLocation {
    Timer timer1;
    LocationManager lm;
    LocationResult locationResult;
    boolean gps_enabled = false;
    boolean network_enabled = false;

    public boolean getLocation(Context context, LocationResult result) {
        // I use LocationResult callback class to pass location value from
        // MyLocation to user code.
        locationResult = result;
        if (lm == null)
            lm = (LocationManager) context
                    .getSystemService(Context.LOCATION_SERVICE);

        // Exceptions will be thrown if the provider is not permitted.
        try {
            gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER);
        }
        catch (Exception ex) {
        }
        try {
            network_enabled = lm
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        }
        catch (Exception ex) {
        }

        // Don't start listeners if no provider is enabled.
        if (!gps_enabled && !network_enabled)
            return false;

        if (gps_enabled)
            lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0,
                    locationListenerGps);
        if (network_enabled)
            lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0,
                    locationListenerNetwork);
        timer1 = new Timer();
        timer1.schedule(new GetLastLocation(), 5000);
        return true;
    }

    LocationListener locationListenerGps = new LocationListener() {
        public void onLocationChanged(Location location) {
            timer1.cancel();
            locationResult.gotLocation(location);
            lm.removeUpdates(this);
            lm.removeUpdates(locationListenerNetwork);
        }

        public void onProviderDisabled(String provider) {
        }

        public void onProviderEnabled(String provider) {
        }

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

    LocationListener locationListenerNetwork = new LocationListener() {
        public void onLocationChanged(Location location) {
            timer1.cancel();
            locationResult.gotLocation(location);
            lm.removeUpdates(this);
            lm.removeUpdates(locationListenerGps);
        }

        public void onProviderDisabled(String provider) {
        }

        public void onProviderEnabled(String provider) {
        }

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

    class GetLastLocation extends TimerTask {
        @Override
        public void run() {
            lm.removeUpdates(locationListenerGps);
            lm.removeUpdates(locationListenerNetwork);

            Location net_loc = null, gps_loc = null;
            if (gps_enabled)
                gps_loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            if (network_enabled)
                net_loc = lm
                        .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

            // If there are both values, use the latest one.
            if (gps_loc != null && net_loc != null) {
                if (gps_loc.getTime() > net_loc.getTime())
                    locationResult.gotLocation(gps_loc);
                else
                    locationResult.gotLocation(net_loc);
                return;
            }

            if (gps_loc != null) {
                locationResult.gotLocation(gps_loc);
                return;
            }
            if (net_loc != null) {
                locationResult.gotLocation(net_loc);
                return;
            }
            locationResult.gotLocation(null);
        }
    }

    public static abstract class LocationResult {
        public abstract void gotLocation(Location location);
    }
}

Tôi hy vọng điều này sẽ giúp bạn...


1
Đừng quên thêm dòng sau vào tệp AndroidManifest của bạn:<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Dr. Failov

7

Bây giờ các dịch vụ vị trí của Google Play đã ở đây, tôi khuyên các nhà phát triển nên bắt đầu sử dụng nhà cung cấp vị trí hợp nhất mới. Bạn sẽ thấy nó dễ sử dụng hơn và chính xác hơn. Vui lòng xem video Google I / O Beyond the Blue Dot: Các tính năng mới trong Vị trí Android của hai người đã tạo API dịch vụ vị trí Google Play mới.

Tôi đã làm việc với các API vị trí trên một số nền tảng di động và tôi nghĩ những gì hai người này đã làm là thực sự mang tính cách mạng. Nó đã thoát khỏi một lượng lớn sự phức tạp của việc sử dụng các nhà cung cấp khác nhau. Stack Overflow tràn ngập các câu hỏi về việc nên sử dụng nhà cung cấp nào, có nên sử dụng vị trí đã biết cuối cùng hay không, cách đặt các thuộc tính khác trên Trình quản lý vị trí, v.v. sử dụng.

Tôi đã viết một ứng dụng Android định kỳ lấy vị trí bằng các dịch vụ định vị của Google Play và gửi vị trí đó đến máy chủ web nơi nó được lưu trữ trong cơ sở dữ liệu và có thể được xem trên Google Maps . Tôi đã viết cả phần mềm máy khách (cho Android, iOS, Windows Phone và Java ME ) và phần mềm máy chủ (cho ASP.NET và SQL Server hoặc PHPMySQL ). Phần mềm được viết bằng ngôn ngữ bản địa trên mỗi nền tảng và hoạt động chính xác trong nền trên mỗi nền tảng. Cuối cùng, phần mềm có Giấy phép MIT . Bạn có thể tìm thấy ứng dụng khách Android tại đây:

https://github.com/nickfox/GpsTracker/tree/master/phoneClrons/android


7

Đơn giản nhất bạn có thể tìm thấy

   package com.javapapers.android.geolocationfinder;

    import android.os.Bundle;
    import android.app.Activity;
    import android.content.Context;
    import android.location.Location;
    import android.location.LocationListener;
    import android.location.LocationManager;
    import android.widget.TextView;

    import android.util.Log;

    public class MainActivity extends Activity implements LocationListener{
    protected LocationManager locationManager;
    protected LocationListener locationListener;
    protected Context context;
    TextView txtLat;
    String lat;
    String provider;
    protected String latitude,longitude; 
    protected boolean gps_enabled,network_enabled;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    txtLat = (TextView) findViewById(R.id.textview1);

    locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
    }
    @Override
    public void onLocationChanged(Location location) {
    txtLat = (TextView) findViewById(R.id.textview1);
    txtLat.setText("Latitude:" + location.getLatitude() + ", Longitude:" + location.getLongitude());
    }

    @Override
    public void onProviderDisabled(String provider) {
    Log.d("Latitude","disable");
    }

    @Override
    public void onProviderEnabled(String provider) {
    Log.d("Latitude","enable");
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    Log.d("Latitude","status");
    }
    }

6

LocationManager là lớp cung cấp các phương thức xây dựng để có được vị trí biết cuối cùng

BƯỚC 1: Tạo Đối tượng LocationManager như bên dưới

LocationManager locationManager = (LocationManager) bối cảnh.getSystemService (Context.LOCATION_SERVICE);

BƯỚC 2: Thêm tiêu chí

*Criteria is use for setting accuracy*

Criteria criteria = new Criteria();
int currentapiVersion = android.os.Build.VERSION.SDK_INT;

if (currentapiVersion >= android.os.Build.VERSION_CODES.HONEYCOMB) {

    criteria.setSpeedAccuracy(Criteria.ACCURACY_HIGH);
    criteria.setAccuracy(Criteria.ACCURACY_FINE);
    criteria.setAltitudeRequired(true);
    criteria.setBearingRequired(true);
    criteria.setSpeedRequired(true);

}

BƯỚC 3: NHẬN Nhà cung cấp sẵn có

Threre là hai loại nhà cung cấp GPS và mạng

 String provider = locationManager.getBestProvider(criteria, true);

BƯỚC 4: Nhận vị trí cuối cùng

Location location = locationManager.getLastKnownLocation(provider);

BƯỚC 5: Nhận Vĩ độ và Kinh độ

Nếu đối tượng vị trí là null thì đừng cố gọi bên dưới phương thức s

getLatitude and getLongitude is methods which returns double values


6

Nhận cập nhật vị trí yêu cầu rất nhiều mã bolierplate trong Android, Bạn cần phải chăm sóc

  • Dịch vụ Google Play có sẵn Kiểm tra,
  • Cập nhật Dịch vụ Google play nếu nó cũ hoặc không khả dụng
  • Tạo hộp thoại Tạo GoogleApiClient và các cuộc gọi lại được kết nối, ngắt kết nối, v.v.
  • Dừng và phát hành tài nguyên để cập nhật vị trí
  • Xử lý các tình huống cho phép Địa điểm
  • Kiểm tra dịch vụ vị trí đang bật hoặc tắt
  • Nhận được vị trí cuối cùng cũng không dễ dàng
  • Dự phòng vị trí đã biết cuối cùng nếu không nhận được vị trí sau thời gian nhất định

Để giảm bớt tất cả các bước này, tôi đã tạo Android-EasyLocation (thư viện Android nhỏ) sẽ chăm sóc tất cả những thứ này và bạn có thể tập trung vào logic kinh doanh.

Tất cả bạn cần là mở rộng EasyLocationActivity và điều này

requestSingleLocationFix(easyLocationRequest);

hoặc là

requestLocationUpdates(easyLocationRequest);

Thanh toán ứng dụng mẫu và các bước cần thiết tại đây tại https://github.com/akhgupta/Android- EasyLocation


5

Tôi đã thực hiện một dự án từ đó chúng tôi có thể có được vị trí chính xác bằng cách sử dụng các nhà cung cấp Dịch vụ, GPS và Mạng của Google Play. Dự án này có thể được tìm thấy ở đây .

Chiến lược tìm vị trí tốt nhất là trước tiên hãy lấy vị trí từ dịch vụ google play nếu tìm thấy vị trí sau đó kiểm tra thời tiết có tốt hơn hay không, nếu vị trí được tìm thấy là null khởi động lại dịch vụ google play và thử tìm nạp vị trí từ API vị trí Android. Đăng ký vị trí trên người nghe thay đổi và khi tìm thấy vị trí tốt hơn, cuộc gọi trở lại trả lại cho hoạt động chính.

Nó rất đơn giản để sử dụng và thực hiện trong mã chỉ có hai lớp học chúng ta cần phải nhúng tức LocationManagerInterfaceSmartLocationManager, LocationActivityđang triển khai giao diện và sử dụng SmartLocationManager để lấy địa điểm.

/**
 * Created by Syed Raza Mehdi Naqvi on 8/10/2016.
 */
public interface LocationManagerInterface {
    String TAG = LocationManagerInterface.class.getSimpleName();

    void locationFetched(Location mLocation, Location oldLocation, String time, String locationProvider);

}

đây là lớp quản lý vị trí

import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;

import java.text.DateFormat;
import java.util.Date;

/**
 * Created by Syed Raza Mehdi Naqvi on 8/9/2016.
 */
public class SmartLocationManager implements
        GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

    private static final String TAG = SmartLocationManager.class.getSimpleName();

    private static final int TWO_MINUTES = 1000 * 60 * 2;
    private static final int PERMISSION_REQUEST_CODE = 1000;
    private static final int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;

    // default value is false but user can change it
    private String mLastLocationUpdateTime;                                                         // fetched location time
    private String locationProvider;                                                                // source of fetched location

    private Location mLastLocationFetched;                                                          // location fetched
    private Location mLocationFetched;                                                              // location fetched
    private Location networkLocation;
    private Location gpsLocation;

    private int mLocationPiority;
    private long mLocationFetchInterval;
    private long mFastestLocationFetchInterval;

    private Context mContext;                                                                       // application context
    private Activity mActivity;                                                                     // activity context
    private LocationRequest mLocationRequest;
    private GoogleApiClient mGoogleApiClient;
    private LocationManagerInterface mLocationManagerInterface;

    private android.location.LocationManager locationManager;
    private android.location.LocationListener locationListener;

    boolean isGPSEnabled;
    boolean isNetworkEnabled;

    private int mProviderType;
    public static final int NETWORK_PROVIDER = 1;
    public static final int ALL_PROVIDERS = 0;
    public static final int GPS_PROVIDER = 2;

//    private final double STANDARD_LOCATION_ACCURACY = 100.0;
//    private final double STANDARD_LOCATION_SEED_LIMIT = 6.95;

    public static final int LOCATION_PROVIDER_ALL_RESTICTION = 1;
    public static final int LOCATION_PROVIDER_RESTRICTION_NONE = 0;
    public static final int LOCATION_PROVIDER_GPS_ONLY_RESTICTION = 2;
    public static final int LOCATION_PROVIDER_NETWORK_ONLY_RESTICTION = 3;
    private int mForceNetworkProviders = 0;

    public SmartLocationManager(Context context, Activity activity, LocationManagerInterface locationInterface, int providerType, int locationPiority, long locationFetchInterval, long fastestLocationFetchInterval, int forceNetworkProviders) {
        mContext = context;
        mActivity = activity;
        mProviderType = providerType;

        mLocationPiority = locationPiority;
        mForceNetworkProviders = forceNetworkProviders;
        mLocationFetchInterval = locationFetchInterval;
        mFastestLocationFetchInterval = fastestLocationFetchInterval;

        mLocationManagerInterface = locationInterface;

        initSmartLocationManager();
    }


    public void initSmartLocationManager() {

        // 1) ask for permission for Android 6 above to avoid crash
        // 2) check if gps is available
        // 3) get location using awesome strategy

        askLocationPermission();                            // for android version 6 above
        checkNetworkProviderEnable(mForceNetworkProviders);                       //

        if (isGooglePlayServicesAvailable())                // if googleplay services available
            initLocationObjts();                            // init obj for google play service and start fetching location
        else
            getLocationUsingAndroidAPI();                   // otherwise get location using Android API
    }

    private void initLocationObjts() {
        // Create the LocationRequest object
        mLocationRequest = LocationRequest.create()
                .setPriority(mLocationPiority)
                .setInterval(mLocationFetchInterval)                    // 10 seconds, in milliseconds
                .setFastestInterval(mFastestLocationFetchInterval);     // 1 second, in milliseconds

        if (mGoogleApiClient == null) {
            mGoogleApiClient = new GoogleApiClient.Builder(mActivity)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .addApi(LocationServices.API)
                    .build();
        }

        startLocationFetching();                                        // connect google play services to fetch location
    }

    @Override
    public void onConnected(Bundle connectionHint) {
        Location location = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        startLocationUpdates();
        if (location == null) {
            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
            getLocationUsingAndroidAPI();
        } else {
            setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
        }
    }

    @Override
    public void onLocationChanged(Location location) {
        if (location == null) {
            getLastKnownLocation();
        } else {
            setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.i(TAG, "Connection suspended");
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        if (connectionResult.hasResolution()) {
            try {
                connectionResult.startResolutionForResult(mActivity, CONNECTION_FAILURE_RESOLUTION_REQUEST); // Start an Activity that tries to resolve the error
                getLocationUsingAndroidAPI();                                                                // try to get location using Android API locationManager
            } catch (IntentSender.SendIntentException e) {
                e.printStackTrace();
            }
        } else {
            Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode());
        }
    }

    private void setNewLocation(Location location, Location oldLocation) {
        if (location != null) {
            mLastLocationFetched = oldLocation;
            mLocationFetched = location;
            mLastLocationUpdateTime = DateFormat.getTimeInstance().format(new Date());
            locationProvider = location.getProvider();
            mLocationManagerInterface.locationFetched(location, mLastLocationFetched, mLastLocationUpdateTime, location.getProvider());
        }
    }

    private void getLocationUsingAndroidAPI() {
        // Acquire a reference to the system Location Manager
        locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);

        setLocationListner();
        captureLocation();
    }

    public void captureLocation() {
        if (Build.VERSION.SDK_INT >= 23 &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        try {
            if (mProviderType == SmartLocationManager.GPS_PROVIDER) {
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
            } else if (mProviderType == SmartLocationManager.NETWORK_PROVIDER) {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
            } else {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
            }
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
    }

    private void setLocationListner() {
        // Define a listener that responds to location updates
        locationListener = new android.location.LocationListener() {
            public void onLocationChanged(Location location) {
                // Called when a new location is found by the network location provider.
                if (location == null) {
                    getLastKnownLocation();
                } else {
                    setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
//                    if (isLocationAccurate(location) && location.getAccuracy() < STANDARD_LOCATION_ACCURACY && location.getSpeed() < STANDARD_LOCATION_SEED_LIMIT) {// no use of this if
//                        setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
//                    } else {
//                        setNewLocation(getBetterLocation(location, mLocationFetched), mLocationFetched);
//                    }
                }
            }

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

            public void onProviderEnabled(String provider) {
            }

            public void onProviderDisabled(String provider) {
            }
        };
    }

    public Location getAccurateLocation() {
        if (Build.VERSION.SDK_INT >= 23 &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return null;
        }
        try {
            gpsLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            networkLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            Location newLocalGPS, newLocalNetwork;
            if (gpsLocation != null || networkLocation != null) {
                newLocalGPS = getBetterLocation(mLocationFetched, gpsLocation);
                newLocalNetwork = getBetterLocation(mLocationFetched, networkLocation);
                setNewLocation(getBetterLocation(newLocalGPS, newLocalNetwork), mLocationFetched);
            }
        } catch (Exception ex) {
            Log.e(TAG, ex.getMessage());
        }
        return mLocationFetched;
    }

    protected void startLocationUpdates() {
        LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
    }

    public void startLocationFetching() {
        mGoogleApiClient.connect();
        if (mGoogleApiClient.isConnected()) {
            startLocationUpdates();
        }
    }

    public void pauseLocationFetching() {
        if (mGoogleApiClient.isConnected()) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
            mGoogleApiClient.disconnect();
        }

    }

    public void abortLocationFetching() {
        mGoogleApiClient.disconnect();

        // Remove the listener you previously added
        if (locationManager != null && locationListener != null) {
            if (Build.VERSION.SDK_INT >= 23 &&
                    ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                    ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
            try {
                locationManager.removeUpdates(locationListener);
                locationManager = null;
            } catch (Exception ex) {
                Log.e(TAG, ex.getMessage());

            }
        }
    }

    public void resetLocation() {
        mLocationFetched = null;
        mLastLocationFetched = null;
        networkLocation = null;
        gpsLocation = null;
    }

    //  Android M Permission check
    public void askLocationPermission() {

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {


            if (ContextCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    || ContextCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                    ) {
                if (ActivityCompat.shouldShowRequestPermissionRationale(mActivity, Manifest.permission.ACCESS_COARSE_LOCATION)
                        || ActivityCompat.shouldShowRequestPermissionRationale(mActivity, Manifest.permission.ACCESS_FINE_LOCATION)) {

                    final AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
                    builder.setMessage("Please allow all permissions in App Settings for additional functionality.")
                            .setCancelable(false)
                            .setPositiveButton("Allow", new DialogInterface.OnClickListener() {
                                public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                                    Toast.makeText(mContext, "Welcome", Toast.LENGTH_SHORT).show();
                                }
                            })
                            .setNegativeButton("Deny", new DialogInterface.OnClickListener() {
                                public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                                    mActivity.finish();
                                }
                            });
                    final AlertDialog alert = builder.create();
                    alert.show();

                } else
                    ActivityCompat.requestPermissions(mActivity, new String[]{Manifest.permission.ACCESS_COARSE_LOCATION
                            , Manifest.permission.ACCESS_FINE_LOCATION
                    }, PERMISSION_REQUEST_CODE);

            }
        }
    }

    public void checkNetworkProviderEnable(int enforceActive) {
        locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);

        isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        if (!isGPSEnabled && !isNetworkEnabled) {
            buildAlertMessageTurnOnLocationProviders("Your location providers seems to be disabled, please enable it", "OK", "Cancel");
        } else if (!isGPSEnabled && mForceNetworkProviders == LOCATION_PROVIDER_GPS_ONLY_RESTICTION) {
            buildAlertMessageTurnOnLocationProviders("Your GPS seems to be disabled, please enable it", "OK", "Cancel");
        } else if (!isNetworkEnabled && mForceNetworkProviders == LOCATION_PROVIDER_NETWORK_ONLY_RESTICTION) {
            buildAlertMessageTurnOnLocationProviders("Your Network location provider seems to be disabled, please enable it", "OK", "Cancel");
        }
        // getting network status

        if (!isGPSEnabled && !isNetworkEnabled) {
            Toast.makeText(mContext, "Location can't be fetched!", Toast.LENGTH_SHORT).show(); // show alert
            mActivity.finish();
        }
    }

    private void buildAlertMessageTurnOnLocationProviders(String message, String positiveButtonText, String negativeButtonText) {
        final AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
        builder.setMessage(message)
                .setCancelable(false)
                .setPositiveButton(positiveButtonText, new DialogInterface.OnClickListener() {
                    public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                        Intent mIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                        mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        mContext.startActivity(mIntent);
                    }
                })
                .setNegativeButton(negativeButtonText, new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                        mActivity.finish();
                    }
                });
        final AlertDialog alert = builder.create();
        alert.show();
    }


    public Location getLastKnownLocation() {
        locationProvider = LocationManager.NETWORK_PROVIDER;
        Location lastKnownLocation = null;
        // Or use LocationManager.GPS_PROVIDER
        if (Build.VERSION.SDK_INT >= 23 &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return lastKnownLocation;
        }
        try {
            lastKnownLocation = locationManager.getLastKnownLocation(locationProvider);
            return lastKnownLocation;
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
        return lastKnownLocation;
    }

    public boolean isGooglePlayServicesAvailable() {
        int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(mContext);

        if (status == ConnectionResult.SUCCESS) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Determines whether one Location reading is better than the current Location fix
     *
     * @param location            The new Location that you want to evaluate
     * @param currentBestLocation The current Location fix, to which you want to compare the new one
     */
    protected Location getBetterLocation(Location location, Location currentBestLocation) {
        if (currentBestLocation == null) {
            // A new location is always better than no location
            return location;
        }

        // Check whether the new location fix is newer or older
        long timeDelta = location.getTime() - currentBestLocation.getTime();
        boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
        boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
        boolean isNewer = timeDelta > 0;

        // If it's been more than two minutes since the current location, use the new location
        // because the user has likely moved
        if (isSignificantlyNewer) {
            return location;
            // If the new location is more than two minutes older, it must be worse
        } else if (isSignificantlyOlder) {
            return currentBestLocation;
        }

        // Check whether the new location fix is more or less accurate
        int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation.getAccuracy());
        boolean isLessAccurate = accuracyDelta > 0;
        boolean isMoreAccurate = accuracyDelta < 0;
        boolean isSignificantlyLessAccurate = accuracyDelta > 200;

        // Check if the old and new location are from the same provider
        boolean isFromSameProvider = isSameProvider(location.getProvider(),
                currentBestLocation.getProvider());

        // Determine location quality using a combination of timeliness and accuracy
        if (isMoreAccurate) {
            return location;
        } else if (isNewer && !isLessAccurate) {
            return location;
        } else if (isNewer && !isSignificantlyLessAccurate && isFromSameProvider) {
            return location;
        }
        return currentBestLocation;
    }

    /**
     * Checks whether two providers are the same
     */

    private boolean isSameProvider(String provider1, String provider2) {
        if (provider1 == null) {
            return provider2 == null;
        }
        return provider1.equals(provider2);
    }

    public boolean isLocationAccurate(Location location) {
        if (location.hasAccuracy()) {
            return true;
        } else {
            return false;
        }
    }

    public Location getStaleLocation() {
        if (mLastLocationFetched != null) {
            return mLastLocationFetched;
        }
        if (Build.VERSION.SDK_INT >= 23 &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ContextCompat.checkSelfPermission(mContext, android.Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return null;
        }
        if (mProviderType == SmartLocationManager.GPS_PROVIDER) {
            return locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        } else if (mProviderType == SmartLocationManager.NETWORK_PROVIDER) {
            return locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        } else {
            return getBetterLocation(locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER), locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER));
        }
    }
}

chúng ta có thể sử dụng nó với hoạt động hoặc một đoạn, ở đây tôi đang sử dụng nó với hoạt động

import android.location.Location;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import android.widget.Toast;

import com.example.raza.locationaware.location.LocationManagerInterface;
import com.example.raza.locationaware.location.SmartLocationManager;
import com.google.android.gms.location.LocationRequest;

public class LocationActivity extends AppCompatActivity implements LocationManagerInterface {

    public static final String TAG = LocationActivity.class.getSimpleName();

    SmartLocationManager mLocationManager;
    TextView mLocalTV, mLocationProviderTV, mlocationTimeTV;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_location);
        mLocationManager = new SmartLocationManager(getApplicationContext(), this, this, SmartLocationManager.ALL_PROVIDERS, LocationRequest.PRIORITY_HIGH_ACCURACY, 10 * 1000, 1 * 1000, SmartLocationManager.LOCATION_PROVIDER_RESTRICTION_NONE); // init location manager
        mLocalTV = (TextView) findViewById(R.id.locationDisplayTV);
        mLocationProviderTV = (TextView) findViewById(R.id.locationProviderTV);
        mlocationTimeTV = (TextView) findViewById(R.id.locationTimeFetchedTV);
    }

    protected void onStart() {
        super.onStart();
        mLocationManager.startLocationFetching();
    }

    protected void onStop() {
        super.onStop();
        mLocationManager.abortLocationFetching();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mLocationManager.pauseLocationFetching();
    }

    @Override
    public void locationFetched(Location mLocal, Location oldLocation, String time, String locationProvider) {
        Toast.makeText(getApplication(), "Lat : " + mLocal.getLatitude() + " Lng : " + mLocal.getLongitude(), Toast.LENGTH_LONG).show();
        mLocalTV.setText("Lat : " + mLocal.getLatitude() + " Lng : " + mLocal.getLongitude());
        mLocationProviderTV.setText(locationProvider);
        mlocationTimeTV.setText(time);
    }
}

Hy vọng nó sẽ giúp, nếu bạn có thể đề nghị bất kỳ cải thiện vui lòng gửi nó trên git . Cảm ơn.


5

GoogleSamples có ví dụ dài dòng bằng cách sử dụng FuseLocationProviderApi mới nhất. Thật không may, các câu trả lời được đánh giá cao nhất đã hết hạn.

Thực hiện theo các ví dụ dưới đây để triển khai Dịch vụ vị trí bằng cách sử dụng FuseLocationProviderApi

https://github.com/googlesamples/android-play-location/tree/master/LocationUpdates

https://github.com/googlesamples/android-play-location/blob/master/LocationUpdates/app/src/main/java/com/google/android/gms/location/sample/locationupdates/MainActivity.java


3

Nếu bạn đang tạo dự án vị trí mới cho Android, bạn nên sử dụng Google Play mới dịch vụ vị trí . Nó chính xác hơn nhiều và sử dụng đơn giản hơn nhiều.

Tôi đã làm việc trong một dự án theo dõi GPS nguồn mở , GpsTracker, trong vài năm. Gần đây tôi đã cập nhật nó để xử lý các bản cập nhật định kỳ từ điện thoại di động Android, iOS, Windows Phone và Java ME . Nó có đầy đủ chức năng và làm những gì bạn cần và có Giấy phép MIT .

Dự án Android trong GpsTracker sử dụng các dịch vụ Google Play mới và cũng có hai ngăn xếp máy chủ ( ASP.NETPHP ) để cho phép bạn theo dõi các điện thoại đó.


3
Vấn đề là không phải tất cả các thiết bị đều có Dịch vụ Google Play, bao gồm mọi ROM tùy chỉnh không vi phạm bản quyền. Nếu bạn sẽ sử dụng nó, hãy chuẩn bị sẵn sàng cho LocationManager.
Gabe Sechan

3

Để kiểm tra vị trí, bạn có thể sử dụng mã sau đây. Bạn có thể đặt nó trong hộp thoại onStart () của hoạt động chính và hiển thị cảnh báo nếu trả về là sai.

private boolean isLocationAccurate()
    {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
        {
            String provider = Settings.Secure
                    .getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
            if (provider != null && !provider.contains("gps"))
            {
                return false;
            }
        }
        else
        {
            try
            {
                int status = Settings.Secure
                        .getInt(this.getContentResolver(), Settings.Secure.LOCATION_MODE);
                if (status != Settings.Secure.LOCATION_MODE_HIGH_ACCURACY)
                {
                    return false;
                }
            }
            catch (Settings.SettingNotFoundException e)
            {
                Log.e(TAG, e.getMessage());
            }
        }

        return true;
    }

3

Tôi đã có được vị trí rất chính xác khi sử dụng FuseLocationProviderClient
( yêu cầu dịch vụ Google Play )

Yêu cầu quyền

ERIC.ACCESS_FINE_LOCATION

ERIC.ACCESS_COARSE_LOCATION

Phụ thuộc

'com.google.android.gms: play-services-location: 15.0.0'

Mã Kotlin

val client = FusedLocationProviderClient(this)
val location = client.lastLocation
location.addOnCompleteListener {
    // this is a lambda expression and we get an 'it' iterator to access the 'result'
    // it.result.latitude gives the latitude
    // it.result.longitude gives the longitude 
    val geocoder = Geocoder(applicationContext, Locale.getDefault())
    val address = geocoder.getFromLocation(it.result.latitude, it.result.longitude, 1)
    if (address != null && address.size > 0) {
        // Get the current city
        city = address[0].locality
    }
}
location.addOnFailureListener {
    // Some error in getting the location, let's log it
    Log.d("xtraces", it.message)
}

3

Cách tốt nhất để tìm nạp vị trí là dưới đây

// put dependancy
 implementation 'com.google.android.gms:play-services-location:11.0.4'

// PUT permissions in Menifest
<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" /> 


// create a Java file as below

public class SingleShotLocationProvider {

  public static interface LocationCallback {
      public void onNewLocationAvailable(GPSCoordinates location);
  }

   // calls back to calling thread, note this is for low grain: if you want higher precision, swap the
   // contents of the else and if. Also be sure to check gps permission/settings are allowed.
   // call usually takes <10ms

  public static void requestSingleUpdate(final Context context, final LocationCallback callback) {
    final LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
    boolean isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    if (isNetworkEnabled) {
        Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_COARSE);
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            return;
        }
        locationManager.requestSingleUpdate(criteria, new LocationListener() {
            @Override
            public void onLocationChanged(Location location) {
                callback.onNewLocationAvailable(new GPSCoordinates(location.getLatitude(), location.getLongitude()));
            }

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

            @Override
            public void onProviderEnabled(String provider) {
            }

            @Override
            public void onProviderDisabled(String provider) {
            }
        }, null);
     } else {
        boolean isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        if (isGPSEnabled) {
            Criteria criteria = new Criteria();
            criteria.setAccuracy(Criteria.ACCURACY_FINE);
            locationManager.requestSingleUpdate(criteria, new LocationListener() {
                @Override
                public void onLocationChanged(Location location) {
                    callback.onNewLocationAvailable(new GPSCoordinates(location.getLatitude(), location.getLongitude()));
                }

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


  // consider returning Location instead of this dummy wrapper class
  public static class GPSCoordinates {
     public float longitude = -1;
     public float latitude = -1;

     public GPSCoordinates(float theLatitude, float theLongitude) {
        longitude = theLongitude;
        latitude = theLatitude;
     }

     public GPSCoordinates(double theLatitude, double theLongitude) {
        longitude = (float) theLongitude;
        latitude = (float) theLatitude;
     }
  }

}
// FILE FINISHED


// FETCH LOCATION FROM ACTIVITY AS BELOW
public void getLocation(Context context) {
    MyApplication.log(LOG_TAG, "getLocation() ");

    SingleShotLocationProvider.requestSingleUpdate(context,
            new SingleShotLocationProvider.LocationCallback() {
                @Override
                public void onNewLocationAvailable(SingleShotLocationProvider.GPSCoordinates loc) {
                    location = loc;
                    MyApplication.log(LOG_TAG, "getLocation() LAT: " + location.latitude + ", LON: " + location.longitude);               
                }
            });
}

2

Tôi đã xuất bản một thư viện nhỏ có thể giúp bạn dễ dàng lấy dữ liệu vị trí trong Android, thậm chí nó còn chăm sóc các quyền của thời gian chạy Android M.

Bạn có thể kiểm tra nó ở đây: https://github.com/julioromano/RxLocation và sử dụng nó hoặc mã nguồn của nó làm ví dụ cho việc triển khai của bạn.


Đó là một giải pháp tốt nhưng không phải là tốt nhất, không hoạt động hầu hết thời gian. Tôi không nhận được kết quả ngay lập tức sau khi nhấp vào nút.
Asif Ali

@AsifAli Nếu bạn tìm thấy một lỗi, vui lòng mở một vấn đề hoặc gửi PR.
Marco Romano

Thư viện này vì thư viện này thiếu một lớp AbstractSafeParcelable
Vikash Parajuli

2

Tìm mã đơn giản Viết mã theo phương pháp vị trí

public void onLocationChanged(Location location) {
    if (mCurrLocationMarker != null) {
        mCurrLocationMarker.remove();
    }


    //Place current location marker
    LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
    MarkerOptions markerOptions = new MarkerOptions();
    markerOptions.position(latLng);
    markerOptions.title("Current Position");
    markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
    mCurrLocationMarker = mMap.addMarker(markerOptions);

    //move map camera
    mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
    mMap.animateCamera(CameraUpdateFactory.zoomTo(18));

    PolylineOptions pOptions = new PolylineOptions()
            .width(5)
            .color(Color.GREEN)
            .geodesic(true);
    for (int z = 0; z < routePoints.size(); z++) {
        LatLng point = routePoints.get(z);
        pOptions.add(point);
    }
    line = mMap.addPolyline(pOptions);
    routePoints.add(latLng);
}

2

Tôi sẽ khuyên bạn nên sử dụng Thư viện vị trí thông minh
Rất đơn giản để sử dụng và nó bao bọc logic vị trí độc đáo.

Để bắt đầu dịch vụ định vị:

SmartLocation.with(context).location()
    .start(new OnLocationUpdatedListener() { ... });

Nếu bạn chỉ muốn có được một vị trí (không phải định kỳ), bạn có thể chỉ cần sử dụng công cụ sửa đổi oneFix. Thí dụ:

SmartLocation.with(context).location()
    .oneFix()
    .start(new OnLocationUpdatedListener() { ... });

0

Cách đơn giản và dễ dàng

Nhận vị trí bằng cách sử dụng https://github.com/sachinvarma/ EasyLocation .

Bước 1: Chỉ cần gọi

new EasyLocationInit(MainActivity.this, timeInterval, fastestTimeInterval, runAsBackgroundService);

timeInterval -> setInterval (dài) (inMilliSeconds) có nghĩa - đặt khoảng thời gian mà bạn muốn nhận vị trí.

quickTimeInterval -> setFastestInterval (dài) (inMilliSeconds) có nghĩa là - nếu một vị trí có sẵn sớm hơn bạn có thể lấy nó. (tức là một ứng dụng khác đang sử dụng dịch vụ định vị).

runAsBackgroundService = True -> (Dịch vụ sẽ chạy trong Nền và cập nhật thường xuyên (theo timeInterval và quickTimeInterval)) runAsBackgroundService = false -> (Dịch vụ sẽ getDestroyed sau khi cập nhật vị trí thành công)

Bước 2: Chuẩn bị người đăng ký EventBus: Khai báo và chú thích phương thức đăng ký của bạn, tùy chọn chỉ định chế độ luồng:

ví dụ:

     @Override
     public void onStart() {
         super.onStart();
         EventBus.getDefault().register(this);
     }

     @Override
     public void onStop() {
         super.onStop();
         EventBus.getDefault().unregister(this);
     }

  @SuppressLint("SetTextI18n")
  @Subscribe
  public void getEvent(final Event event) {

    if (event instanceof LocationEvent) {
      if (((LocationEvent) event).location != null) {
        ((TextView) findViewById(R.id.tvLocation)).setText("The Latitude is "
          + ((LocationEvent) event).location.getLatitude()
          + " and the Longitude is "
          + ((LocationEvent) event).location.getLongitude());
      }
    }
  }

Đó là tất cả.

Hy vọng nó sẽ giúp được ai đó trong tương lai.


0

Tháng 4 năm 2020

Các bước đầy đủ để có được vị trí hiện tại và tránh tính vô hiệu của Vị trí đã biết Cuối cùng.

Theo tài liệu chính thức , Địa điểm được biết đến cuối cùng có thể là Null trong trường hợp:

  • Vị trí bị tắt trong cài đặt thiết bị. Khi nó xóa bộ nhớ cache.
  • Thiết bị không bao giờ ghi lại vị trí của nó. (Thiết bị mới)
  • Dịch vụ Google Play trên thiết bị đã khởi động lại.

Trong trường hợp này, bạn nên yêu cầuLocationUpdates và nhận vị trí mới trên LocationCallback .

Bằng các bước sau Vị trí được biết đến cuối cùng của bạn không bao giờ null.


Điều kiện tiên quyết: Thư viện EasyPermission


Bước 1: Trong tệp kê khai thêm quyền này

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Bước 2:

    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    //Create location callback when it's ready.
    createLocationCallback()

    //createing location request, how mant request would be requested.
    createLocationRequest()

    //Build check request location setting request
    buildLocationSettingsRequest()

    //FusedLocationApiClient which includes location 
    mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this)
    //Location setting client
    mSettingsClient = LocationServices.getSettingsClient(this)

    //Check if you have ACCESS_FINE_LOCATION permission
    if (!EasyPermissions.hasPermissions(
            this@MainActivity,
            Manifest.permission.ACCESS_FINE_LOCATION)) {
        requestPermissionsRequired()
    }
    else{
        //If you have the permission we should check location is opened or not
        checkLocationIsTurnedOn()
    }

}

Bước 3: Tạo các hàm cần thiết được gọi trong onCreate ()

private fun requestPermissionsRequired() {
    EasyPermissions.requestPermissions(
        this,
        getString(R.string.location_is_required_msg),
        LOCATION_REQUEST,
        Manifest.permission.ACCESS_FINE_LOCATION
    )
}

private fun createLocationCallback() {
    //Here the location will be updated, when we could access the location we got result on this callback.
    mLocationCallback = object : LocationCallback() {
        override fun onLocationResult(locationResult: LocationResult) {
            super.onLocationResult(locationResult)
            mCurrentLocation = locationResult.lastLocation
        }
    }
}

private fun buildLocationSettingsRequest() {
    val builder = LocationSettingsRequest.Builder()
    builder.addLocationRequest(mLocationRequest!!)
    mLocationSettingsRequest = builder.build()
    builder.setAlwaysShow(true)
}

private fun createLocationRequest() {
    mLocationRequest = LocationRequest.create()
    mLocationRequest!!.interval = 0
    mLocationRequest!!.fastestInterval = 0
    mLocationRequest!!.numUpdates = 1
    mLocationRequest!!.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}

public fun checkLocationIsTurnedOn() { // Begin by checking if the device has the necessary location settings.
    mSettingsClient!!.checkLocationSettings(mLocationSettingsRequest)
        .addOnSuccessListener(this) {
            Log.i(TAG, "All location settings are satisfied.")
            startLocationUpdates()
        }
        .addOnFailureListener(this) { e ->
            val statusCode = (e as ApiException).statusCode
            when (statusCode) {
                LocationSettingsStatusCodes.RESOLUTION_REQUIRED -> {
                    try {
                        val rae = e as ResolvableApiException
                        rae.startResolutionForResult(this@MainActivity, LOCATION_IS_OPENED_CODE)
                    } catch (sie: IntentSender.SendIntentException) {
                    }
                }
                LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
                    mRequestingLocationUpdates = false
                }
            }
        }
}

private fun startLocationUpdates() {
    mFusedLocationClient!!.requestLocationUpdates(
        mLocationRequest,
        mLocationCallback, null
    )
}

Bước 4:

Xử lý các cuộc gọi lại trong onActivityResult () sau khi đảm bảo vị trí được mở hoặc người dùng chấp nhận mở nó vào.

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    when (requestCode) {
        LOCATION_IS_OPENED_CODE -> {
            if (resultCode == AppCompatActivity.RESULT_OK) {
                Log.d(TAG, "Location result is OK")
            } else {
                activity?.finish()
            }
        }
}

Bước 5: Nhận vị trí được biết đến cuối cùng từ FuseClientApi

override fun onMapReady(map: GoogleMap) {
    mMap = map
    mFusedLocationClient.lastLocation.addOnSuccessListener {
        if(it!=null){
            locateUserInMap(it)
        }
    }

}
   private fun locateUserInMap(location: Location) {
    showLocationSafetyInformation()
    if(mMap!=null){
        val currentLocation = LatLng(location.latitude,location.longitude )
        addMarker(currentLocation)
    }
}


private fun addMarker(currentLocation: LatLng) {
    val cameraUpdate = CameraUpdateFactory.newLatLng(currentLocation)
    mMap?.clear()
    mMap?.addMarker(
        MarkerOptions().position(currentLocation)
            .title("Current Location")
    )
    mMap?.moveCamera(cameraUpdate)
    mMap?.animateCamera(cameraUpdate)
    mMap?.setMinZoomPreference(14.0f);
}

Tôi hy vọng điều này sẽ giúp.

Mã hóa hạnh phúc

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.