如何在 Android 中像 Google 地图一样获得持续的位置更新?

2024-04-30

我正在构建一个朋友跟踪 Android 应用程序。当我的朋友激活应用程序并带着他的 GPS 和蜂窝数据离开时,我需要在我的设备上跟踪他。这就是这个概念。

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

  1. 有没有其他方法可以持续更新位置?
  2. 如果我需要在设备锁定后继续获取位置而不使用唤醒锁怎么办?

这是我的位置侦听器类:

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

}

This my onCreate() method:

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

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

任何帮助对我来说都是很大的。


Use 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 服务:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Android 中像 Google 地图一样获得持续的位置更新? 的相关文章

  • Android 布局不需要的填充

    所以我有这个布局文件 如下 正如您所看到的 没有填充或边距 dimen xml 文件也没有任何填充 边距 最后 我根本不以编程方式更改布局
  • Mesibo 通话 UI 未更新

    我正在尝试更改 Mesibo Call UI 的配置 但它并没有改变 我尝试如下 MesiboCallConfig mesiboCallConfig new MesiboCallConfig mesiboCallConfig backgro
  • 有没有办法替代Android中的标准Log?

    有没有办法以某种方式拦截对 android 中标准 Log 的调用并执行其他操作 在桌面 Java 中 人们通常会得到一些记录器 因此有多种方法可以安装不同的日志处理程序 实现 但是 Android似乎对Log有静态调用 我找不到任何有关替
  • 错误 libGL.so:无法使用 Android 模拟器打开共享对象文件

    我试图在 Ubuntu 12 04 64 位 中运行 android 模拟器 但是 我收到以下错误 Starting emulator for AVD emulatr Failed to load libGL so error libGL
  • 无法从 com.android.aaptcompiler.ParsedResource@ef79973 提取资源

    无法从 com android aaptcompiler ParsedResource ef79973 提取资源 无法从 com android aaptcompiler ParsedResource 4c95ce87 提取资源 C Use
  • 如何找到特定路线上两点之间的距离?

    我正在为我的大学开发一个 Android 应用程序 可以帮助学生跟踪大学巴士的当前位置 并为他们提供巴士到达他们的预计时间 截至目前 我获取了公交车的当前位置 通过公交车上的设备 和学生的位置 我陷入了必须找到两个 GPS 坐标之间的距离的
  • AOSP 中 android.Build.SERIAL 何时何地生成?

    我知道android Build SERIAL是在第一次设备启动时生成的 但我无法准确定位位置和时间 我正在建造AOSP Jelly Bean Android平板电脑 nosdcard 第二个问题 这个是序列号吗 really对所有人来说都
  • 当编辑文本获得焦点时更改边框颜色

    我想知道当编辑文本聚焦时如何更改它的边框颜色 目前它看起来像这样 我尝试过在SDK中检查源图片 但我无法理解它 我也尝试过使用xml 但无法仅更改边框颜色 如果我找到源图片 我可以在 Photoshop 中编辑以更改颜色 有什么关于如何执行
  • opencv人脸检测示例

    当我在设备上运行应用程序时 应用程序崩溃并显示以下按摩 java lang UnsatisfiedLinkError 无法加载 detector based tracker findLibrary 返回 null 我正在使用 OpenCV
  • Android 性能:SharedPreferences 的成本

    当我的应用程序启动时 我使用分片首选项中的值填充容器类 这个想法是处理 SharedPreferences 和 PreferenceManager 一次 因为我猜它们很重 这是一个示例 SharedPreferences prefs Pre
  • Android 26 (O) 通知不显示操作图标 [重复]

    这个问题在这里已经有答案了 随着 Android 26 O 引入通知渠道 我一直在调查 Google 提供的com example android notificationchannels 这个示例按预期工作 直到我尝试添加Action到示
  • popupBackground 与 Material Design 相关的问题

    我一直致力于将我的应用程序更新为 Material Design 我有一个使用选项卡的应用程序 由于某种原因 每当我使用 android popupBackground 设置下拉菜单颜色时 它就会崩溃 我设置了一个带有选项卡的默认项目并使用
  • Android - 正确使用 invalidateOptionsMenu()

    我一直在寻找很多invalidateOptionsMenu 我知道它的作用 但我想不出这种方法在现实生活中有用的任何例子 我的意思是 例如 假设我们要添加一个新的MenuItem to our ActionBar 我们可以简单地获取菜单on
  • 使用 AndroidX ExifInterface 从图像中检索 GPS EXIF 数据?

    我的目标是 Android 13 并使用新的照片选择器 https developer android com training data storage shared photopicker检索图像 例如 val photoPicker
  • 确定视图是否在屏幕上 - Android

    我对这个有点困惑 首先也是最重要的是 以下链接很有用 但是我提出了一些可见性问题 链接 检查视图可见性 https stackoverflow com questions 4628800 android how to check if a
  • 为什么 ExpandableListView 更改 ChildView 设置(Android)?

    我对使用 ExpandableListView 有疑问 就我而言 我有两个组视图和两个子视图 而子视图由一个带有多个按钮 文本视图等的相对布局组成 例如 当首先扩展第二组并对视图持有者进行一些更改并随后扩展第一组时 先前所做的更改也会自动应
  • 从多个 TextView 中选择文本

    如何在android中从多个文本视图中选择文本 我已经尝试过以下代码 该代码一次仅适用于一个文本视图 我想一次性从许多文本视图中复制文本 android textIsSelectable true 你不能同时这样做 您需要在单个文本视图中设
  • 在上下文操作模式下选择时,ListView 项目不会在视觉上“突出显示”

    我关注了 Android 官方网站创建上下文操作菜单的教程 http developer android com guide topics ui menus html CAB 使用下面的代码 当我长按我的 ListView 项目之一时 它确
  • firebase中按范围查询

    我有一个食品价格范围滑块 根据滑块的最小值和最大值 我想显示此范围内的食品 滑块代码 multiSlider setOnThumbValueChangeListener new MultiSlider SimpleChangeListene
  • 如何让用户在android列表视图中选择主题?

    我有一个带有两个标签的列表视图 标题和副标题 我想要深色和浅色背景作为用户选项 标题具有 textAppearanceMedium 副标题具有 textAppearanceSmall 我希望样式 MyTheme Dark 具有白色文本 My

随机推荐