簡體   English   中英

獲取當前用戶位置或最后已知位置

[英]Get current user location or last known location

我意識到這個問題之前已經被問過很多次了,但我現在問它是因為答案很舊(與新 API 相比)。

我以前使用過位置管理器,但我發現它非常不可靠。 例如在我的應用程序中,使用 getLastKnownLocation 和/或當前位置,它會立即加載用戶當前位置的相機。 但是假設我在啟動我的應用程序之前在我的設備上打開了位置,它不會在用戶的當前位置上顯示相機,而是在 Nigera 附近的某個地方(我相信是默認視圖)。

僅當我使用 Google 地圖應用程序並固定我的位置或等待一段時間時,我的應用程序才會在視圖中加載用戶的位置(使用 moveCamera)。

有時它會起作用,有時它不會。 但是我想使用 Google Api Client 或者更流暢的東西來檢索用戶的位置。

我想這樣做:

1.) 如果用戶沒有打開他們的位置,提示他們打開它。

2.) 打開定位后,以用戶當前位置為中心啟動地圖相機/視圖。

3.) 最后,如果用戶決定離開位置或從他們的位置移動,絕對什么都不做。

我在這里閱讀了很多問題,但找不到任何可以幫助我使用 Google Api 客戶端或其他任何東西配置此功能的內容。 我已經嘗試了幾乎所有的位置管理器,但我仍然無法讓它順利工作。 出於沮喪,我刪除了我所有的位置管理器代碼。

如果你想看看我寫下或嘗試過的內容,我的大部分資料都來自這個問題(和相關的):

在 Android 上獲取用戶當前位置的最簡單、最可靠的方法是什么?

感謝您抽出時間來閱讀。

位置管理器非常適合我,但是對於 API 級別 23,您需要做一些解決方法。 獲取API級別23的權限,需要在主線程中編寫權限邏輯。

這是我在其中一個代碼中使用的示例。

   /*Checking for permission if API level is more than 23 or 23, if condition match function calls*/
    if (Build.VERSION.SDK_INT >= 23) {
        requestMultiplePermissions();
    }

    /*Background Thread for splash screen with 2 seconds*/
    final Thread splashScreenThread = new Thread() {

        public void run() {

            try {
                Thread.sleep(2000);

            } catch (InterruptedException exception) {
                exception.printStackTrace();
            } finally {
                Intent homeScreen = new Intent(SplashScreen.this, MainActivity.class);
                startActivity(homeScreen);
                finish();

            }
        }
    };

    splashScreenThread.start();


}

/*Standar Permission chcking code for API level 23 or more*/
private void requestMultiplePermissions() {
    String locationPermission = Manifest.permission.ACCESS_FINE_LOCATION;
    int hasLocPermission = checkSelfPermission(locationPermission);
    List<String> permissions = new ArrayList<String>();
    if (hasLocPermission != PackageManager.PERMISSION_GRANTED) {
        permissions.add(locationPermission);
    }

    if (!permissions.isEmpty()) {
        String[] params = permissions.toArray(new String[permissions.size()]);
        requestPermissions(params, 1);
    } else {
        // We already have permission, so handle as normal

    }

}

/*This is function is used when permissions is granted by user, here we are firing a Intent after getting permission
* */
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                       int[] grantResults) {
    Toast.makeText(SplashScreen.this, " " + grantResults, Toast.LENGTH_SHORT).show();
    switch (requestCode) {
        case 1:
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Handle permission granted firing the Intent
                Intent intent = new Intent(SplashScreen.this, MainActivity.class);
                startActivity(intent);
                finish();

            } else {
                // Handle permission denied, giving Alertbox to user with some text
                new AlertDialog.Builder(this)
                        .setMessage("The app cannot continue without permissions")
                        .setCancelable(false)
                        .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                            public void onClick(DialogInterface dialog, int id) {
                                SplashScreen.this.finish();
                            }
                        })
                        .show();


            }
            break;
        default:
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
    //

在您的 Mainactivity 或您想要的任何地方輸入上述代碼,我更願意在應用程序啟動時請求許可。

以下服務優雅地為我提供了位置服務的准確性和狀態。 在我登錄應用程序之前使用此服務,因為應用程序需要啟用定位服務。

基於此服務輸入,您可以

  1. 提示用戶開啟定位
  2. 一旦接收到位置,就可以啟動地圖
  3. 如果位置斷開連接,請注意其余邏輯

位置更新要記住的要點是

  • 指定接收更新的最小距離變化setSmallestDisplacement (即使我們長時間停留在一個位置不動,API 也會取回數據)
  • 設置 FastestInterval以接收位置更新
  • 根據您的要求設置優先級參數setPriority

    public class AppLocationService extends Service implements GoogleApiClient.ConnectionCallbacks,
            GoogleApiClient.OnConnectionFailedListener,
            LocationListener{

        private LocationRequest locationRequest;
        private GoogleApiClient googleApiClient;
        private Context appContext;
        private boolean currentlyProcessingLocation = false;
        private int mInterval=0;
        private final int CONNTIMEOUT=50000;
        private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters

    @Override
    public void onCreate() {
        super.onCreate();

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        appContext=getBaseContext();
        Toast.makeText(getBaseContext(), "Location Service Started", Toast.LENGTH_SHORT)
                .show();
        if(intent != null){
            mInterval = intent.getIntExtra(Constants.REFRESHTIMETAG, 5);
            mIMEI = intent.getStringExtra(Constants.IMEITAG);
            Log.v(Constants.BLL_LOG, "AppLocationService onStartCommand , mInterval=" + mInterval + " | mIMEI=" + mIMEI);
        }
        if (!currentlyProcessingLocation) {
            currentlyProcessingLocation = true;
            startTracking();
        }

        return START_STICKY;
    }

    private void startTracking() {
        Log.v(Constants.BLL_LOG, "startTracking");
        if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) {
            Log.v(Constants.BLL_LOG, "ConnectionResult SUCCESS");
            googleApiClient = new GoogleApiClient.Builder(this)
                    .addApi(LocationServices.API)
                    .addConnectionCallbacks(this)
                    .addOnConnectionFailedListener(this)
                    .build();

            if (!googleApiClient.isConnected() || !googleApiClient.isConnecting()) {
                googleApiClient.connect();
                Log.v(Constants.BLL_LOG, "googleApiClient.connect()");
            }else{
                Log.v(Constants.BLL_LOG, "NOT connected googleApiClient.connect()");
                //
                //INTIMATE UI WITH EITHER HANDLER OR RUNONUI THREAD
                //
            }
        } else {
            Log.v(Constants.BLL_LOG, "unable to connect to google play services.");
        }
    }

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

    @Override
    public void onConnected(Bundle bundle) {
        Log.v(Constants.BLL_LOG, "onConnected");
        locationRequest = LocationRequest.create();
        locationRequest.setInterval(mInterval * 1000); // milliseconds
        locationRequest.setFastestInterval(mInterval * 1000);
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setSmallestDisplacement(MIN_DISTANCE_CHANGE_FOR_UPDATES);//distance change
        int permissionCheck = ContextCompat.checkSelfPermission(appContext, Manifest.permission.ACCESS_COARSE_LOCATION);
        if (permissionCheck!= PackageManager.PERMISSION_DENIED)
        {    LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);}

        Handler handler = new Handler(Looper.getMainLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(appContext, "Location Service got connected", Toast.LENGTH_SHORT)
                        .show();
            }
        });
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.v(Constants.BLL_LOG, "onConnectionSuspended");
        //INTIMATE UI ABOUT DISCONNECTION STATUS
    }

    @Override
    public void onLocationChanged(Location location) {
        Log.v(Constants.BLL_LOG, "onLocationChanged position: " + location.getLatitude() + ", " + location.getLongitude() + " accuracy: " + location.getAccuracy());
        //if (location.getAccuracy() < 500.0f) 
        Log.v(Constants.BLL_LOG, "onLocationChanged position: location.getAccuracy()= "+location.getAccuracy());

        //DO YOUR BUSINESS LOGIC, FOR ME THE SAME WAS TO SEND TO SERVER
        sendLocationDataToWebsite(location);        

    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.v(Constants.BLL_LOG, "onConnectionFailed");
        Handler handler = new Handler(Looper.getMainLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(appContext, "Location Service got disconnected temporarily", Toast.LENGTH_SHORT)
                        .show();
            }
        });
    }

    /**
     * Send details to server
     * @param location
     */
    void sendLocationDataToWebsite(Location location){


    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (googleApiClient != null && googleApiClient.isConnected()) {
            googleApiClient.disconnect();
        }
        this.unregisterReceiver(this.batteryInfoReceiver);
    }
}

注意:此服務仍需要在更新版本中進行測試

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM