java - 如何使用 AlarmReceiver 每 10 分钟 ping 一次 GPS 位置?

标签 java android gps

我真的很抱歉提前,但这个问题很长。

我有一个功能正常的 GPSTracker 类,其中包含对设备的 GPS 位置执行 ping 操作的方法。在我的 MainActivity 中,我有一个按钮,它使用 GPS 跟踪器在 toast 中显示位置。我正在尝试将此按钮转换为自动操作,每 X 分钟重复一次,我们选择 10 分钟。(现在警报接收器设置为 10 秒) 即使应用程序位于后台。因此,我设置了一个 AlarmReceiver 来尝试执行此操作,但我无法完全使其正常工作。

这是我的 GPSTracker 类:

    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 GPSTracker extends Service implements LocationListener {
private final Context context;

boolean isGPSEnabled = false;
boolean canGetLocation = false;
boolean isNetworkEnabled = false;

Location location;

double latitude;
double longitude;

private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10;
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1;

protected LocationManager locationManager;

public GPSTracker(Context context) {
    this.context = context.getApplicationContext();
    getLocation();
}

public Location getLocation(){
    try {
        locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE);

        isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);

        isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        if(!isGPSEnabled && !isNetworkEnabled) {

        }else {
            this.canGetLocation = true;

            if (isNetworkEnabled) {
                locationManager.requestLocationUpdates(
                        LocationManager.NETWORK_PROVIDER,
                        MIN_TIME_BW_UPDATES,
                        MIN_DISTANCE_CHANGE_FOR_UPDATES, this);


                if(locationManager != null){
                    location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

                    if(location !=null){
                        latitude = location.getLatitude();
                        longitude = location.getLongitude();
                    }
                }
            }

            if(isGPSEnabled){
                if(location == null){
                    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

                    if(locationManager !=null){
                        location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);

                        if (location != null){
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                        }
                    }
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

        return location;
}

public void stopUsingGPS() {
    if(locationManager != null){
        locationManager.removeUpdates(GPSTracker.this);
    }
}

public double getLatitude() {
    if(location!= null){
        latitude = location.getLatitude();
    }
    return latitude;
}

public double getLongitude() {
    if(location !=null){
        longitude = location.getLongitude();
    }
    return longitude;
}

public boolean canGetLocation(){
    return this.canGetLocation;
}

public void showSettingsAlert() {
    AlertDialog.Builder alertDialog = new AlertDialog.Builder(context);

    alertDialog.setTitle("GPS is settings");

    alertDialog.setMessage("GPS isn't enabled.  Do you want to go to settings menu?");

    alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            context.startActivity(intent);
        }
    });

    alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {

        @Override
        public void onClick(DialogInterface dialog, int i) {
            dialog.cancel();
        }
    });

    alertDialog.show();
}

@Override
public void onLocationChanged(Location location) {

}

@Override
public void onStatusChanged(String s, int i, Bundle bundle) {

}

@Override
public void onProviderEnabled(String s) {

}

@Override
public void onProviderDisabled(String s) {

}

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

这是我的主要 Activity :

    package com.example.gwyn.locationnabtest;

    import android.app.AlarmManager;
    import android.app.PendingIntent;
    import android.content.BroadcastReceiver;
    import android.content.Context;
import android.content.Intent;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;


public class MainActivity extends ActionBarActivity {

    Button btnShowLocation;
    Button btnStartService;
    Button btnStopService;
    GPSTracker gps;
    //GoogleMap mMap;

    private PendingIntent pendingIntent;
    private AlarmManager manager;



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

        btnShowLocation = (Button) findViewById(R.id.show_location);

        btnShowLocation.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View view) {
                FragmentActivity activity = (FragmentActivity)view.getContext();
                FragmentManager manager = activity.getSupportFragmentManager();
                //MapFragment myMap = (MapFragment) (MainActivity.getFragmentManager()).findFragmentById((R.id.mapFragment));

                // Test, remove me.
               // mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapFragment)).getMap();

                gps = new GPSTracker(MainActivity.this);

                if(gps.canGetLocation()) {
                    // Location Achieved.
                    double latitude = gps.getLatitude();
                    double longitude = gps.getLongitude();

                    // Draw Marker for Current Location on Fragment
                    // Currently Crashing App
                   //  mMap.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude)).title("Marker"));

                    // Toast a popup of the location data.
                    Toast.makeText(getApplicationContext(), "Your Location is -\nLat:" + latitude + "\nLong:" + longitude, Toast.LENGTH_LONG).show();
                } else {
                    gps.showSettingsAlert();
                }
            }
        });

        Intent alarmIntent = new Intent(this, AlarmReceiver.class);
        pendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, 0);





        btnStartService = (Button) findViewById(R.id.start_service);
        btnStartService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                manager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
                int interval = 10000;
                // 10 Second Interval.  Good for testing, but turn this off.
                manager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), interval, pendingIntent);
                Toast.makeText(getApplicationContext(), "Service Started", Toast.LENGTH_SHORT).show();

                //startService(new Intent(getBaseContext(), MyServices.class));
            }
                        });

        btnStopService = (Button) findViewById(R.id.stop_service);
        btnStopService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Cancel pending intents
                manager.cancel(pendingIntent);
                Toast.makeText(getApplicationContext(), "Pending Intents Cancelled", Toast.LENGTH_SHORT).show();
            }
        });
        }

    }

要特别强调的是,这是 MainActivity 中用于显示 GPS 的部分:

public void onClick(View view) {
                FragmentActivity activity = (FragmentActivity)view.getContext();
                FragmentManager manager = activity.getSupportFragmentManager();
                //MapFragment myMap = (MapFragment) (MainActivity.getFragmentManager()).findFragmentById((R.id.mapFragment));

                // Test, remove me.
               // mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.mapFragment)).getMap();

                gps = new GPSTracker(MainActivity.this);

                if(gps.canGetLocation()) {
                    // Location Achieved.
                    double latitude = gps.getLatitude();
                    double longitude = gps.getLongitude();

                    // Draw Marker for Current Location on Fragment
                    // Currently Crashing App
                   //  mMap.addMarker(new MarkerOptions().position(new LatLng(latitude, longitude)).title("Marker"));

                    // Toast a popup of the location data.
                    Toast.makeText(getApplicationContext(), "Your Location is -\nLat:" + latitude + "\nLong:" + longitude, Toast.LENGTH_LONG).show();
                } else {
                    gps.showSettingsAlert();
                }
            }

我的AlarmReceiver如下,在创建GPSTracker时产生错误:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.widget.Toast;


public class AlarmReceiver extends BroadcastReceiver {
    GPSTracker gps;

    @Override
    public void onReceive(Context arg0, Intent arg1) {
       // Here's where we'd grab location and store it into DB.

        //gps = new GPSTracker(AlarmReceiver.this);

       // if(gps.canGetLocation()) {
       //     double latitude = gps.getLatitude();
       //     double longitude = gps.getLongitude();
            // Draw Marker for Current Location on Fragment

            // Toast a popup of the location data.
       //     Toast.makeText(arg0, "Your Location is -\nLat:" + latitude + "\nLong:" + longitude, Toast.LENGTH_LONG).show();
       // } else {
        //    gps.showSettingsAlert();
       // }


        // Toast that the alarm ran.
        Toast.makeText(arg0, "Location Pinged.", Toast.LENGTH_SHORT).show();

    }

更具体地说,问题的一部分是我在这里调用新的 gps Tracker 对象的方式:

//gps = new GPSTracker(AlarmReceiver.this);

我不确定如何在使用警报接收器而不是按钮时实现原始结果,这是我的问题的主要根源。有谁确切知道我可以在这里修改什么以使警报接收器正确使用 GPSTracker 类?

最佳答案

请勿使用 GPSTracker。它有十几个方面的缺陷。忘记它的存在。如果你想要更好的版本,可以使用http://gabesechansoftware.com/location-tracking/该链接还解释了为什么 GPSTracker 在设计上被破坏以及为什么永远不应该使用它。如果在最佳环境下使用,它基本上可以工作,并且在所有其他情况下都会为您提供可怕的数据。

其次,如果您使用的是 GPS 而不是网络 - 您需要给它时间来获取位置同步。这可能需要几秒钟到几分钟(或者几小时,如果用户在地下室或其他地方),因此获取位置的直接形式将不起作用 - 您必须等待它实际同步位置。

我建议您不要寻找库来解决这个问题,而应该真正尝试了解基本 API 的工作原理。在此之前,您使用的任何东西都会遇到麻烦,因为这里有很多极端情况,而且这不是一件小事。

关于java - 如何使用 AlarmReceiver 每 10 分钟 ping 一次 GPS 位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29931980/

相关文章:

java - Hibernate @Lob on byte[] 导致 "Bad value for type long"

java - 获取异常 : selenium. NoSuchSessionException : Session ID is null. 这里我使用 Localthread<webdriver> 进行并行执行

Java - 停止具有共享对象的线程

android - 为什么应用程序服务重启,但无法重启?

java - maven 插件别名是如何映射的

android - Google Play 上是否还使用了特色图片和宣传图片?

android - 什么是 Apache-HttpClient/UNAVAILABLE 错误(Android、Google App Engine)?

android - 在 Activity 之间保持蓝牙连接?

gps - 获取 GPS 定位的合理超时时间是多少?

algorithm - 比较车辆的 "path"(或 GPS 轨迹)