获取当前用户位置或上次已知位置

时间:2016-10-14 03:53:07

标签: android google-maps location google-api-client

我意识到这个问题之前已被问过很多次,但我现在问它,因为答案很古老(与新的API相比)。

之前我使用过位置管理器,但我发现它非常不可靠。例如,在我的应用程序中,使用getLastKnownLocation和/或当前位置,它会立即加载相机在用户的当前位置。但是说如果我在开始使用应用程序之前就将设备上的位置关闭了,那么相机就不会出现在用户的当前位置,而是放在Nigera附近(默认视图,我相信)。

只有当我使用谷歌地图应用程序和针脚指向我的位置或我等了一段时间,然后我的应用程序将加载用户在视图中的位置(使用moveCamera)。

有时它会起作用,有时则不行。但我想使用谷歌Api客户端,或者更平滑的东西来检索用户的位置。

我想这样做:

1。)如果用户没有打开他们的位置,请提示他们打开它。

2.。)打开位置后,启动地图相机/视图,用户当前位置在中心。

3。)最后,如果用户决定取消位置或从他们的位置移动,请不要做任何事情。

我在这里已经阅读了很多问题,但是找不到任何可以帮助我使用Google Api Client或其他任何东西配置此功能的内容。我用位置管理器尝试了几乎所有东西,但我仍然无法让它顺利运行。出于沮丧,我删除了所有的位置管理器代码。

如果你想看看我写下或试过的内容,我的大多数资料来自这个问题(和相关的):

What is the simplest and most robust way to get the user's current location on Android?

感谢您抽出宝贵时间阅读本文。

2 个答案:

答案 0 :(得分:0)

位置管理器对我来说非常合适,但对于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 :(得分:0)

以下服务优雅地为我提供位置服务的准确性和状态。在我登录应用程序之前使用此服务,因为应用程序需要启用位置服务。

根据此服务输入,您可以

  1. 提示用户启用位置
  2. 收到位置后,可以启动地图
  3. 如果位置已断开,请注意其余逻辑
  4. 要记住位置更新的重要事项是

    • 指定接收更新的最小距离更改 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);
        }
    }
    

    注意:此服务需要在更新版本中进行测试