如何在Android地图中获得连续的位置更新?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在Android地图中获得连续的位置更新?相关的知识,希望对你有一定的参考价值。

我正在建立一个跟踪android应用的朋友。当我的朋友激活应用程序并随着他的GPS和手机数据一起离开时,我需要在我的设备上跟踪他。这就是概念。

我已经实现了LocationListener类,现在我可以从Gps或网络获取最后更新的位置,但除非我启动Google Maps并返回我的应用程序,否则不会更新。在谷歌搜索后,我了解到位置缓存仅由GMaps更新。

  1. 是否有另一种方法可以持续更新位置?
  2. 如果我需要在没有使用Wakelock的情况下锁定设备后继续定位怎么办?

这是我的位置监听器类:

package com.amazinginside;

/** AMAZING LOCATION SUPPORT CLASS, Devoloped By SANGEETH NANDAKUMAR */

import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;

public class AmazingLocation extends Service implements LocationListener

    private final Context mContext;
    boolean isGPSEnabled = false;
    boolean isNetworkEnabled = false;
    boolean canGetLocation = false;

    Location location;
    double latitude=0.0;
    double longitude=0.0;

    //MINIMUM DISTANCE FOR UPDATE (meters)
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 0; // 0 Meters

    //MINIMUM TIME BETWEEN UPDATES
    private static final long MIN_TIME_BW_UPDATES = 1000 * 0; // 0 Seconds

    //LOCATION MANAGER
    protected LocationManager locationManager;

    //CONSTRUCTOR
    public AmazingLocation(Context context)
    
        this.mContext = context;
        getLocation();
    

    //LOCATION PROVISION
    public Location getLocation()
    
        try
        
            //GET LOCATION MANAGER
            locationManager = (LocationManager) mContext.getSystemService(LOCATION_SERVICE);
            //CHECK GPS STATE
            isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
            //CHECK NETWORK STATE
            isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            if (!isGPSEnabled && !isNetworkEnabled)
            
                //NO LOCATION PROVIDERS
            
            else
            
                this.canGetLocation = true;

                /** GET LOCATION FROM NETWORK */
                //FIRST GET LOCATION FROM NETWORK
                if (isNetworkEnabled)
                
                    //REQUEST LOCATION
                    locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    if (locationManager != null)
                    
                        //START WITH LAST KNOWN LOCATION
                        location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        //EXTRACT LOCATION
                        if (location != null)
                        
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                        
                    
                

                /** GET LOCATION FROM GPS SENSOR */
                //THEN GET LOCATION FROM GPS
                if (isGPSEnabled)
                
                    if (location == null)
                    
                        //REQUEST GPS LOCATION
                        locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

                        if (locationManager != null)
                        
                            //EXTRACT LAST KNOWN LOCATION
                            location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            //RETURN LOCATION
                            if (location != null)
                            
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                            
                        
                    
                
            

        
        catch (Exception e)
        
            e.printStackTrace();
        

        return location;
    

    //STOP GPS SENSOR
    public void stopUsingGPS()
    
        if(locationManager != null)
        
            locationManager.removeUpdates(AmazingLocation.this);
        
    

    //EXTRACT LATTITUDE
    public double getLatitude()
    
        if(location != null)
        
            latitude = location.getLatitude();
        

        // return latitude
        return latitude;
    

    //EXTACT LONGITUDE
    public double getLongitude()
    
        if(location != null)
        
            longitude = location.getLongitude();
        

        // return longitude
        return longitude;
    

    //CAN I GET THE LOCATION.?
    public AmazingStatus canGetLocation()
    
        AmazingStatus status=new AmazingStatus();
        if(this.canGetLocation)
        
            status.setStatus(true);
            status.setErrorcode(0);
            status.setErrormsg("Task completed");
        
        else
        
            status.setStatus(false);
            status.setErrorcode(145);
            status.setErrormsg("Please turn on GPS access manually");
        
        return status;
    

    //SHOW LOCATION SETTINGS
    public AmazingStatus showSettingsAlert()
    
        final AmazingStatus status=new AmazingStatus();
        AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);
        alertDialog.setTitle("REQUIRES LOCATION ACCESS");
        alertDialog.setMessage("Please allow GPS access to this app");

        //POSSITIVE REPLY
        alertDialog.setPositiveButton("Allow", new DialogInterface.OnClickListener()
        
            public void onClick(DialogInterface dialog,int which)
            
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                mContext.startActivity(intent);
                status.setStatus(true);
                status.setErrorcode(0);
                status.setErrormsg("Task completed");
            
        );

        //NEGATIVE REPLY
        alertDialog.setNegativeButton("Deny", new DialogInterface.OnClickListener()
        
            public void onClick(DialogInterface dialog, int which)
            
                status.setStatus(false);
                status.setErrorcode(408);
                status.setErrormsg("User denied permission");
                dialog.cancel();
            
        );

        // Showing Alert Message
        alertDialog.show();
        return status;
    

    //UNUSED OVERRIDE METHORDS...
    @Override
    public void onLocationChanged(Location location)
    
        getLocation();
    

    @Override
    public void onProviderDisabled(String provider)
    
    

    @Override
    public void onProviderEnabled(String provider)
    
        getLocation();
    

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras)
    
        getLocation();
    

    @Override
    public IBinder onBind(Intent arg0)
    
        return null;
    


这是我的onCreate()方法:

@Override protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //CREATE A BUTTON HANDLER
    Button start_btn=(Button)findViewById(R.id.start_location_streaming);
    //ON BUTTON CLICK EVENT
    start_btn.setOnClickListener(new View.OnClickListener()
    
        @Override
        public void onClick(View v)
        
            //REPEAT A METHORD AT SPECIFIC INTERVALS
            Timer myTimer = new Timer();
            myTimer.schedule(new TimerTask()
            
                @Override
                public void run()
                
                    TimerMethod();
                

            , 0, 8000);
        
    );  

这些是其他方法:

private void TimerMethod()

    //START METHORD
    this.runOnUiThread(Timer_Tick);


//LOCATION REPORTING METHORD
private Runnable Timer_Tick = new Runnable()

    public void run()
    
        Toast.makeText(MainActivity.this, "Current latitude : "+Double.toString(getLocation().latitude), Toast.LENGTH_SHORT).show();
        Toast.makeText(MainActivity.this, "Current longitude : "+Double.toString(getLocation().longitude), Toast.LENGTH_SHORT).show();
    
;

private LatLng getLocation()

    //CREATE A LOCATION CLASS INSTANCE
    AmazingLocation gps = new AmazingLocation(this);
    //RETRIVE LOCATION
    double latitude = gps.getLatitude();
    double longitude = gps.getLongitude();
    //RETURN LOCATION
    LatLng loc=new LatLng(latitude,longitude);
    return loc;
  

现在的问题是,吐司只是显示以前知道的位置而不是更新,除非我打开谷歌地图并返回。

任何帮助对我来说都很棒。

答案

在Android中使用融合位置提供程序设置您的间隔:

举个例子,像这样创建你的活动:

public class LocationActivity extends Activity implements
        LocationListener,
        GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener 

    private static final String TAG = "LocationActivity";
    private static final long INTERVAL = 1000 * 10;
    private static final long FASTEST_INTERVAL = 1000 * 5;
    Button btnFusedLocation;
    TextView tvLocation;
    LocationRequest mLocationRequest;
    GoogleApiClient mGoogleApiClient;
    Location mCurrentLocation;
    String mLastUpdateTime;

    protected void createLocationRequest() 
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(INTERVAL);
        mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate ...............................");
        //show error dialog if GoolglePlayServices not available
        if (!isGooglePlayServicesAvailable()) 
            finish();
        
        createLocationRequest();
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

        setContentView(R.layout.activity_main);
        tvLocation = (TextView) findViewById(R.id.tvLocation);

        btnFusedLocation = (Button) findViewById(R.id.btnShowLocation);
        btnFusedLocation.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View arg0) 
                updateUI();
            
        );

    

    @Override
    public void onStart() 
        super.onStart();
        if (mGoogleApiClient.isConnected()) 
            startLocationUpdates();
            Log.d(TAG, "Location update resumed .....................");
        
    

    @Override
    public void onStop() 
        super.onStop();
        Log.d(TAG, "onStop fired ..............");
        mGoogleApiClient.disconnect();
        Log.d(TAG, "isConnected ...............: " + mGoogleApiClient.isConnected());
    

    private boolean isGooglePlayServicesAvailable() 
        int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
        if (ConnectionResult.SUCCESS == status) 
            return true;
         else 
            GooglePlayServicesUtil.getErrorDialog(status, this, 0).show();
            return false;
        
    

    @Override
    public void onConnected(Bundle bundle) 
        Log.d(TAG, "onConnected - isConnected ...............: " + mGoogleApiClient.isConnected());
        startLocationUpdates();
    

    protected void startLocationUpdates() 
        PendingResult<Status> pendingResult = LocationServices.FusedLocationApi.requestLocationUpdates(
                mGoogleApiClient, mLocationRequest, this);
        Log.d(TAG, "Location update started ..............: ");
    

    @Override
    public void onConnectionSuspended(int i) 

    

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) 
        Log.d(TAG, "Connection failed: " + connectionResult.toString());
    

    @Override
    public void onLocationChanged(Location location) 
        Log.d(TAG, "Firing onLocationChanged..............................................");
        mCurrentLocation = location;
        mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
        updateUI();
    

    private void updateUI() 
        Log.d(TAG, "UI update initiated .............");
        if (null != mCurrentLocation) 
            String lat = String.valueOf(mCurrentLocation.getLatitude());
            String lng = String.valueOf(mCurrentLocation.getLongitude());
            tvLocation.setText("At Time: " + mLastUpdateTime + "\n" +
                    "Latitude: " + lat + "\n" +
                    "Longitude: " + lng + "\n" +
                    "Accuracy: " + mCurrentLocation.getAccuracy() + "\n" +
                    "Provider: " + mCurrentLocation.getProvider());
         else 
            Log.d(TAG, "location is null ...............");
        
    

    @Override
    protected void onPause() 
        super.onPause();
        stopLocationUpdates();
    

    protected void stopLocationUpdates() 
        LocationServices.FusedLocationApi.removeLocationUpdates(
                mGoogleApiClient, this);
        Log.d(TAG, "Location update stopped .......................");
    

    @Override
    public void onResume() 
        super.onResume();
        if (mGoogleApiClient.isConnected()) 
            startLocationUpdates();
            Log.d(TAG, "Location update resumed .....................");
        
    

需要Google Play服务:

另一答案

我相信,不是重新发明轮子,你可以使用易于实现的第三方库之一,在这种情况下,电池效率。我发现的其中一个图书馆是SmartLocation。您可以在build.gradle(app)中添加以下依赖项以开始使用该库。

compile 'io.nlopez.smartlocation:library:3.2.9'

添加依赖项后,您应该重建项目以获取引用。

例如,您可以在Activity中尝试以下代码。

Button start_btn=(Button)findViewById(R.id.start_location_streaming);

Context context = start_btn.getContext();

Handler handler = new Handler();

start_btn.setOnClickListener(new View.OnClickListener() 
    @Override
    public void onClick(View v) 
        SmartLocation.with(context).location().start(locationListener);
    
);

OnLocationUpdatedListener locationListener = new OnLocationUpdatedListener(
    @Override
    public void onLocationUpdated(Location location) 
        double lat = location.getLatitude();
        double lng = location.getLongitude();
        handler.postDelayed(locationRunnable,8000);
    
);

Runnable locationRunnable = new Runnable(
    @Override
    public void run() 
        SmartLocation.with(context).location().start(locationListener);
    
);

您可以在onStop()方法中停止位置跟踪

@Override
public void onStop() 
    SmartLocation.with(context).location().stop();
    super.onStop();

SmartLocation库将为您提供超出预期的功能,只需尝试一次。

注意:确保您的应用程序具有ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION(两者)以获得准确的结果。不要忘记在Android 6.0及更高版本的运行时请求权限。

另一答案

您应该使用Android服务,而不是应用程序本身。这样,您将在后台连续运行代码,即使应用程序关闭,您也会收到该位置。

https://www.tutorialspoint.com/android/android_services.htm

另一答案

这个库可能会派上用场。它具有您需要为位置更新执行的所有操作,例如请求权限和设置间隔时间。

https://github.com/bikcrum/LocationUpdate

以上是关于如何在Android地图中获得连续的位置更新?的主要内容,如果未能解决你的问题,请参考以下文章

android-如何在不打开地图/导航应用程序的情况下更新位置

如何在同一项目中获得连续的位置(纬度和经度)以及位置地址?

如何在谷歌地图android中显示当前位置的平滑移动

如何连续计算位置更新之间的距离以获得总距离

Android怎么实现点击按钮获取当前位置的信息,没有地图的情况下。

如何从后台服务android更新谷歌地图v2位置