com.forrestguice.suntimeswidget.getfix.GetFixHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.forrestguice.suntimeswidget.getfix.GetFixHelper.java

Source

/**
Copyright (C) 2014 Forrest Guice
This file is part of SuntimesWidget.
    
SuntimesWidget is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
SuntimesWidget is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with SuntimesWidget.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.forrestguice.suntimeswidget.getfix;

import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.ContextCompat;
import android.util.Log;

import com.forrestguice.suntimeswidget.R;
import com.forrestguice.suntimeswidget.settings.AppSettings;

import java.util.ArrayList;

/**
 * A helper class that helps to manage a GetFixTask; has methods for starting/stopping the task;
 * allows a single task to run at a time.
 */
public class GetFixHelper {
    public static final String KEY_LOCATION_GETTINGFIX = "gettingfix";
    public static final String KEY_LOCATION_GOTFIX = "gotfix";
    public static final String KEY_LOCATION_UIINDEX = "uiindex";

    public static final String DIALOGTAG_ENABLEGPS = "enablegps";
    public static final String DIALOGTAG_KEEPTRYING = "keeptrying";

    public static final int REQUEST_GETFIX_LOCATION = 1;

    public GetFixTask getFixTask = null;
    public Location fix = null;

    public boolean gettingFix = false;
    public boolean wasGettingFix = false;
    public boolean gotFix = false;

    private FragmentActivity myParent;
    private ArrayList<GetFixUI> uiObj = new ArrayList<GetFixUI>();
    private int uiIndex = 0;

    public GetFixHelper(FragmentActivity parent, GetFixUI ui) {
        myParent = parent;
        addUI(ui);
    }

    /**
     * Get a fix; main entry point for GPS "get fix" button in location settings.
     * Spins up a GetFixTask; allows only one such task to execute at a time.
     */
    public void getFix() {
        if (!gettingFix) {
            if (hasGPSPermissions(myParent, REQUEST_GETFIX_LOCATION)) {
                if (isLocationEnabled()) {
                    SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(myParent);
                    getFixTask = new GetFixTask(myParent, this);

                    int minElapsed = AppSettings.loadPrefGpsMinElapsed(prefs, GetFixTask.MIN_ELAPSED);
                    getFixTask.setMinElapsed(minElapsed);

                    int maxElapsed = AppSettings.loadPrefGpsMaxElapsed(prefs, GetFixTask.MAX_ELAPSED);
                    getFixTask.setMaxElapsed(maxElapsed);

                    int maxAge = AppSettings.loadPrefGpsMaxAge(prefs, GetFixTask.MAX_AGE);
                    getFixTask.setMaxAge(maxAge);

                    //Log.d("GetFixHelper", "MinElapsed: " + minElapsed);
                    //Log.d("GetFixHelper", "MaxElapsed: " + maxElapsed);
                    //Log.d("GetFixHelper", "MaxAge: " + maxAge);

                    getFixTask.addGetFixTaskListeners(listeners);
                    getFixTask.addGetFixTaskListener(new GetFixTask.GetFixTaskListener() {
                        @Override
                        public void onFinished(Location result) {
                            fix = result;
                            gotFix = (fix != null);

                            if (!getFixTask.isCancelled() && !gotFix) {
                                showKeepSearchingPrompt();
                            }
                        }
                    });
                    getFixTask.execute();

                } else {
                    Log.w("GetFixHelper", "getFix called while GPS disabled; showing a prompt");
                    showGPSEnabledPrompt();
                }
            } else {
                Log.w("GetFixHelper", "getFix called without GPS permissions! ignored");
            }
        } else {
            Log.w("GetFixHelper", "getFix called while already running! ignored");
        }
    }

    public void getFix(int i) {
        if (!gettingFix) {
            setUiIndex(i);
            getFix();

        } else {
            Log.w("GetFixHelper", "getFix called while already running! ignored");
        }
    }

    /**
     * Cancel acquiring a location fix (cancels running task(s)).
     */
    public void cancelGetFix() {
        if (gettingFix && getFixTask != null) {
            //Log.d("GetFixHelper", "Canceling getFix");
            getFixTask.cancel(true);
        }
    }

    public boolean hasGPSPermissions(FragmentActivity activity, int requestID) {
        int permission = ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION);
        boolean hasPermission = (permission == PackageManager.PERMISSION_GRANTED);
        //Log.d("hasGPSPermissions", "" + hasPermission);

        if (!hasPermission) {
            ActivityCompat.requestPermissions(activity, new String[] { Manifest.permission.ACCESS_FINE_LOCATION },
                    requestID);
        }

        return hasPermission;
    }

    public boolean isGettingFix() {
        return gettingFix;
    }

    public GetFixUI getUI() {
        return uiObj.get(uiIndex);
    }

    /**
     * @param i the UI index (default 0)
     * @return a GetFixUI instance
     */
    public GetFixUI getUI(int i) {
        if (i >= 0 && i < uiObj.size())
            return uiObj.get(i);
        else
            return uiObj.get(0);
    }

    /**
     * @param ui the ui obj to be added to and managed by the helper
     */
    public void addUI(GetFixUI ui) {
        uiObj.add(ui);
    }

    /**
     * @return the number of ui objects managed by this helper
     */
    public int numUI() {
        return uiObj.size();
    }

    /**
     * @return the index of the ui object currently that is currently set to be used
     */
    public int getUiIndex() {
        return uiIndex;
    }

    /**
     * Set the index of the ui object to use when getting a fix.
     * @param i the ui obj index
     * @return true the index was set, false failed to set
     */
    public boolean setUiIndex(int i) {
        if (uiIndex >= 0 && uiIndex < uiObj.size()) {
            uiIndex = i;
            return true;

        } else {
            Log.w("GetFixHelper", "setUiIndex was called with a negative value! " + i);
            return false;
        }
    }

    private ArrayList<GetFixTask.GetFixTaskListener> listeners = new ArrayList<GetFixTask.GetFixTaskListener>();

    public void addGetFixTaskListener(GetFixTask.GetFixTaskListener listener) {
        if (!listeners.contains(listener)) {
            listeners.add(listener);
            if (getFixTask != null) {
                getFixTask.addGetFixTaskListener(listener);
            }
        }
    }

    public void removeGetFixTaskListener(GetFixTask.GetFixTaskListener listener) {
        listeners.remove(listener);
        if (getFixTask != null) {
            getFixTask.removeGetFixTaskListener(listener);
        }
    }

    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
        case REQUEST_GETFIX_LOCATION:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                getFix();
            }
            break;
        }
    }

    public void loadSettings(Bundle bundle) {
        if (bundle == null)
            return;

        //Log.d("DEBUG", "GetFixHelper loadSettings (bundle)");
        wasGettingFix = bundle.getBoolean(KEY_LOCATION_GETTINGFIX);
        gotFix = bundle.getBoolean(KEY_LOCATION_GOTFIX);
        setUiIndex(bundle.getInt(KEY_LOCATION_UIINDEX));
    }

    public void saveSettings(Bundle bundle) {
        //Log.d("DEBUG", "GetFixHelper saveSettings (bundle)");
        bundle.putBoolean(KEY_LOCATION_GETTINGFIX, gettingFix);
        bundle.putBoolean(KEY_LOCATION_GOTFIX, gotFix);
        bundle.putInt(KEY_LOCATION_UIINDEX, uiIndex);
    }

    public void onResume() {
        //Log.d("DEBUG", "GetFixHelper onResume");
        FragmentManager fragments = myParent.getSupportFragmentManager();

        KeepTryingDialog keepTryingDialog = (KeepTryingDialog) fragments.findFragmentByTag(DIALOGTAG_KEEPTRYING);
        if (keepTryingDialog != null) {
            keepTryingDialog.setHelper(this);
        }

        EnableGPSDialog enableGPSDialog = (EnableGPSDialog) fragments.findFragmentByTag(DIALOGTAG_ENABLEGPS);
        if (enableGPSDialog != null) {
            enableGPSDialog.setHelper(this);
        }

        if (wasGettingFix) {
            Log.w("DEBUG", "GetFixHelper was previously getting fix... restarting");
            getFix();
        }
    }

    /**
     * Keep trying dialog fragment; "No fix found. Keep searching? yes, no"
     */
    public static class KeepTryingDialog extends DialogFragment {
        private GetFixHelper helper;

        public GetFixHelper getHelper() {
            return helper;
        }

        public void setHelper(GetFixHelper helper) {
            this.helper = helper;
        }

        @NonNull
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            final Activity context = getActivity();
            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setMessage(context.getString(R.string.gps_keeptrying_msg)).setCancelable(false)
                    .setPositiveButton(context.getString(R.string.gps_keeptrying_ok),
                            new DialogInterface.OnClickListener() {
                                public void onClick(final DialogInterface dialog, final int id) {
                                    helper.getFix();
                                }
                            })
                    .setNegativeButton(context.getString(R.string.gps_keeptrying_cancel),
                            new DialogInterface.OnClickListener() {
                                public void onClick(final DialogInterface dialog,
                                        @SuppressWarnings("unused") final int id) {
                                    dialog.cancel();
                                }
                            });
            return builder.create();
        }
    }

    public void showKeepSearchingPrompt() {
        final KeepTryingDialog dialog = new KeepTryingDialog();
        dialog.setHelper(this);
        dialog.show(myParent.getSupportFragmentManager(), DIALOGTAG_KEEPTRYING);
    }

    /**
     * Enable GPS alert dialog fragment; "Enable GPS? yes, no"
     */
    public static class EnableGPSDialog extends DialogFragment {
        public EnableGPSDialog() {
        }

        private GetFixHelper helper;

        public void setHelper(GetFixHelper helper) {
            this.helper = helper;
        }

        @NonNull
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            final Activity context = getActivity();
            final AlertDialog.Builder builder = new AlertDialog.Builder(context);
            builder.setMessage(context.getString(R.string.gps_dialog_msg)).setCancelable(false).setPositiveButton(
                    context.getString(R.string.gps_dialog_ok), new DialogInterface.OnClickListener() {
                        public void onClick(final DialogInterface dialog, final int id) {
                            context.startActivity(
                                    new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
                        }
                    }).setNegativeButton(context.getString(R.string.gps_dialog_cancel),
                            new DialogInterface.OnClickListener() {
                                public void onClick(final DialogInterface dialog,
                                        @SuppressWarnings("unused") final int id) {
                                    dialog.cancel();
                                }
                            });
            return builder.create();
        }
    }

    public boolean isLocationEnabled() {
        return isNetProviderEnabled(myParent) || isGPSProviderEnabled(myParent)
                || isPassiveProviderEnabled(myParent);
    }

    public static boolean isGPSProviderEnabled(Context context) {
        LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    }

    public static boolean isNetProviderEnabled(Context context) {
        LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        return locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
    }

    public static boolean isPassiveProviderEnabled(Context context) {
        LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        return locationManager.isProviderEnabled(LocationManager.PASSIVE_PROVIDER);
    }

    public void showGPSEnabledPrompt() {
        final EnableGPSDialog dialog = new EnableGPSDialog();
        dialog.setHelper(this);
        dialog.show(myParent.getSupportFragmentManager(), DIALOGTAG_ENABLEGPS);
    }

}