zack.yovel.clear.controller.background.UserPresentReceiver.java Source code

Java tutorial

Introduction

Here is the source code for zack.yovel.clear.controller.background.UserPresentReceiver.java

Source

/*
 * Copyright (c) 2014 Yehezkel (Zack) Yovel
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package zack.yovel.clear.controller.background;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Location;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.text.TextUtils;
import android.util.Log;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;

import org.joda.time.DateTime;

import java.io.FileNotFoundException;

import zack.yovel.clear.R;
import zack.yovel.clear.infrastructure.networking.geocoding.GeoCoderTask;
import zack.yovel.clear.infrastructure.networking.geocoding.LatLng;
import zack.yovel.clear.infrastructure.networking.weather.WeatherApiClientFactory;
import zack.yovel.clear.infrastructure.networking.weather.WeatherApiClientInterface;
import zack.yovel.clear.infrastructure.persist.AWeatherPersistAgent;
import zack.yovel.clear.infrastructure.persist.IWeatherPersist;
import zack.yovel.clear.util.Constants;

public class UserPresentReceiver extends BroadcastReceiver implements GooglePlayServicesClient.ConnectionCallbacks,
        GooglePlayServicesClient.OnConnectionFailedListener, LocationListener, GeoCoderTask.OnAddressReady {

    private static final String TAG = "UserPresentReceiver";
    private LocationClient locationClient;
    private Context context;
    private SharedPreferences preferences;
    private boolean locationUpdateRequired;

    @Override
    public void onReceive(Context context, Intent intent) {

        this.context = context;
        initLocationServices();
        preferences = PreferenceManager.getDefaultSharedPreferences(context);

        long lastPersistedWeatherReport = -1;//invalid, will require an update
        try {
            IWeatherPersist weatherReportPersistenceAgent = AWeatherPersistAgent.getInstance();
            lastPersistedWeatherReport = weatherReportPersistenceAgent.getLastReportTime(context);
        } catch (FileNotFoundException e) {
            // do nothing here, the workflow will lead to triggering an update anyway.
        }

        DateTime lastUpdate = new DateTime(lastPersistedWeatherReport);

        if (lastUpdate.plusHours(1).isBeforeNow()) {

            boolean needCurrentLocation = preferences.getBoolean(Constants.Keys.PREF_MY_LOCATION, true);

            if (!needCurrentLocation) {
                String latlng = preferences.getString(Constants.Keys.PREF_LATLNG, null);

                if (null != latlng) {
                    update(context, latlng);
                } else {
                    findCurrentLocation();
                }
            } else {
                findCurrentLocation();
            }
        }
    }

    private void initLocationServices() {
        int available = GooglePlayServicesUtil.isGooglePlayServicesAvailable(context);
        if (available == ConnectionResult.SUCCESS) {
            locationClient = new LocationClient(context, this, this);
            locationClient.connect();
        }
    }

    private void update(Context context, String latlng) {
        WeatherApiClientInterface client = WeatherApiClientFactory.getInstance();
        client.makeAsyncRequest(context, latlng);
    }

    @Override
    public void onConnected(Bundle bundle) {
        if (locationUpdateRequired) {
            requestCurrentLocation();
        }
    }

    private void requestCurrentLocation() {
        Location lastLocation = locationClient.getLastLocation();
        if (lastLocation != null) {
            setNewLocation(lastLocation);
        } else {
            LocationRequest request = LocationRequest.create();
            request.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
            int expirationDuration = 30 * 1000;
            request.setExpirationDuration(expirationDuration);
            request.setInterval(1000);
            request.setNumUpdates(1);
            locationClient.requestLocationUpdates(request, this);
        }
    }

    private void findCurrentLocation() {
        if (locationClient.isConnected()) {
            requestCurrentLocation();
        } else {
            this.locationUpdateRequired = true;
        }
    }

    private void setNewLocation(Location location) {
        String latlng = location.getLatitude() + "," + location.getLongitude();
        update(context, latlng);
        GeoCoderTask geoCoderTask = new GeoCoderTask(context, this);
        geoCoderTask.execute(new LatLng(location));
    }

    @Override
    public void onDisconnected() {
        Log.d(TAG, "Disconnected from location services.");
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.d(TAG, "Connection to location services failed with error code: " + connectionResult.getErrorCode());
    }

    @Override
    public void onLocationChanged(Location location) {
        setNewLocation(location);
    }

    @Override
    public void onAddressReady(String address) {
        if (TextUtils.isEmpty(address)) {
            address = context.getString(R.string.app_name);
        }
        SharedPreferences.Editor editor = preferences.edit();
        editor.putString(Constants.Keys.PREF_LOCATION_NAME, address);
        editor.putBoolean(Constants.Keys.PREF_MY_LOCATION, true);
        editor.commit();
    }
}