首页 > 解决方案 > 地理围栏服务

问题描述

我正在尝试提供一项服务,将设备的位置插入数据库中,并且当设备位于地理围栏列表之外时,它会向服务器发送另一条消息。现在我只有服务将位置发送到服务器的部分。

这是我所拥有的:

public class UbicacionEmisor extends Service {

    private static final String TAG = "BOOMBOOMTESTGPS";
    private LocationManager mLocationManager = null;
    private static final int LOCATION_INTERVAL = 10000;
    private static final float LOCATION_DISTANCE = 0;
    private SOService mService;
    SharedPreferences preferences;
    SharedPreferences.Editor editor;
    private static final String PREF_NAME = "decaught-preferences";
    private List<GeofenceR> geofenceRList = new ArrayList<>();


    private class LocationListener implements android.location.LocationListener {
        Location mLastLocation;

        public LocationListener(String provider) {
            Log.e(TAG, "LocationListener " + provider);
            mLastLocation = new Location(provider);
        }

        @Override
        public void onLocationChanged(Location location) {
            Log.e(TAG, "onLocationChanged: " + location);
            mLastLocation.set(location);

            SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
            String date = f.format(new Date());

            editor.putString("latitude",  String.valueOf(location.getLatitude()));
            editor.putString("longitude",  String.valueOf(location.getLongitude()));
            editor.apply();
            //This part is used to send to the server the Location
            mService.add_location("Token " + preferences.getString("token", ""), preferences.getString("imei",""), date, String.valueOf(location.getLatitude()), String.valueOf(location.getLongitude()), true).enqueue(new Callback<escoladeltreball.org.decaught.models.Location>() {

                @Override
                public void onResponse(Call<escoladeltreball.org.decaught.models.Location> call, Response<escoladeltreball.org.decaught.models.Location> response) {
                    if (response.isSuccessful()) {
                        Log.d("UbicationEmisor", "Ubication send");
                    } else {
                        int statusCode = response.code();
                        if (response.code() == 400) {
                            try {
                                Log.v("Error code 400", response.errorBody().string());
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                        Log.d("UbicationEmisor", "Ubication not send, error: " + statusCode);
                        Log.d("UbicationEmisor", "Ubication not send, error: " + response.errorBody());

                        // handle request errors depending on status code
                    }
                }

                @Override
                public void onFailure(Call<escoladeltreball.org.decaught.models.Location> call, Throwable t) {

                    Log.d("RolSelectionActivity", "Error trying to connect to database");

                }
            });

        }

        @Override
        public void onProviderDisabled(String provider) {
            Log.e(TAG, "onProviderDisabled: " + provider);
        }

        @Override
        public void onProviderEnabled(String provider) {
            Log.e(TAG, "onProviderEnabled: " + provider);
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            Log.e(TAG, "onStatusChanged: " + provider);
        }
    }

    LocationListener[] mLocationListeners = new LocationListener[]{
            new LocationListener(LocationManager.GPS_PROVIDER),
            new LocationListener(LocationManager.NETWORK_PROVIDER)
    };

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand");
        super.onStartCommand(intent, flags, startId);
        preferences = getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
        editor = preferences.edit();


        return START_STICKY;
    }

    @Override
    public void onCreate() {
        Log.e(TAG, "onCreate");
        mService = ApiUtils.getSOService();
        obtainGeofences();
        initializeLocationManager();
        try {
            mLocationManager.requestLocationUpdates(
                    LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
                    mLocationListeners[1]);
        } catch (java.lang.SecurityException ex) {
            Log.i(TAG, "fail to request location update, ignore", ex);
        } catch (IllegalArgumentException ex) {
            Log.d(TAG, "network provider does not exist, " + ex.getMessage());
        }
        try {
            mLocationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
                    mLocationListeners[0]);
        } catch (java.lang.SecurityException ex) {
            Log.i(TAG, "fail to request location update, ignore", ex);
        } catch (IllegalArgumentException ex) {
            Log.d(TAG, "gps provider does not exist " + ex.getMessage());
        }
    }

    private void obtainGeofences() {
        String imei = preferences.getString("imei","");


        mService.listGeofence("Token " + preferences.getString("token", ""), imei).enqueue(new Callback<List<GeofenceR>>() {
            @Override
            public void onResponse(Call<List<GeofenceR>> call, Response<List<GeofenceR>> response) {
               geofenceRList = response.body();
            }

            @Override
            public void onFailure(Call<List<GeofenceR>> call, Throwable t) {

            }
        });
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy");
        super.onDestroy();
        if (mLocationManager != null) {
            for (int i = 0; i < mLocationListeners.length; i++) {
                try {
                    mLocationManager.removeUpdates(mLocationListeners[i]);
                } catch (Exception ex) {
                    Log.i(TAG, "fail to remove location listners, ignore", ex);
                }
            }
        }
    }

    private void initializeLocationManager() {
        Log.e(TAG, "initializeLocationManager");
        if (mLocationManager == null) {
            mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
        }
    }
}

知道如何制作地理围栏部分吗?还是我应该重新开始?

标签: androidgeofencing

解决方案


我使用过地理围栏,我真的建议你阅读这个地理围栏文档和这个例子

关于您的问题,我建议您重新开始,因为地理围栏不使用 LocationManager(或至少不明确)。

您想做类似(步骤列表)的事情:

定义地理围栏 lng/lat 和半径并分配退出事件

mGeofenceList.add(new Geofence.Builder()
    // Set the request ID of the geofence. This is a string to identify this
    // geofence.
    .setRequestId(entry.getKey())

    .setCircularRegion(
            entry.getValue().latitude,
            entry.getValue().longitude,
            Constants.GEOFENCE_RADIUS_IN_METERS
    )
    .setExpirationDuration(Constants.GEOFENCE_EXPIRATION_IN_MILLISECONDS)
    .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_EXIT)
    .build());

定义待定意图

 public class MainActivity extends AppCompatActivity {

        // ...

        private PendingIntent getGeofencePendingIntent() {
            // Reuse the PendingIntent if we already have it.
            if (mGeofencePendingIntent != null) {
                return mGeofencePendingIntent;
            }
            Intent intent = new Intent(this, GeofenceTransitionsIntentService.class);
            // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when
            // calling addGeofences() and removeGeofences().
            mGeofencePendingIntent = PendingIntent.getService(this, 0, intent, PendingIntent.
                    FLAG_UPDATE_CURRENT);
            return mGeofencePendingIntent;
        }

**Define the Service**

public class GeofenceTransitionsIntentService extends IntentService {
    // ...
    protected void onHandleIntent(Intent intent) {
        GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent);
        if (geofencingEvent.hasError()) {
            String errorMessage = GeofenceErrorMessages.getErrorString(this,
                    geofencingEvent.getErrorCode());
            Log.e(TAG, errorMessage);
            return;
        }

        // Get the transition type.
        int geofenceTransition = geofencingEvent.getGeofenceTransition();

        // Test that the reported transition was of interest.
        if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT) {

            // Get the geofences that were triggered. A single event can trigger
            // multiple geofences.


            // HERE YOUR CODE TO SAVE THE LOCATION IN THE DB
            // AND SEND THE NOTIFICATION 

            sendNotification(geofenceTransitionDetails);
            Log.i(TAG, geofenceTransitionDetails);
        } else {
            // Log the error.
            Log.e(TAG, getString(R.string.geofence_transition_invalid_type,
                    geofenceTransition));
        }
    }

注意

使用地理围栏最烦人的事情是打瞌睡。一段时间后,您将不会再看到任何通知,因为 Doze 会停止它以节省电池,因此请记住这一点。在开始打瞌睡之前,请务必阅读此内容。

享受 =)


推荐阅读