edu.pdx.cecs.orcycle.MyApplication.java Source code

Java tutorial

Introduction

Here is the source code for edu.pdx.cecs.orcycle.MyApplication.java

Source

/**
 *  ORcycle, Copyright 2014, 2015, PSU Transportation, Technology, and People Lab.
 *
 *  @author Robin Murray <robin5@pdx.edu>    (code)
 *  @author Miguel Figliozzi <figliozzi@pdx.edu> and ORcycle team (general app
 *  design and features, report questionnaires and new ORcycle features)
 *
 *  For more information on the project, go to
 *  http://www.pdx.edu/transportation-lab/orcycle and http://www.pdx.edu/transportation-lab/app-development
 *
 *  Updated/modified for Oregon pilot study and app deployment.
 *
 *  ORcycle 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 any later version.
 *  ORcycle 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
 *  ORcycle. If not, see <http://www.gnu.org/licenses/>.
 *
 */

package edu.pdx.cecs.orcycle;

import java.text.SimpleDateFormat;
import java.util.List;
import java.util.UUID;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.location.Location;
import android.location.LocationManager;
import android.os.Build;
import android.os.IBinder;
import android.support.v4.app.FragmentActivity;
import android.util.Log;

/**
 * This class extends the <code>Application<code/> class, and implements it as a singleton.
 * This class is used to maintain global application state.
 * @author robin5 (Robin Murray)
 * @version 1.0
 * @see <code>Application<code/> class.
 * created 5/22/2014
 */
public class MyApplication extends android.app.Application {

    private final String MODULE_TAG = "MyApplication";

    public static final String PREFS_APPLICATION = "PREFS_APPLICATION";
    public static final String ORCYCLE_URI = "http://www.pdx.edu/transportation-lab/android-instructions";
    public static final String URI_PRIVACY_POLICY = "http://www.pdx.edu/transportation-lab/privacy-policy";
    public static final String URI_REPORT_ROAD_HAZARDS = "http://www.pdx.edu/transportation-lab/reporting-road-hazards";
    public static final String URI_ORCYCLE_MAPS = "http://www.pdx.edu/transportation-lab/orcycle-maps";

    private static final String SETTING_USER_WELCOME_ENABLED = "USER_WELCOME_ENABLED";
    private static final String SETTING_TUTORIAL_ENABLED = "TUTORIAL_ENABLED";
    private static final String SETTING_USER_INFO_UPLOADED = "USER_INFO_UPLOADED";
    private static final String SETTING_FIRST_TRIP_COMPLETED = "SETTING_FIRST_TRIP_COMPLETED";
    private static final String SETTING_HINT_DONT_REPEAT_TRIPS = "SETTING_WARN_REPEAT_TRIPS";
    private static final String SETTING_HINT_DO_REPORT_NOW = "SETTING_HINT_DO_REPORT_NOW";
    private static final String SETTING_HINT_DO_REPORT_LATER = "SETTING_HINT_DO_REPORT_LATER";
    private static final String SETTING_HINT_EMAIL_NAME_AND_NUMBER = "SETTING_HINT_EMAIL_NAME_AND_NUMBER";
    private static final String SETTING_USER_ID = "SETTING_USER_ID";
    private static final String SETTING_FIRST_USE = "SETTING_FIRST_USE";
    private static final String SETTING_SIX_MONTH_ALARM_ENABLED = "SETTING_SIX_MONTH_ALARM_ENABLED";
    private static final double RESET_START_TIME = 0.0;
    private static final String ANDROID_USER = "android";

    private String userId = null;
    private int versionCode;
    private String versionName;
    private String appVersion;
    private String deviceModel;
    private long firstUse = -1;
    private boolean hintDontRepeatTrips;
    private boolean hintDoReportNow;
    private boolean hintDoReportLater;
    private boolean hintEmailNameAndNumber;
    private boolean firstTripCompleted;
    private boolean sixMonthAlarmEnabled;

    private RecordingService recordingService = null;
    private TripData trip;

    private boolean running;

    private boolean checkedForUserProfile = false;
    private boolean userProfileUploaded;

    private boolean checkedForUserWelcome = false;
    private boolean userWelcomeEnabled;

    private boolean checkedForTutorial = false;
    private boolean tutorialEnabled;

    private double lastTripStartTime = RESET_START_TIME;

    /**
    * Reference to class instance
    */
    private static MyApplication myApp = null;

    private static final Controller controller = new Controller();

    /**
     * Returns the class instance of the MyApplication object
     */
    public static MyApplication getInstance() {
        return myApp;
    }

    public Controller getController() {
        return controller;
    }

    // *********************************************************************************
    // *                            Application Interface
    // *********************************************************************************

    /**
     * Called when the application is starting, before any activity, service,
     * or receiver objects (excluding content providers) have been created.
     * @throws java.lang.OutOfMemoryError
     */
    @Override
    public final void onCreate() {
        super.onCreate();

        // Set reference to this instance
        myApp = this;

        ConnectRecordingService();
        loadApplicationSettings();
    }

    private void loadApplicationSettings() {

        //generateUserId();  // For resetting while debugging
        SharedPreferences settings = getSharedPreferences(PREFS_APPLICATION, MODE_PRIVATE);
        userId = settings.getString(SETTING_USER_ID, null);
        if ((null == userId) || (userId.equals(""))) {
            userId = generateUserId();
        }

        firstUse = settings.getLong(SETTING_FIRST_USE, -1);
        if (-1 == firstUse) {
            firstUse = generateFirstUse();
        }

        // setDefaultApplicationSettings();

        firstTripCompleted = settings.getBoolean(SETTING_FIRST_TRIP_COMPLETED, true);

        userProfileUploaded = settings.getBoolean(SETTING_USER_INFO_UPLOADED, false);

        //userWelcomeEnabled = settings.getBoolean(SETTING_USER_WELCOME_ENABLED, true);
        // We are purposely disabling the welcome screen for now
        userWelcomeEnabled = false;

        tutorialEnabled = settings.getBoolean(SETTING_TUTORIAL_ENABLED, true);

        hintDontRepeatTrips = settings.getBoolean(SETTING_HINT_DONT_REPEAT_TRIPS, true);
        hintDoReportNow = settings.getBoolean(SETTING_HINT_DO_REPORT_NOW, true);
        hintDoReportLater = settings.getBoolean(SETTING_HINT_DO_REPORT_LATER, true);
        hintEmailNameAndNumber = settings.getBoolean(SETTING_HINT_EMAIL_NAME_AND_NUMBER, true);

        if (false == (sixMonthAlarmEnabled = settings.getBoolean(SETTING_SIX_MONTH_ALARM_ENABLED, false))) {
            UseReminder.rescheduleAlarm(this.getBaseContext());
            setSixMonthAlarmEnabled(true);
        }

        loadDeviceInfo();
    }

    public void setDefaultApplicationSettings() {
        //setFirstTripCompleted(true); // for debugging
        setFirstTripCompleted(false);
        setUserProfileUploaded(false);
        setUserWelcomeEnabled(false);
        setTutorialEnabled(true);
        setHintDontRepeatTrips(true);
        setHintDoReportNow(true);
        setHintDoReportLater(true);
        setHintEmailNameAndNumber(true);
        setSixMonthAlarmEnabled(false);
    }

    /**
     * This is called when the overall system is running low on memory, and
     * actively running processes should trim their memory usage.
     */
    @Override
    public final void onLowMemory() {
        super.onLowMemory();
    }

    /**
     * Called when the operating system has determined that it is a good
     * time for a process to trim unneeded memory from its process.
     */
    @Override
    public final void onTrimMemory(int level) {
        super.onTrimMemory(level);
    }

    /**
     * Called by the system when the device configuration changes while
     * the component is running.
     */
    @Override
    public final void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }

    // *********************************************************************************
    // *
    // *********************************************************************************

    public boolean isRunning() {
        return this.running;
    }

    public void setRunning(boolean value) {
        running = value;
    }

    // *********************************************************************************
    // *
    // *********************************************************************************

    private boolean isProviderEnabled() {
        final LocationManager manager = (LocationManager) getSystemService(LOCATION_SERVICE);
        return manager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    }

    public ApplicationStatus getStatus() {

        ApplicationStatus applicationStatus = new ApplicationStatus(this.isProviderEnabled(), this.trip);

        return applicationStatus;
    }

    // *********************************************************************************
    // *              RecordingService ServiceConnection Interface
    // *********************************************************************************

    /**
     * Connects the recording service to the Application object
     */
    private void ConnectRecordingService() {

        try {
            Intent intent = new Intent(this, RecordingService.class);
            bindService(intent, recordingServiceServiceConnection, Context.BIND_AUTO_CREATE);
        } catch (SecurityException ex) {
            Log.d(MODULE_TAG, ex.getMessage());
        }
    }

    /**
     * Connection to the RecordingService
     */
    public final ServiceConnection recordingServiceServiceConnection = new ServiceConnection() {

        /**
         * Called when a connection to the Service has been established, with
         * the {@link android.os.IBinder} of the communication channel to the
         * Service.
         *
         * @param name The concrete component name of the service that has
         * been connected.
         *
         * @param service The IBinder of the Service's communication channel,
         * which you can now make calls on.
         */
        public void onServiceConnected(ComponentName name, IBinder service) {

            Log.v(MODULE_TAG, "Connecting to RecordingService");

            if (null == recordingService) {
                recordingService = ((RecordingService.MyServiceBinder) service).getService();
            }
        }

        /**
         * Called when a connection to the Service has been lost. This typically
         * happens when the process hosting the service has crashed or been killed.
         * This does <em>not</em> remove the ServiceConnection itself -- this
         * binding to the service will remain active, and you will receive a call
         * to {@link #onServiceConnected} when the Service is next running.
         *
         * @param name The concrete component name of the service whose
         * connection has been lost.
         */
        public void onServiceDisconnected(ComponentName name) {

            Log.v(MODULE_TAG, "Disconnecting from RecordingService");

            recordingService = null;
        }
    };

    public IRecordService getRecordingService() {
        return recordingService;
    }

    /**
     * startRecording
     */
    public void startRecording(FragmentActivity activity) {

        switch (recordingService.getState()) {

        case RecordingService.STATE_IDLE:
            trip = TripData.createTrip(activity);
            recordingService.startRecording(trip);
            break;

        case RecordingService.STATE_RECORDING:
            long id = recordingService.getCurrentTripID();
            trip = TripData.fetchTrip(activity, id);
            break;
        }

        startRecordingNotification(lastTripStartTime = trip.getStartTime());

        UseReminder.rescheduleAlarm(activity);
        UseReminder.cancelOneWeekAlarm(activity);
    }

    /**
     * finishRecording
     */
    public void finishRecording() {
        recordingService.finishRecording();
        clearRecordingNotifications();
        lastTripStartTime = RESET_START_TIME;
    }

    /**
     * cancelRecording
     */
    public void cancelRecording() {
        recordingService.cancelRecording();
        clearRecordingNotifications();
        lastTripStartTime = RESET_START_TIME;
    }

    public boolean isRecording() {
        if (recordingService == null) {
            return false;
        } else {
            return ((RecordingService.STATE_RECORDING == recordingService.getState())
                    || (RecordingService.STATE_PAUSED == recordingService.getState()));
        }
    }

    // *********************************************************************************
    // *                              UserProfile
    // *********************************************************************************

    public void setCheckedForUserProfile(boolean value) {
        checkedForUserProfile = value;
    }

    public boolean getCheckedForUserProfile() {
        return checkedForUserProfile;
    }

    public void setUserProfileUploaded(boolean value) {
        userProfileUploaded = value;
        SharedPreferences settings;
        settings = getSharedPreferences(PREFS_APPLICATION, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor = settings.edit();
        editor.putBoolean(SETTING_USER_INFO_UPLOADED, userProfileUploaded);
        editor.apply();
    }

    public boolean getUserProfileUploaded() {
        return userProfileUploaded;
    }

    public void setFirstTripCompleted(boolean value) {
        firstTripCompleted = value;
        SharedPreferences settings = getSharedPreferences(PREFS_APPLICATION, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor = settings.edit();
        editor.putBoolean(SETTING_FIRST_TRIP_COMPLETED, firstTripCompleted);
        editor.apply();
    }

    public boolean getFirstTripCompleted() {
        return firstTripCompleted;
    }

    // *********************************************************************************
    // *                                UserWelcome
    // *********************************************************************************

    public void setCheckedForUserWelcome(boolean value) {
        checkedForUserWelcome = value;
    }

    public boolean getCheckedForUserWelcome() {
        return checkedForUserWelcome;
    }

    public void setUserWelcomeEnabled(boolean value) {
        userWelcomeEnabled = value;
        SharedPreferences settings;
        settings = getSharedPreferences(PREFS_APPLICATION, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor = settings.edit();
        editor.putBoolean(SETTING_USER_WELCOME_ENABLED, userWelcomeEnabled);
        editor.apply();
    }

    public boolean getUserWelcomeEnabled() {
        return userWelcomeEnabled;
    }

    // *********************************************************************************
    // *                                HowTo
    // *********************************************************************************

    public void setCheckedForTutorial(boolean value) {
        checkedForTutorial = value;
    }

    public boolean getCheckedForTutorial() {
        return checkedForTutorial;
    }

    public void setTutorialEnabled(boolean value) {
        tutorialEnabled = value;
        SharedPreferences settings;
        settings = getSharedPreferences(PREFS_APPLICATION, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor = settings.edit();
        editor.putBoolean(SETTING_TUTORIAL_ENABLED, tutorialEnabled);
        editor.apply();
    }

    public boolean getTutorialEnabled() {
        return tutorialEnabled;
    }

    public void setSixMonthAlarmEnabled(boolean value) {
        sixMonthAlarmEnabled = value;
        SharedPreferences settings = getSharedPreferences(PREFS_APPLICATION, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor = settings.edit();
        editor.putBoolean(SETTING_SIX_MONTH_ALARM_ENABLED, sixMonthAlarmEnabled);
        editor.apply();
    }

    // *********************************************************************************
    // *                                Hints
    // *********************************************************************************

    public void setHintDontRepeatTrips(boolean value) {
        hintDontRepeatTrips = value;
        SharedPreferences settings = getSharedPreferences(PREFS_APPLICATION, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor = settings.edit();
        editor.putBoolean(SETTING_HINT_DONT_REPEAT_TRIPS, hintDontRepeatTrips);
        editor.apply();
    }

    public boolean getHintDontRepeatTrips() {
        return hintDontRepeatTrips;
    }

    public void setHintDoReportNow(boolean value) {
        hintDoReportNow = value;
        SharedPreferences settings = getSharedPreferences(PREFS_APPLICATION, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor = settings.edit();
        editor.putBoolean(SETTING_HINT_DO_REPORT_NOW, hintDoReportNow);
        editor.apply();
    }

    public boolean getHintDoReportNow() {
        return hintDoReportNow;
    }

    public void setHintDoReportLater(boolean value) {
        hintDoReportLater = value;
        SharedPreferences settings = getSharedPreferences(PREFS_APPLICATION, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor = settings.edit();
        editor.putBoolean(SETTING_HINT_DO_REPORT_LATER, hintDoReportLater);
        editor.apply();
    }

    public boolean getHintDoReportLater() {
        return hintDoReportLater;
    }

    public void setHintEmailNameAndNumber(boolean value) {
        hintEmailNameAndNumber = value;
        SharedPreferences settings = getSharedPreferences(PREFS_APPLICATION, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor = settings.edit();
        editor.putBoolean(SETTING_HINT_EMAIL_NAME_AND_NUMBER, hintEmailNameAndNumber);
        editor.apply();
    }

    public boolean getHintEmailNameAndNumber() {
        return hintEmailNameAndNumber;
    }

    // *********************************************************************************
    // *                                FirstUse
    // *********************************************************************************

    /**
     * Sets SETTING_FIRST_USE, and SETTING_VERSION_CODE settings
     * @return new value of SETTING_FIRST_USE
     */
    private long generateFirstUse() {
        long value = System.currentTimeMillis();
        SharedPreferences settings = getSharedPreferences(PREFS_APPLICATION, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor = settings.edit();
        editor.putLong(SETTING_FIRST_USE, value);
        editor.apply();
        return value;
    }

    public long getFirstUse() {
        return firstUse;
    }

    public String getFirstUseString() {
        return (new SimpleDateFormat("MMMM d, y  h:mm a")).format(firstUse);
    }

    public String getUserId() {
        return userId;
    }

    private String generateUserId() {
        String value = ANDROID_USER + UUID.randomUUID().toString();
        SharedPreferences settings = getSharedPreferences(PREFS_APPLICATION, MODE_PRIVATE);
        SharedPreferences.Editor editor = settings.edit();
        editor = settings.edit();
        editor.putString(SETTING_USER_ID, value);
        editor.apply();
        return value;
    }

    // *********************************************************************************
    // *
    // *********************************************************************************

    public void ResumeNotification() {
        if (isRecording()) {
            startRecordingNotification(lastTripStartTime);
        }
    }

    public void startRecordingNotification(double startTime) {

        // Add the notify bar and blinking light
        MyNotifiers.setRecordingNotification(this);
    }

    public void clearRecordingNotifications() {
        MyNotifiers.cancelRecordingNotification(this.getBaseContext());
    }

    public void clearReminderNotifications() {
        MyNotifiers.cancelReminderNotification(this.getBaseContext());
    }

    // *********************************************************************************
    // *
    // *********************************************************************************

    public Location getLastKnownLocation() {

        LocationManager lm = null;
        List<String> providers = null;
        Location location = null;

        if (null != (lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE))) {
            if (null != (providers = lm.getProviders(true))) {
                /* Loop over the array backwards, and if you get a location, then break out the loop*/
                for (int i = providers.size() - 1; i >= 0; --i) {
                    if (null != (location = lm.getLastKnownLocation(providers.get(i)))) {
                        break;
                    }
                }
            }
        }
        return location;
    }

    private void loadDeviceInfo() {

        // Determine application information
        versionName = "";
        versionCode = 0;
        try {
            Context context = this.getBaseContext();
            PackageInfo pInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
            versionName = pInfo.versionName;
            versionCode = pInfo.versionCode;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        appVersion = versionName + " (" + versionCode + ") on Android " + Build.VERSION.RELEASE;

        // Determine model information
        String manufacturer = Build.MANUFACTURER;
        String model = Build.MODEL;

        if (model.startsWith(manufacturer)) {
            deviceModel = capitalize(model);
        } else {
            deviceModel = capitalize(manufacturer) + " " + model;
        }
    }

    public String getVersionName() {
        return versionName;
    }

    public int getVersionCode() {
        return versionCode;
    }

    public String getAppVersion() {
        return appVersion;
    }

    public String getDeviceModel() {
        return (deviceModel);
    }

    private String capitalize(String s) {
        if (s == null || s.length() == 0) {
            return "";
        }
        char first = s.charAt(0);
        if (Character.isUpperCase(first)) {
            return s;
        } else {
            return Character.toUpperCase(first) + s.substring(1);
        }
    }
}