Пример использования Android LocationServices.GeofencingApi

Кто-нибудь знает пример использования LocationServices.GeofencingApi? Все найденные мной примеры геозон для Android используют устаревший класс LocationClient. Из того, что я вижу, класс LocationServices — это тот, который нужно использовать, но, похоже, нет никаких рабочих примеров того, как его использовать.

Самое близкое, что я нашел, это этот пост с выделением запросы на обновление местоположения

ОБНОВЛЕНИЕ: самый близкий ответ, который я нашел, - это этот пример git, но он по-прежнему использует устаревший LocationClient для запуска ограждений.


person InquisitorJax    schedule 29.10.2014    source источник
comment
вы пробовали в источнике: d.android.com в разделе обучения акроним названия статьи - CaMG   -  person Selvin    schedule 29.10.2014
comment
Конкретная ссылка находится здесь developer.android.com/training/location/geofencing.html, который использует устаревший класс LocationClient — кажется, они еще не обновили документацию   -  person InquisitorJax    schedule 31.10.2014


Ответы (1)


Я только что перенес свой код на новый API. Вот рабочий пример:

Рабочий проект на GitHub, основанный на этом ответе: https://github.com/androidfu/GeofenceExample

Этот вспомогательный класс регистрирует геозоны с помощью API. Я использую интерфейс обратного вызова для связи с вызывающим действием/фрагментом. Вы можете создать обратный вызов, который соответствует вашим потребностям.

public class GeofencingRegisterer implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {
    private Context mContext;
    private GoogleApiClient mGoogleApiClient;
    private List<Geofence> geofencesToAdd;
    private PendingIntent mGeofencePendingIntent;

    private GeofencingRegistererCallbacks mCallback;

    public final String TAG = this.getClass().getName();

    public GeofencingRegisterer(Context context){
        mContext =context;
    }

    public void setGeofencingCallback(GeofencingRegistererCallbacks callback){
        mCallback = callback;
    }

    public void registerGeofences(List<Geofence> geofences){
        geofencesToAdd = geofences;

        mGoogleApiClient = new GoogleApiClient.Builder(mContext)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
        mGoogleApiClient.connect();
    }


    @Override
    public void onConnected(Bundle bundle) {
        if(mCallback != null){
            mCallback.onApiClientConnected();
        }

        mGeofencePendingIntent = createRequestPendingIntent();
        PendingResult<Status> result = LocationServices.GeofencingApi.addGeofences(mGoogleApiClient, geofencesToAdd, mGeofencePendingIntent);
        result.setResultCallback(new ResultCallback<Status>() {
            @Override
            public void onResult(Status status) {
                if (status.isSuccess()) {
                    // Successfully registered
                    if(mCallback != null){
                        mCallback.onGeofencesRegisteredSuccessful();
                    }
                } else if (status.hasResolution()) {
                    // Google provides a way to fix the issue
                    /*
                    status.startResolutionForResult(
                            mContext,     // your current activity used to receive the result
                            RESULT_CODE); // the result code you'll look for in your
                    // onActivityResult method to retry registering
                    */
                } else {
                    // No recovery. Weep softly or inform the user.
                    Log.e(TAG, "Registering failed: " + status.getStatusMessage());
                }
            }
        });
    }

    @Override
    public void onConnectionSuspended(int i) {
        if(mCallback != null){
            mCallback.onApiClientSuspended();
        }

        Log.e(TAG, "onConnectionSuspended: " + i);
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        if(mCallback != null){
            mCallback.onApiClientConnectionFailed(connectionResult);
        }

        Log.e(TAG, "onConnectionFailed: " + connectionResult.getErrorCode());
    }



    /**
     * Returns the current PendingIntent to the caller.
     *
     * @return The PendingIntent used to create the current set of geofences
     */
    public PendingIntent getRequestPendingIntent() {
        return createRequestPendingIntent();
    }

    /**
     * Get a PendingIntent to send with the request to add Geofences. Location
     * Services issues the Intent inside this PendingIntent whenever a geofence
     * transition occurs for the current list of geofences.
     *
     * @return A PendingIntent for the IntentService that handles geofence
     * transitions.
     */
    private PendingIntent createRequestPendingIntent() {
        if (mGeofencePendingIntent != null) {
            return mGeofencePendingIntent;
        } else {
            Intent intent = new Intent(mContext, GeofencingReceiver.class);
            return PendingIntent.getService(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
        }
    }
}

Этот класс является базовым классом для вашего приемника перехода геозоны.

public abstract class ReceiveGeofenceTransitionIntentService extends IntentService {

    /**
     * Sets an identifier for this class' background thread
     */
    public ReceiveGeofenceTransitionIntentService() {
        super("ReceiveGeofenceTransitionIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        GeofencingEvent event = GeofencingEvent.fromIntent(intent);
        if(event != null){

            if(event.hasError()){
                onError(event.getErrorCode());
            } else {
                int transition = event.getGeofenceTransition();
                if(transition == Geofence.GEOFENCE_TRANSITION_ENTER || transition == Geofence.GEOFENCE_TRANSITION_DWELL || transition == Geofence.GEOFENCE_TRANSITION_EXIT){
                    String[] geofenceIds = new String[event.getTriggeringGeofences().size()];
                    for (int index = 0; index < event.getTriggeringGeofences().size(); index++) {
                        geofenceIds[index] = event.getTriggeringGeofences().get(index).getRequestId();
                    }

                    if (transition == Geofence.GEOFENCE_TRANSITION_ENTER || transition == Geofence.GEOFENCE_TRANSITION_DWELL) {
                        onEnteredGeofences(geofenceIds);
                    } else if (transition == Geofence.GEOFENCE_TRANSITION_EXIT) {
                        onExitedGeofences(geofenceIds);
                    }
                }
            }

        }
    }

    protected abstract void onEnteredGeofences(String[] geofenceIds);

    protected abstract void onExitedGeofences(String[] geofenceIds);

    protected abstract void onError(int errorCode);
}

Этот класс реализует абстрактный класс и выполняет всю обработку переходов между геозонами.

public class GeofencingReceiver extends ReceiveGeofenceTransitionIntentService {

    @Override
    protected void onEnteredGeofences(String[] geofenceIds) {
        Log.d(GeofencingReceiver.class.getName(), "onEnter");
    }

    @Override
    protected void onExitedGeofences(String[] geofenceIds) {
        Log.d(GeofencingReceiver.class.getName(), "onExit");
    }

    @Override
    protected void onError(int errorCode) {
        Log.e(GeofencingReceiver.class.getName(), "Error: " + i);
    }
}

И в свой манифест добавьте:

<service
        android:name="**xxxxxxx**.GeofencingReceiver"
        android:exported="true"
        android:label="@string/app_name" >
</service>

Интерфейс обратного вызова

public interface GeofencingRegistererCallbacks {
    public void onApiClientConnected();
    public void onApiClientSuspended();
    public void onApiClientConnectionFailed(ConnectionResult connectionResult);

    public void onGeofencesRegisteredSuccessful();
}
person L93    schedule 14.12.2014
comment
не могли бы вы также предоставить свой обратный звонок? Я новичок в разработке Android, было бы неплохо, если бы вы могли поделиться своим кодом :) спасибо - person BastianW; 17.12.2014
comment
Согласно документам, метод LocationServices.GeofencingApi.addGeofences(GoogleApiClient, List<Geofence>, PendingIntent); также устарел. Вместо этого используйте LocationServices.GeofencingApi.addGeofences(GoogleApiClient, GeofencingRequest, PendingIntent);, создав сначала GeofencingRequest: GeofencingRequest geofenceRequest = new GeofencingRequest.Builder().addGeofences(mGeofencesToAdd).build(); - person Ruben; 23.12.2014
comment
Хорошо, они снова изменили документы. На прошлой неделе это не устарело. - person L93; 23.12.2014
comment
Почему сервис GeofencingReceiver экспортируется? - person Wooff; 12.01.2015
comment
Я не могу этого объяснить, я нашел это в другой документации API геозоны. Возможно, это связано с тем, что служба вызывается структурой сервисов Google Play. - person L93; 12.01.2015
comment
Но IntentService не может работать после его завершения! Что делать, если я хочу, чтобы служба работала бесконечно в фоновом режиме? - person IgorGanapolsky; 28.01.2015
comment
Зачем тебе это? Служба IntentService вызывается каждый раз, когда службы Google Play подтверждают переход через геозону. - person L93; 28.01.2015