Android上的LocationManager API似乎对一个只需要偶尔粗略估计用户位置的应用程序来说有点麻烦。

我正在开发的应用程序本身并不是一个定位应用程序,但它确实需要获取用户的位置,以便显示附近企业的列表。它不需要担心用户是否在移动或类似的事情。

以下是我想做的:

向用户显示附近位置的列表。预加载用户的位置,以便在“活动X”中需要它时,它将可用。我并不特别关心更新的准确性或频率。只要不太远,只要抓住一个位置就足够了。也许如果我想变得更漂亮,我会每隔几分钟左右更新一次位置,但这不是一个很大的优先事项。适用于任何具有GPS或网络位置提供商的设备。

这似乎并不难,但在我看来,我必须组建两个不同的位置提供商(GPS和NETWORK),并管理每个提供商的生命周期。不仅如此,我还必须在多个活动中复制相同的代码以满足#2。过去,我曾尝试使用getBestProvider()将解决方案简化为仅使用一个位置提供程序,但这似乎只提供了最好的“理论”提供程序,而不是实际会为您提供最佳结果的提供程序。

有没有更简单的方法来实现这一点?


当前回答

地理定位的简单和最佳方式。

LocationManager lm = null;
boolean network_enabled;


if (lm == null)
                lm = (LocationManager) Kikit.this.getSystemService(Context.LOCATION_SERVICE);

            network_enabled = lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            dialog = ProgressDialog.show(Kikit.this, "", "Fetching location...", true);


            final Handler handler = new Handler();
            timer = new Timer();
            TimerTask doAsynchronousTask = new TimerTask() {

                @Override
                public void run() {
                    handler.post(new Runnable() {

                        @Override
                        public void run() 
                        {

                            Log.e("counter value","value "+counter);

                            if(counter<=8)
                            {
                                try 
                                {
                                    counter++;


                                    if (network_enabled) {

                                        lm = (LocationManager) Kikit.this.getSystemService(Context.LOCATION_SERVICE);

                                        Log.e("in network_enabled..","in network_enabled");

                                        // Define a listener that responds to location updates
                                        LocationListener locationListener = new LocationListener() 
                                        {


                                            public void onLocationChanged(Location location) 
                                            {
                                                if(attempt == false)

                                                {
                                                    attempt = true;
                                                    Log.e("in location listener..","in location listener..");
                                                    longi = location.getLongitude();
                                                    lati = location.getLatitude();
                                                    Data.longi = "" + longi; 
                                                    Data.lati = "" + lati;


                                                    Log.e("longitude : ",""+longi);
                                                    Log.e("latitude : ",""+lati);



                                                    if(faceboo_name.equals(""))
                                                    {
                                                        if(dialog!=null){
                                                        dialog.cancel();}
                                                        timer.cancel();
                                                        timer.purge();
                                                        Data.homepage_resume = true;
                                                        lm = null;
                                                        Intent intent = new Intent();                              
                                                        intent.setClass(Kikit.this,MainActivity.class);

                                                        startActivity(intent);      
                                                        finish();
                                                    }
                                                    else
                                                    {           

                                                        isInternetPresent = cd.isConnectingToInternet();

                                                        if (isInternetPresent) 
                                                        {
                                                            if(dialog!=null)
                                                                dialog.cancel();

                                                            Showdata();
                                                        }
                                                        else
                                                        {
                                                            error_view.setText(Data.internet_error_msg);
                                                            error_view.setVisibility(0);
                                                            error_gone();
                                                        }

                                                    }   
                                                }

                                            }

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

                                            public void onProviderEnabled(String provider) {
                                                //Toast.makeText(getApplicationContext(), "Location enabled", Toast.LENGTH_LONG).show();

                                            }

                                            public void onProviderDisabled(String provider) {


                                            }
                                        };



                                        // Register the listener with the Location Manager to receive
                                        // location updates
                                        lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 100000, 10,locationListener);

                                    } else{
                                        //Toast.makeText(getApplicationContext(), "No Internet Connection.", 2000).show();
                                        buildAlertMessageNoGps();

                                    }



                                } catch (Exception e) {
                                    // TODO
                                    // Auto-generated
                                    // catch
                                    // block
                                }
                            }
                            else
                            {

                                timer.purge();
                                timer.cancel();

                                if(attempt == false)
                                {
                                    attempt = true;

                                    String locationProvider = LocationManager.NETWORK_PROVIDER;
                                    // Or use LocationManager.GPS_PROVIDER

                                    try {
                                        Location lastKnownLocation = lm.getLastKnownLocation(locationProvider);

                                        longi = lastKnownLocation.getLongitude();
                                        lati = lastKnownLocation.getLatitude();
                                        Data.longi = "" + longi; 
                                        Data.lati = "" + lati;
                                    } catch (Exception e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                        Log.i("exception in loc fetch", e.toString());
                                    }

                                    Log.e("longitude of last known location : ",""+longi);
                                    Log.e("latitude of last known location : ",""+lati);

                                    if(Data.fb_access_token == "")
                                    {

                                        if(dialog!=null){
                                            dialog.cancel();}
                                        timer.cancel();
                                        timer.purge();
                                        Data.homepage_resume = true;
                                        Intent intent = new Intent();                              
                                        intent.setClass(Kikit.this,MainActivity.class);

                                        startActivity(intent);  
                                        finish();
                                    }
                                    else
                                    {           

                                        isInternetPresent = cd.isConnectingToInternet();

                                        if (isInternetPresent) 
                                        {
                                            if(dialog!=null){
                                                dialog.cancel();}           
                                            Showdata();
                                        }
                                        else
                                        {
                                            error_view.setText(Data.internet_error_msg);
                                            error_view.setVisibility(0);
                                            error_gone();
                                        }

                                    }   

                                }
                            }
                        }
                    });
                }
            };
            timer.schedule(doAsynchronousTask, 0, 2000);


private void buildAlertMessageNoGps() {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);

        builder.setMessage("Your WiFi & mobile network location is disabled , do you want to enable it?")
        .setCancelable(false)
        .setPositiveButton("Yes", new DialogInterface.OnClickListener() {


            public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) 
            {
                startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
                setting_page = true;
            }
        })
        .setNegativeButton("No", new DialogInterface.OnClickListener() {
            public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                dialog.cancel();
                finish();
            }
        });
        final AlertDialog alert = builder.create();
        alert.show();
    }

其他回答

编辑:更新了Google Play Services库中的最新位置服务API(2014年7月)

我建议您使用新的位置服务API,该API可从Google Play Services库中获得,它提供了一个更强大的高级框架,可自动执行位置提供商选择和电源管理等任务。根据官方文档:“……位置API使您可以轻松地构建位置感知应用程序,而无需关注底层位置技术的细节。它们还允许您通过使用设备硬件的所有功能来最小化功耗。”

有关更多信息,请访问:使您的应用程序位置感知

要查看使用最新位置服务API的完整示例,请访问:Android LocationClient类已弃用,但在文档中使用

这是我请求用户权限的方式。

在AndroidManifest.xml中的应用程序标记外添加这些权限请求。

<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" />

然后在App Gradle文件中添加Google的位置依赖项。

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

现在声明一些全局变量。

private lateinit var mFusedLocationProvider:FusedLocationProviderClient
private lateinit var mLocationCallback: LocationCallback
private lateinit var mLocationRequest: LocationRequest
private var mLocationPermissionGranted:Boolean = false

在活动的OnCreate方法中(我无法正确格式化代码,对此深表歉意)

mFusedLocationProvider = LocationServices.getFusedLocationProviderClient(this)

//Location Callback
mLocationCallback = object: LocationCallback(){
 override fun onLocationResult(p0: LocationResult?) {
  if(p0==null){
     //todo(request user to enable location from settings then remove return)
     return
  }else{
      getDeviceLocation()
       }
  }
}

//Location Request
mLocationRequest = LocationRequest.create()
mLocationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY
//Set the Interval for Latest Interval Update
mLocationRequest.interval = 5000
//Set How Many Location Updated you Want
mLocationRequest.numUpdates = 1

getLocationPermission()
getDeviceLocation()

现在创建这两个函数。

 private fun getLocationPermission() {

            val permission:Array<String> = arrayOf(android.Manifest.permission.ACCESS_FINE_LOCATION,android.Manifest.permission.ACCESS_COARSE_LOCATION)
            if(ContextCompat.checkSelfPermission(applicationContext,Constant.FINE_LOCATION)== PermissionChecker.PERMISSION_GRANTED){
                if(ContextCompat.checkSelfPermission(applicationContext,Constant.COARSE_LOCATION)== PermissionChecker.PERMISSION_GRANTED){
                    mLocationPermissionGranted = true
                }
            }else{
                ActivityCompat.requestPermissions(this,permission,Constant.LOCATION_REQUEST_CODE)
            }

    }

第二种方法

private fun getDeviceLocation() {
        try{
            if(mLocationPermissionGranted){

                mFusedLocationProvider.lastLocation.addOnCompleteListener(this,{task: Task<Location> ->
                    if(task.isSuccessful){
                        var currentLocation: Location? = task.result
                        if(currentLocation!=null){

                            Log.i("Location","Latitude is ${currentLocation.latitude} and Longitude" +
                                    "${currentLocation.longitude}")
                        }

                        else
                            mFusedLocationProvider.requestLocationUpdates(mLocationRequest,mLocationCallback,null)
                    }
                })
            }
        }catch (e:SecurityException){
            Log.e("Error", "Security Exception ${e.message}")
        }
    }

对于常量.kt

class Constant{
    companion object {

        //Location Request Settings
        const val SET_INTERVAL:Long = 2000
        const val NUM_UPDATES:Int = 1

        //Location Permission
        const val FINE_LOCATION:String = android.Manifest.permission.ACCESS_FINE_LOCATION
        const val COARSE_LOCATION:String = android.Manifest.permission.ACCESS_COARSE_LOCATION
    }
}

看到所有答案后,提出问题(最简单、最稳健)。我只点击了图书馆Android ReactiveLocation。

当我制作一个位置跟踪应用程序时。然后我意识到,通过优化电池处理位置跟踪是非常典型的。

所以我想告诉新手和开发者,他们不想在未来的优化中维护他们的位置代码。使用此库。

ReactiveLocationProvider locationProvider = new 

    ReactiveLocationProvider(context);
    locationProvider.getLastKnownLocation()
        .subscribe(new Consumer<Location>() {
            @Override
            public void call(Location location) {
                doSthImportantWithObtainedLocation(location);
            }
        });

要放入应用程序级别build.gradle的依赖项

dependencies {
    ...
    compile 'pl.charmas.android:android-reactive-location2:2.1@aar'
    compile 'com.google.android.gms:play-services-location:11.0.4' //you can use newer GMS version if you need
    compile 'com.google.android.gms:play-services-places:11.0.4'
    compile 'io.reactivex:rxjava:2.0.5' //you can override RxJava version if you need
}

使用此库的优点:

现在和将来都将积极维护这种自由。您不必担心电池优化。因为开发人员已经尽力了。易于安装,放置依赖项和播放。轻松连接到Play Services API获取最后一个已知位置订阅位置更新使用位置设置API管理地理围栏地址列表的地理编码位置活动识别使用当前位置API获取位置自动完成建议

我已经创建了一个小应用程序,并逐步描述以获取当前位置GPS坐标。

以下URL中的完整示例源代码:


获取当前位置坐标,城市名称-在Android中


查看其工作原理:

我们只需要在清单文件中添加此权限<uses permission android:name=“android.permission.ACCESS_FINE_LOCATION”></使用权限>并像这样创建LocationManager实例LocationManager LocationManager=(LocationManager)getSystemService(Context.LOCATION_SERVICE);检查GPS是否已启用然后实现LocationListener和Get CoordinatesLocationListener LocationListener=新的MyLocationListeners();locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,5000,10,locationListener);下面是要做的示例代码


/*----------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) {}
}

使用以下代码,它将提供可用的最佳提供商:

String locCtx = Context.LOCATION_SERVICE; 

LocationManager locationMgr = (LocationManager) ctx.getSystemService(locCtx);

Criteria criteria  = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(true);
criteria.setPowerRequirement(Criteria.POWER_LOW);

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

System.out.println("Best Available provider::::"+provider);