【问题标题】:How to get latitude and longitude of current location in Android?如何在Android中获取当前位置的经纬度?
【发布时间】:2015-02-08 18:03:46
【问题描述】:

我有一个片段,我想在其中显示用户(设备)的当前位置。我使用 Google Map Android API v2。如何获取设备当前的经纬度?

您可以在下面看到我使用的代码。不幸的是,应用程序运行错误,不像我预期的那样。它只显示地图,但没有我设置的标记,也没有当前位置。任何人都可以检查并修复它吗?怎么了?感谢您的帮助!

编辑:

MainFragment.java

public class MainFragment extends Fragment{

    private SupportMapFragment mSupportMapFragment;
    private GoogleMap mGoogleMap;

    public BroadcastReceiver receiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {

        Bundle extras = intent.getExtras();
        LatLng temp = new LatLng(extras.getDouble("Latitude"),extras.getDouble("Longitude"));
    }
    };

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        FragmentManager mFragmentManager = getChildFragmentManager();
        mSupportMapFragment = (SupportMapFragment) mFragmentManager.findFragmentById(R.id.map_container);
        if (mSupportMapFragment == null) {
            mSupportMapFragment = SupportMapFragment.newInstance();
            mFragmentManager.beginTransaction().replace(R.id.map_container, mSupportMapFragment).commit();
        }

        //Broadcast/ Filter
        IntentFilter filter = new IntentFilter();
        filter.addAction(LocationService.BROADCAST_ACTION);
        getActivity().registerReceiver(receiver, filter);
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
           //Start service
           getActivity().startService(new Intent(getActivity(),LocationService.class));
    }

    @Override
    public void onResume(){
         receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            Log.d(TAG, "BroadcastReceiver works!");

            Bundle extras = intent.getExtras();
            final LatLng temp = new LatLng(extras.getDouble("Latitude"),extras.getDouble("Longitude"));

            if (mGoogleMap != null) {
                mGoogleMap = mSupportMapFragment.getMap();
                mGoogleMap.addMarker(new MarkerOptions().position(temp).title("Marker").snippet("Location"));
            }
            try {
                CameraUpdate center = CameraUpdateFactory.newLatLng(temp);
                CameraUpdate zoom = CameraUpdateFactory.zoomTo(15f);
                mGoogleMap.moveCamera(center);
                mGoogleMap.animateCamera(zoom);
            }catch (NumberFormatException e) {
                //Some code here for exception
            }
        }
    };
    }

    @Override
    public void onDetach() {
        super.onDetach();
        try {
            Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
            childFragmentManager.setAccessible(true);
            childFragmentManager.set(this, null);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}

fragment_main.xml

<RelativeLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:id="@+id/map_container">

       <!-- The map fragments will go here -->
</RelativeLayout>

【问题讨论】:

  • 你能添加你的错误日志吗?
  • @Muthu 我在真机上测试过。我测试了我刚刚编写的纬度和经度值并将其缩放,因此在这种情况下它可以工作。我还尝试在具有 Google API 但内存错误的模拟器中进行测试。
  • 你好@Muthu 我编辑了我的帖子。现在我只看到地图,它没有显示标记和当前位置。请你再检查一下帖子的代码并说什么错了吗?谢谢,祝您有愉快的一天!
  • 如果你愿意,我可以分享我的工作位置服务代码。
  • 如果你能给我你的例子@Muthu,我认为这对我很有用。

标签: android google-maps android-fragments google-maps-android-api-2 google-maps-api-2


【解决方案1】:

您的应用可以从融合位置提供程序检索的 Location 对象中提供这些信息以及更多信息:https://developer.android.com/training/location/retrieve-current.html

【讨论】:

  • GoogleApiClient 在 Fragment 中是否可用?事实上,我也尝试使用它,但应用程序也崩溃了。
  • 你好,玛丽安·帕兹奥奇!我在你给我的那个源中的信息的帮助下编辑了我的帖子。现在我只看到地图,它没有显示标记和当前位置。请你再检查一下帖子的代码并说什么错了吗?谢谢,祝您有愉快的一天!
【解决方案2】:

您可以从我当前的项目中尝试一下 -

使用位置管理器获取最后一个已知位置:

public void onLocationChanged(Location location) {
    TextView locationTv = (TextView) findViewById(R.id.latlongLocation);
    double latitude = location.getLatitude();
    double longitude = location.getLongitude();
    LatLng latLng = new LatLng(latitude, longitude);
    googleMap.addMarker(new MarkerOptions().position(latLng));
    googleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
    googleMap.animateCamera(CameraUpdateFactory.zoomTo(21));
    locationTv.setText("Latitude:" + latitude + ", Longitude:" + longitude);
}

我正在调用此方法从我的手机中获取最后一个位置。

【讨论】:

  • 您好!在我的情况下,此代码仅显示地图,但您如何获取设备的当前纬度/经度?
【解决方案3】:

这是我当前的工作代码,它是用于通过广播发送位置的服务。

package maps.custom.com.googlemapsapi;

import android.app.IntentService;
import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.hardware.GeomagneticField;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.Toast;
import android.app.Service;

import com.google.android.gms.maps.model.LatLng;

import java.util.ArrayList;
import java.util.List;
import maps.custom.com.googlemapsapi.support.CNotificationBuilder;

/**
 * Created by hackers on 7/12/14.
 */
public class LocationService extends Service
{
    public static final String BROADCAST_ACTION = "com.location.service.location";
    public static final long DEFAULT_DELAY=1000;
    private static final int TWO_MINUTES = 1000 * 60 * 2;
    public LocationManager locationManager;
    public MyLocationListener listener;
    public Location previousBestLocation = null;

    Intent intent;
    int counter = 0;

    @Override
    public void onCreate()
    {
        super.onCreate();
        Log.i("Service","create");
        intent = new Intent(BROADCAST_ACTION);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("Service","started");
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
        listener = new MyLocationListener();
        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3*DEFAULT_DELAY, 0, listener); //get updates in every 3 seconds
        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 3*DEFAULT_DELAY, 0, listener); //get updates in every 3 seconds
        return super.onStartCommand(intent, flags, startId);
    }



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

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



    @Override
    public void onDestroy() {
        // handler.removeCallbacks(sendUpdatesToUI);
        super.onDestroy();
        Log.v("STOP_SERVICE", "DONE");
        locationManager.removeUpdates(listener);
    }

    public static Thread performOnBackgroundThread(final Runnable runnable) {
        final Thread t = new Thread() {
            @Override
            public void run() {
                try {
                    runnable.run();
                } finally {

                }
            }
        };
        t.start();
        return t;
    }


    GeomagneticField geoField;
    float heading;

    public class MyLocationListener implements LocationListener
    {


        public void onLocationChanged(final Location loc)
        {
            Log.i("**************************************", "Location changed");
            if(isBetterLocation(loc, previousBestLocation)) {
                loc.getLatitude();
                loc.getLongitude();

                intent.putExtra("Latitude", loc.getLatitude());
                intent.putExtra("Longitude", loc.getLongitude());
                intent.putExtra("Provider", loc.getProvider());
                intent.putExtra("Accuracy",  loc.getAccuracy());
                intent.putExtra("Speed",loc.getSpeed());
                sendBroadcast(intent);
        }

        public void onProviderDisabled(String provider)
        {
            Toast.makeText(getApplicationContext(), "Gps Disabled", Toast.LENGTH_SHORT).show();
        }


        public void onProviderEnabled(String provider)
        {
            Toast.makeText( getApplicationContext(), "Gps Enabled", Toast.LENGTH_SHORT).show();
        }


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

        }

    }
}

您需要通过以下代码启动服务

Intent locationservice= new Intent(this,LocationService.class);
startService(locationservice);

接收广播

  BroadcastReceiver receiver = new BroadcastReceiver() {

                @Override
                public void onReceive(Context context, Intent intent) {

                    Bundle extras = intent.getExtras();
                    LatLng temp = new LatLng(extras.getDouble("Latitude"),extras.getDouble("Longitude"));
    }
    }

注册广播接收器。

IntentFilter filter = new IntentFilter();
    filter.addAction(LocationService.BROADCAST_ACTION);
    registerReceiver(receiver, filter); 

不使用时使用服务会消耗电源停止服务。

更新您的代码

public class MainFragment extends Fragment{

    private SupportMapFragment mSupportMapFragment;
    private GoogleMap mGoogleMap;

    public BroadcastReceiver receiver=null;
    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);


    receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

        Bundle extras = intent.getExtras();
        final LatLng temp = new LatLng(extras.getDouble("Latitude"),extras.getDouble("Longitude"));
           if (mGoogleMap != null) {
      mGoogleMap.addMarker(new MarkerOptions().position(temp).title("Marker").snippet("Location"));

        try {
            CameraUpdate center = CameraUpdateFactory.newLatLng(temp);
            CameraUpdate zoom = CameraUpdateFactory.zoomTo(15f);
            mGoogleMap.moveCamera(center);
            mGoogleMap.animateCamera(zoom);
        }catch (NumberFormatException e) {
            //Some code here for exception
        }
           }
    }
    };
        FragmentManager mFragmentManager = getChildFragmentManager();
        mSupportMapFragment = (SupportMapFragment) mFragmentManager.findFragmentById(R.id.map_container);
        if (mSupportMapFragment == null) {
            mSupportMapFragment = SupportMapFragment.newInstance();
            mFragmentManager.beginTransaction().replace(R.id.map_container, mSupportMapFragment).commit();
        }


    }

    @Override
    public void onResume(){
         if (mGoogleMap == null) {
        mGoogleMap = mSupportMapFragment.getMap();
        mGoogleMap.getUiSettings().setMyLocationButtonEnabled(false);
        mGoogleMap.setMyLocationEnabled(true);

    }

        //Broadcast/ Filter
        IntentFilter filter = new IntentFilter();
        filter.addAction(LocationService.BROADCAST_ACTION);
        getActivity().registerReceiver(receiver, filter);
    }

    @Override
    public void onDetach() {
        super.onDetach();
        try {
            Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
            childFragmentManager.setAccessible(true);
            childFragmentManager.set(this, null);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}

【讨论】:

  • 哦,它只是显示地图,什么都没有。太伤心了=(我也尝试了下一个:我认为最好在 onResume 方法中调用接收器并将其删除到该方法但结果相同。你现在有什么想法吗?无论如何谢谢!你花时间给我。
  • 做一件事 你能在 BradCast 接收器中记录纬度和经度吗?如果你得到 lat & lang,我们可以找到其他方法,这意味着服务没有运行,你需要启动服务。
  • 你好穆图!我也想过。是否可以删除 Intent mLocationService= new Intent(this,LocationService.class);启动服务(mLocationService);到 Fragment 原因现在它在我的 MainActivity...
  • @NurzhanNogerbek 运气好吗?
  • 我更新了我的帖子。你能检查一下吗?我删除了 Intent to Fragment 并将 Log.d 添加到 Broadcast。不幸的是,在没有 Google API 的情况下在模拟器中打开了相同的结果和应用程序。这意味着 BroadcastService 不起作用。但为什么? =(
【解决方案4】:

请注意,如果最近获取的位置不可用,getLastKnownLocation 可以返回 null。在尝试提取纬度/经度之前,您应该检查此方法调用的结果。显然,如果结果 null,则请求纬度或经度都会导致 NullPointerException。

【讨论】:

  • 你好!我试图创建单独的服务类并用 LocationListener 实现它,我有你说的这样的想法。纬度/经度的值为0/0。如果你愿意,我可以给你看那门课。你有什么可行的例子吗?
  • 你好@stkent 我在你给我的那个源中的信息的帮助下编辑了我的帖子。现在我只看到地图,它没有显示标记和当前位置。请你再检查一下帖子的代码并说什么错了吗?谢谢,祝您有愉快的一天!
  • 这一行有问题:if(mLocation !=null &amp; mGoogleMap == null){。您不想在每次收到位置更新时都检查 mGoogleMap 是否为空。将其分解为两个单独的 if 语句(首先检查 mGoogleMap)。这有意义吗?
  • 那么如何解决呢?你有什么想法@stkent?
  • 是的,正如我所说,您应该分别检查 mGoogleMap 是否为空,而不是检查 mLocation 是否为空。
猜你喜欢
  • 2013-07-05
  • 2011-08-31
  • 2017-05-09
  • 2012-07-08
  • 2011-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多