edu.princeton.jrpalmer.asmlibrary.Settings.java Source code

Java tutorial

Introduction

Here is the source code for edu.princeton.jrpalmer.asmlibrary.Settings.java

Source

/*
 * Space Mapper
 * Copyright (C) 2012, 2013 John R.B. Palmer
 * Contact: jrpalmer@princeton.edu
 * 
 * This file is part of Space Mapper.
 * 
 * Space Mapper 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.
 * 
 * Space Mapper 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 Space Mapper.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * This file incorporates code written by Chang Y. Chung, Necati E. Ozgencil, 
 * and Kathleen Li for the Human Mobility Project, which is subject to the 
 * following terms: 
 * 
 *       Copyright (C) 2010, 2011 Human Mobility Project
 *
 *      Permission is hereby granted, free of charge, to any person obtaining 
 *      a copy of this software and associated documentation files (the
 *      "Software"), to deal in the Software without restriction, including
 *      without limitation the rights to use, copy, modify, merge, publish, 
 *      distribute, sublicense, and/or sell copies of the Software, and to
 *      permit persons to whom the Software is furnished to do so, subject to
 *      the following conditions:
 *
 *      The above copyright notice and this permission notice shall be included
 *      in all copies or substantial portions of the Software.
 *
 *      THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *      EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *      MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *      IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 *      CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 *      TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 *      SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 
 */

package edu.princeton.jrpalmer.asmlibrary;

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.ColorStateList;
import android.database.Cursor;
import android.graphics.Color;
import android.location.LocationManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.text.SpannableString;
import android.text.util.Linkify;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Chronometer;
import android.widget.DatePicker;
import android.widget.ImageButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.ToggleButton;
import edu.princeton.jrpalmer.asmlibrary.Upload.Uploads;

/**
 * Allows user to change the app settings.
 * 
 * @author John R.B. Palmer
 * 
 */
public class Settings extends FragmentActivity {

    // private static final String TAG = "Settings";

    private Chronometer participationTimeText;
    private TextView nUploadsText;

    ColorStateList oldColors;
    private TextView mServiceMessage;
    private ToggleButton mServiceButton;
    private Spinner mIntervalSpinner;
    private Spinner mStorageSpinner;
    private RadioGroup mShareDataRadioGroup;
    private RadioGroup mToggleSatRadioGroup;
    private RadioGroup mToggleIconsRadioGroup;
    private RadioGroup mToggleAccRadioGroup;
    private RadioGroup mLimitStartDateRadioGroup;
    private RadioGroup mLimitEndDateRadioGroup;

    private static Button mStartDateButton;
    private static Button mEndDateButton;

    private int MIN_STORAGE = 0;
    private int MAX_STORAGE = 365;

    private TextView mStorageHeading;
    private TextView mStorageText;

    private TextView mIntervalHeading;
    private TextView mIntervalText;

    private TextView mStorageSizePendingUploadsText;
    private TextView mStorageSizeUserDbText;
    private ImageButton deletePendingUploadsButton;
    private ImageButton deleteUserDbButton;
    private ImageButton uploadButton;

    TextView participationLabel;
    TextView pendingUploadsLabel;

    private boolean storeMyData;
    private boolean shareMyData;

    static int storageDays;
    static Date savedStartDate;
    static Date savedEndDate;
    static Context context;

    UploadReceiver uploadReceiver;
    FixReceiver fixReceiver;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        context = getApplicationContext();
        PropertyHolder.init(context);

        storeMyData = PropertyHolder.getStoreMyData();

        setContentView(R.layout.settings);

        // views
        mServiceButton = (ToggleButton) findViewById(R.id.service_button);
        mServiceMessage = (TextView) findViewById(R.id.service_message);
        mIntervalSpinner = (Spinner) findViewById(R.id.spinner_interval);

        mStorageHeading = (TextView) findViewById(R.id.storageHeading);
        mStorageText = (TextView) findViewById(R.id.storageText);
        mIntervalHeading = (TextView) findViewById(R.id.intervalHeading);
        mIntervalText = (TextView) findViewById(R.id.intervalText);

        participationLabel = (TextView) findViewById(R.id.participationHeading);
        pendingUploadsLabel = (TextView) findViewById(R.id.pendingUploadsHeading);

        mStorageSizePendingUploadsText = (TextView) findViewById(R.id.storageSizePendingUploadsText);
        mStorageSizeUserDbText = (TextView) findViewById(R.id.storageSizeUserDbText);

        participationTimeText = (Chronometer) findViewById(R.id.participationTimeText);
        nUploadsText = (TextView) findViewById(R.id.nUploadsText);

        mStorageSpinner = (Spinner) findViewById(R.id.spinner_mydata);
        ArrayAdapter<CharSequence> sAdapter = new ArrayAdapter<CharSequence>(this,
                android.R.layout.simple_spinner_item);
        sAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        for (int i = MIN_STORAGE; i <= MAX_STORAGE; i++) {
            sAdapter.add(" " + Integer.toString(i));
        }

        mStorageSpinner.setAdapter(sAdapter);

        mShareDataRadioGroup = (RadioGroup) findViewById(R.id.sharedataRadioGroup);

        deletePendingUploadsButton = (ImageButton) findViewById(R.id.deletePendingUploadsButton);

        uploadButton = (ImageButton) findViewById(R.id.uploadButton);

        oldColors = mStorageText.getTextColors();

    }

    @Override
    protected void onResume() {

        if (Util.trafficCop(this))
            finish();
        IntentFilter uploadFilter;
        uploadFilter = new IntentFilter(
                getResources().getString(R.string.internal_message_id) + Util.MESSAGE_FIX_UPLOADED);
        uploadReceiver = new UploadReceiver();
        registerReceiver(uploadReceiver, uploadFilter);

        IntentFilter fixFilter;
        fixFilter = new IntentFilter(
                getResources().getString(R.string.internal_message_id) + Util.MESSAGE_FIX_RECORDED);
        fixReceiver = new FixReceiver();
        registerReceiver(fixReceiver, fixFilter);

        shareMyData = PropertyHolder.getShareData();

        toggleParticipationViews(shareMyData);

        int nUploads = PropertyHolder.getNUploads();

        final long participationTime = PropertyHolder.ptCheck();
        participationTimeText.setBase(SystemClock.elapsedRealtime() - participationTime);

        // service button
        boolean isServiceOn = PropertyHolder.isServiceOn();

        mServiceButton.setChecked(isServiceOn);
        mServiceButton.setOnClickListener(new ToggleButton.OnClickListener() {
            public void onClick(View view) {
                if (view.getId() != R.id.service_button)
                    return;
                Context context = view.getContext();
                boolean on = ((ToggleButton) view).isChecked();
                String schedule = on ? Util.MESSAGE_SCHEDULE : Util.MESSAGE_UNSCHEDULE;
                // Log.e(TAG, schedule + on);

                // now schedule or unschedule
                Intent intent = new Intent(getString(R.string.internal_message_id) + schedule);
                context.sendBroadcast(intent);
                showSpinner(on, storeMyData);

                if (on && shareMyData) {
                    final long ptNow = PropertyHolder.ptStart();
                    participationTimeText.setBase(SystemClock.elapsedRealtime() - ptNow);
                    participationTimeText.start();

                    ContentResolver ucr = getContentResolver();

                    ucr.insert(Util.getUploadQueueUri(context), UploadContentValues.createUpload("ONF",
                            "on," + Util.iso8601(System.currentTimeMillis()) + "," + ptNow));
                } else {

                    final long ptNow = PropertyHolder.ptStop();
                    participationTimeText.setBase(SystemClock.elapsedRealtime() - ptNow);
                    participationTimeText.stop();
                    // stop uploader
                    Intent stopUploaderIntent = new Intent(Settings.this, FileUploader.class);
                    // Stop service if it is currently running
                    stopService(stopUploaderIntent);

                    if (shareMyData) {

                        ContentResolver ucr = getContentResolver();

                        ucr.insert(Util.getUploadQueueUri(context), UploadContentValues.createUpload("ONF",
                                "off," + Util.iso8601(System.currentTimeMillis()) + "," + ptNow));

                    }

                }
                // If user turns CountdownDisplay on but GPS is not on, remind
                // user to turn
                // GPS on
                if (on) {
                    final LocationManager manager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

                    if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                        if (!manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
                            buildAlertMessageNoGpsNoNet();
                        } else
                            buildAlertMessageNoGps();
                    }
                }

                return;
            }
        });

        // interval spinner
        int intspinner_item = android.R.layout.simple_spinner_item;
        int dropdown_item = android.R.layout.simple_spinner_dropdown_item;
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.interval_array,
                intspinner_item);
        adapter.setDropDownViewResource(dropdown_item);
        mIntervalSpinner.setAdapter(adapter);
        mIntervalSpinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
            public void onItemSelected(AdapterView<?> parent, View v, int pos, long id) {
                int parentId = parent.getId();
                if (parentId != R.id.spinner_interval)
                    return;
                if (pos > mInterval.length)
                    return;
                if (!PropertyHolder.isServiceOn()) {
                    PropertyHolder.setAlarmInterval(mInterval[pos]);
                    return;
                }
                PropertyHolder.setAlarmInterval(mInterval[pos]);
                mServiceButton.setChecked(true);

                Intent intent = new Intent(getString(R.string.internal_message_id) + Util.MESSAGE_SCHEDULE);
                Context context = getApplicationContext();
                context.sendBroadcast(intent);
                showSpinner(true, storeMyData);

                if (shareMyData) {
                    ContentResolver ucr = getContentResolver();

                    ucr.insert(Util.getUploadQueueUri(context), UploadContentValues.createUpload("INT",
                            Util.iso8601(System.currentTimeMillis()) + "," + mInterval[pos]));
                }
            }

            public void onNothingSelected(AdapterView<?> parent) {
                // do nothing
            }
        });
        int pos = ai2pos(PropertyHolder.getAlarmInterval());
        mIntervalSpinner.setSelection(pos);
        showSpinner(isServiceOn, storeMyData);

        // mydata buttons

        // storage spinner

        storageDays = PropertyHolder.getStorageDays();

        mStorageSpinner.setOnItemSelectedListener(new Spinner.OnItemSelectedListener() {
            public void onItemSelected(AdapterView<?> parent, View v, int pos, long id) {
                int parentId = parent.getId();
                if (parentId != R.id.spinner_mydata)
                    return;
                if (pos > MAX_STORAGE - MIN_STORAGE)
                    return;
                PropertyHolder.setStorageDays(pos + MIN_STORAGE);
                PropertyHolder.setStoreMyData((pos + MIN_STORAGE) > 0);
            }

            public void onNothingSelected(AdapterView<?> parent) {
                // do nothing
            }
        });
        int storagepos = storageDays - MIN_STORAGE;
        mStorageSpinner.setSelection(storagepos);

        // NEW STUFF
        mToggleSatRadioGroup = (RadioGroup) findViewById(R.id.toggleSatRadioGroup);
        mToggleIconsRadioGroup = (RadioGroup) findViewById(R.id.toggleIconsRadioGroup);
        mToggleAccRadioGroup = (RadioGroup) findViewById(R.id.toggleAccRadioGroup);
        mLimitStartDateRadioGroup = (RadioGroup) findViewById(R.id.limitStartDateRadioGroup);
        mLimitEndDateRadioGroup = (RadioGroup) findViewById(R.id.limitEndDateRadioGroup);

        Intent i = getIntent();
        if (i.getBooleanExtra(MapMyData.DATES_BUTTON_MESSAGE, false)) {

            RelativeLayout dateSettingsArea = (RelativeLayout) findViewById(R.id.dateSettingsArea);
            dateSettingsArea.setFocusable(true);
            dateSettingsArea.setFocusableInTouchMode(true);
            dateSettingsArea.requestFocus();
        }

        if (shareMyData && isServiceOn) {
            participationTimeText.setBase(SystemClock.elapsedRealtime() - PropertyHolder.ptStart());
            participationTimeText.start();
        }

        nUploadsText.setText(String.valueOf(nUploads));

        if (nUploads >= Util.UPLOADS_TO_PRO && !PropertyHolder.getProVersion()
                && participationTime >= Util.TIME_TO_PRO) {
            Util.createProNotification(context);
            PropertyHolder.setProVersion(true);
            PropertyHolder.setNeedsDebriefingSurvey(true);
        }

        boolean proV = PropertyHolder.getProVersion();

        // 19 December 2013: end of research changes
        mShareDataRadioGroup.check(R.id.sharedataNo);

        mShareDataRadioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                if (checkedId == R.id.sharedataYes) {
                    buildSharingOverAnnouncement();
                }
                mShareDataRadioGroup.check(R.id.sharedataNo);
            }
        });

        /*
         * if (proV) {
         * 
         * if (shareMyData) { mShareDataRadioGroup.check(R.id.sharedataYes); if
         * (PropertyHolder.isRegistered() == false ||
         * PropertyHolder.hasConsented() == false) { send2Intro(context); } }
         * else { mShareDataRadioGroup.check(R.id.sharedataNo); }
         * 
         * mShareDataRadioGroup .setOnCheckedChangeListener(new
         * OnCheckedChangeListener() {
         * 
         * @Override public void onCheckedChanged(RadioGroup group, int
         * checkedId) { shareMyData = (checkedId == R.id.sharedataYes);
         * PropertyHolder.setShareData(shareMyData);
         * toggleParticipationViews(shareMyData); final boolean on =
         * PropertyHolder.isServiceOn(); if (shareMyData) { if
         * (PropertyHolder.isRegistered() == false ||
         * PropertyHolder.hasConsented() == false) { send2Intro(context);
         * 
         * } if (on) {
         * 
         * final long ptNow = PropertyHolder.ptStart();
         * participationTimeText.setBase(SystemClock .elapsedRealtime() -
         * ptNow);
         * 
         * participationTimeText.start();
         * 
         * ContentResolver ucr = getContentResolver();
         * 
         * ucr.insert( Util.getUploadQueueUri(context),
         * UploadContentValues.createUpload( "ONF", "on," + Util.iso8601(System
         * .currentTimeMillis()) + "," + ptNow));
         * 
         * } } else {
         * 
         * final long ptNow = PropertyHolder.ptStop();
         * participationTimeText.setBase(SystemClock .elapsedRealtime() -
         * ptNow); participationTimeText.stop(); // stop uploader Intent i = new
         * Intent(Settings.this, FileUploader.class); // Stop service if it is
         * currently running stopService(i);
         * 
         * if (on) { ContentResolver ucr = getContentResolver();
         * 
         * ucr.insert( Util.getUploadQueueUri(context),
         * UploadContentValues.createUpload( "ONF", "off," + Util.iso8601(System
         * .currentTimeMillis()) + "," + ptNow));
         * 
         * }
         * 
         * }
         * 
         * } }); } else { mShareDataRadioGroup.check(R.id.sharedataYes);
         * mShareDataRadioGroup .setOnCheckedChangeListener(new
         * OnCheckedChangeListener() {
         * 
         * @Override public void onCheckedChanged(RadioGroup group, int
         * checkedId) { if (checkedId == R.id.sharedataNo) {
         * mShareDataRadioGroup.check(R.id.sharedataYes);
         * showCurrentlySharingDialog(); } } });
         * 
         * }
         */
        new CheckPendingUploadsSizeTask().execute(context);
        new CheckUserDbSizeTask().execute(context);

        deletePendingUploadsButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                ContentResolver cr = getContentResolver();
                final int nDeleted = cr.delete(Util.getUploadQueueUri(context), "1", null);

                // Log.i("Settings", "number of rows deleted=" + nDeleted);
                Util.toast(context, String.valueOf(nDeleted) + " "
                        + getResources().getString(R.string.locations_deleted) + ".");

                updateStorageSizes();

            }

        });

        deleteUserDbButton = (ImageButton) findViewById(R.id.deleteMyDbButton);

        deleteUserDbButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                ContentResolver cr = getContentResolver();
                final int nDeleted = cr.delete(Util.getFixesUri(context), "1", null);

                Util.toast(context, String.valueOf(nDeleted) + " "
                        + getResources().getString(R.string.locations_deleted) + ".");
                updateStorageSizes();

            }

        });

        uploadButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                if (Util.isOnline(context)) {
                    Intent i = new Intent(Settings.this, FileUploader.class);
                    startService(i);

                    new UploadMessageTask().execute(context);
                } else {
                    Util.toast(context, getResources().getString(R.string.offline_warning));
                }

            }

        });

        mToggleSatRadioGroup.check(PropertyHolder.getMapSat() ? R.id.toggleSatYes : R.id.toggleSatNo);

        mToggleSatRadioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                PropertyHolder.setMapSat(checkedId == R.id.toggleSatYes);
            }
        });

        mToggleIconsRadioGroup.check(PropertyHolder.getMapIcons() ? R.id.toggleIconsYes : R.id.toggleIconsNo);

        mToggleIconsRadioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                PropertyHolder.setMapIcons(checkedId == R.id.toggleIconsYes);
            }
        });

        mToggleAccRadioGroup.check(PropertyHolder.getMapAcc() ? R.id.toggleAccYes : R.id.toggleAccNo);

        mToggleAccRadioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                PropertyHolder.setMapAcc(checkedId == R.id.toggleAccYes);
            }
        });

        mStartDateButton = (Button) findViewById(R.id.startDateButton);
        mEndDateButton = (Button) findViewById(R.id.endDateButton);

        boolean limitStartDate = PropertyHolder.getLimitStartDate();
        boolean limitEndDate = PropertyHolder.getLimitEndDate();

        if (!limitStartDate)
            mStartDateButton.setVisibility(View.GONE);
        else {
            mStartDateButton.setVisibility(View.VISIBLE);

        }
        if (!limitEndDate)
            mEndDateButton.setVisibility(View.GONE);
        else {
            mEndDateButton.setVisibility(View.VISIBLE);
        }

        mLimitStartDateRadioGroup.check(limitStartDate ? R.id.limitStartDateYes : R.id.limitStartDateNo);

        mLimitStartDateRadioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                PropertyHolder.setLimitStartDate(checkedId == R.id.limitStartDateYes);

                if (checkedId != R.id.limitStartDateYes)
                    mStartDateButton.setVisibility(View.GONE);
                else {
                    mStartDateButton.setVisibility(View.VISIBLE);
                }
            }
        });

        mLimitEndDateRadioGroup.check(limitEndDate ? R.id.limitEndDateYes : R.id.limitEndDateNo);

        mLimitEndDateRadioGroup.setOnCheckedChangeListener(new OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                PropertyHolder.setLimitEndDate(checkedId == R.id.limitEndDateYes);

                if (checkedId != R.id.limitEndDateYes)
                    mEndDateButton.setVisibility(View.GONE);
                else {
                    mEndDateButton.setVisibility(View.VISIBLE);
                }
            }
        });

        mStartDateButton.setText(Util.userDateNoTime(PropertyHolder.getMapStartDate()));
        mStartDateButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                DialogFragment newFragment = new StartDatePickerFragment();
                newFragment.show(getSupportFragmentManager(), "datePicker");

            }

        });

        mEndDateButton.setText(Util.userDateNoTime(PropertyHolder.getMapEndDate()));
        mEndDateButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                DialogFragment newFragment = new EndDatePickerFragment();
                newFragment.show(getSupportFragmentManager(), "datePicker");

            }

        });

        if (PropertyHolder.getNeedsDebriefingSurvey()) {
            buildProAnnouncement();
            PropertyHolder.setNeedsDebriefingSurvey(false);
        }

        super.onResume();

    }

    @Override
    protected void onPause() {
        unregisterReceiver(fixReceiver);
        unregisterReceiver(uploadReceiver);
        participationTimeText.stop();

        super.onPause();
    }

    // for interval spinner
    private int[] mInterval = { 15000, 30000, 60000, 120000, 300000, 600000, 1800000, 3600000 };

    private int ai2pos(Long interval) {
        interval = interval == -1 ? Util.ALARM_INTERVAL : interval;
        for (int i = 0; i < mInterval.length; i++) {
            if (mInterval[i] == interval)
                return i;
        }
        return -1;
    }

    private void showSpinner(boolean _show, boolean store) {
        mIntervalSpinner.setEnabled(_show);
        if (_show) {
            mServiceMessage.setText(R.string.service_is_on);
            mIntervalSpinner.setVisibility(View.VISIBLE);
            mIntervalHeading.setTextColor(Color.WHITE);
            mIntervalText.setTextColor(oldColors);

        } else {
            mServiceMessage.setText(R.string.service_is_off);
            mIntervalSpinner.setVisibility(View.INVISIBLE);
            mIntervalHeading.setTextColor(Color.GRAY);
            mIntervalText.setTextColor(Color.GRAY);

        }
    }

    private void buildAlertMessageNoGps() {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(getResources().getString(R.string.noGPSAlert)).setCancelable(false)
                .setPositiveButton(getResources().getString(R.string.yes), new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog, final int id) {
                        startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
                    }
                }).setNegativeButton(getResources().getString(R.string.no), new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog, final int id) {
                        dialog.cancel();
                    }
                });
        final AlertDialog alert = builder.create();
        alert.show();
    }

    private void buildAlertMessageNoGpsNoNet() {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(getResources().getString(R.string.noGPSnoNetAlert)).setCancelable(false)
                .setPositiveButton(getResources().getString(R.string.yes), new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog, final int id) {
                        startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
                    }
                }).setNegativeButton(getResources().getString(R.string.no), new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog, final int id) {
                        dialog.cancel();
                    }
                });
        final AlertDialog alert = builder.create();
        alert.show();
    }

    // TODO limit possible date selections by setting end date to current date
    // whenever user tries to set it over, and start date to first date in date
    // whenever user tries to set it under. Also stop user from setting start
    // date higher than end date.
    public static class StartDatePickerFragment extends DialogFragment
            implements DatePickerDialog.OnDateSetListener {

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {

            Calendar c = PropertyHolder.getMapStartCalendar();

            int year = c.get(Calendar.YEAR);
            int month = c.get(Calendar.MONTH);
            int day = c.get(Calendar.DAY_OF_MONTH);

            // Create a new instance of DatePickerDialog and return it
            return new DatePickerDialog(getActivity(), this, year, month, day);
        }

        public void onDateSet(DatePicker view, int year, int month, int day) {

            PropertyHolder.setMapStartDate(year, month, day);

            GregorianCalendar gc = new GregorianCalendar(year, month, day);
            mStartDateButton.setText(Util.userDateNoTime(gc.getTime()));

            MapMyData.reloadData = true;

            if (gc.after(PropertyHolder.getMapEndCalendar()))
                Util.toast(context, getResources().getString(R.string.warning_calendar_start_date));

        }
    }

    public static class EndDatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener {

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {

            Calendar c = PropertyHolder.getMapEndCalendar();

            int year = c.get(Calendar.YEAR);
            int month = c.get(Calendar.MONTH);
            int day = c.get(Calendar.DAY_OF_MONTH);

            // Create a new instance of DatePickerDialog and return it
            return new DatePickerDialog(getActivity(), this, year, month, day);
        }

        public void onDateSet(DatePicker view, int year, int month, int day) {

            PropertyHolder.setMapEndDate(year, month, day);

            GregorianCalendar gc = new GregorianCalendar(year, month, day);
            mEndDateButton.setText(Util.userDateNoTime(gc.getTime()));

            MapMyData.reloadData = true;

            if (gc.before(PropertyHolder.getMapStartCalendar()))
                Util.toast(context, getResources().getString(R.string.warning_calendar_end_date));

        }
    }

    private void showCurrentlySharingDialog() {

        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(getResources().getString(R.string.currently_sharing)).setCancelable(true)
                .setPositiveButton(getResources().getString(R.string.ok), new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog, final int id) {
                        dialog.cancel();
                    }
                }).setNeutralButton(getResources().getString(R.string.more_info),
                        new DialogInterface.OnClickListener() {
                            public void onClick(final DialogInterface dialog, final int id) {
                                Intent i = new Intent(Settings.this, Help.class);
                                // start the intent
                                startActivity(i);
                                finish();
                            }
                        })

        ;
        final AlertDialog alert = builder.create();
        alert.show();
    }

    private void send2Intro(Context context) {
        Intent intent = new Intent(context, Intro.class);
        startActivity(intent);
        return;
    }

    public class UploadReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            updateStorageSizes();
            int nUploads = intent.getIntExtra("nUploads", 0);
            nUploadsText.setText(String.valueOf(nUploads));
            // Log.i(TAG, "nUploads=" + nUploads);

        }

    }

    public class FixReceiver extends BroadcastReceiver {

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

    }

    private void updateStorageSizes() {

        new CheckPendingUploadsSizeTask().execute(context);
        new CheckUserDbSizeTask().execute(context);

    }

    public class CheckPendingUploadsSizeTask extends AsyncTask<Context, Integer, Boolean> {

        String resultUsed = "0 bytes";
        String resultAvailable = "0 bytes";
        boolean dummy = false;

        @Override
        protected void onPreExecute() {

            mStorageSizePendingUploadsText.setText(getResources().getString(R.string.calculating) + " . . .");
        }

        protected Boolean doInBackground(Context... context) {

            resultUsed = Util.getPendingUploadsMB(context[0]);

            resultAvailable = Util.getAvailableMB();

            return true;
        }

        protected void onProgressUpdate(Integer... progress) {

            if (dummy)
                mStorageSizePendingUploadsText.setText(getResources().getString(R.string.calculating) + " . . .");
            else
                mStorageSizePendingUploadsText.setText(getResources().getString(R.string.calculating) + ". . .");

            dummy = !dummy;
        }

        protected void onPostExecute(Boolean result) {

            mStorageSizePendingUploadsText.setText(resultUsed + " " + getResources().getString(R.string.used) + " ("
                    + resultAvailable + " " + getResources().getString(R.string.available) + ")");

        }
    }

    public class CheckUserDbSizeTask extends AsyncTask<Context, Integer, Boolean> {

        String resultUsed = "0 bytes";
        String resultAvailable = "0 bytes";
        boolean dummy = false;

        @Override
        protected void onPreExecute() {

            mStorageSizeUserDbText.setText(getResources().getString(R.string.calculating) + " . . .");
        }

        protected Boolean doInBackground(Context... context) {

            resultUsed = Util.getUserDbMB(context[0]);

            resultAvailable = Util.getAvailableMB();

            return true;
        }

        protected void onProgressUpdate(Integer... progress) {

            if (dummy)
                mStorageSizeUserDbText.setText(getResources().getString(R.string.calculating) + " . . .");
            else
                mStorageSizeUserDbText.setText(getResources().getString(R.string.calculating) + ". . .");

            dummy = !dummy;
        }

        protected void onPostExecute(Boolean result) {

            mStorageSizeUserDbText.setText(resultUsed + " " + getResources().getString(R.string.used) + " ("
                    + resultAvailable + " " + getResources().getString(R.string.available) + ")");

        }
    }

    public class UploadMessageTask extends AsyncTask<Context, Integer, Boolean> {
        int nRecords = 0;

        @Override
        protected void onPreExecute() {

        }

        protected Boolean doInBackground(Context... context) {

            ContentResolver cr = getContentResolver();
            String[] proj = { Uploads.KEY_PREFIX };
            String selectionString = Uploads.KEY_PREFIX + " = " + "'FIX'";

            Cursor c = cr.query(Util.getUploadQueueUri(context[0]), proj, selectionString, null, null);
            if (c.moveToFirst())
                nRecords = c.getCount();
            c.close();

            return true;
        }

        protected void onProgressUpdate(Integer... progress) {

        }

        protected void onPostExecute(Boolean result) {

            final String msg;

            if (nRecords == 1)
                msg = getResources().getString(R.string.uploading) + " " + nRecords + " "
                        + getResources().getString(R.string.location) + ". "
                        + getResources().getString(R.string.thank_you_for_participating);
            else
                msg = getResources().getString(R.string.uploading) + " " + nRecords + " "
                        + getResources().getString(R.string.locations) + ". "
                        + getResources().getString(R.string.thank_you_for_participating);

            Util.toast(context, msg);

        }
    }

    private void toggleParticipationViews(boolean isActive) {
        if (isActive) {
            participationLabel.setTextColor(Color.WHITE);
            pendingUploadsLabel.setTextColor(Color.WHITE);
            participationTimeText.setTextColor(Color.WHITE);
            nUploadsText.setTextColor(Color.WHITE);
            deletePendingUploadsButton.setVisibility(View.VISIBLE);
            uploadButton.setVisibility(View.VISIBLE);
            mStorageSizePendingUploadsText.setVisibility(View.VISIBLE);

        } else {
            participationLabel.setTextColor(Color.GRAY);
            pendingUploadsLabel.setTextColor(Color.GRAY);
            participationTimeText.setTextColor(Color.GRAY);
            nUploadsText.setTextColor(Color.GRAY);
            deletePendingUploadsButton.setVisibility(View.INVISIBLE);
            uploadButton.setVisibility(View.INVISIBLE);
            mStorageSizePendingUploadsText.setVisibility(View.INVISIBLE);

        }

    }

    // 19 December 2013: end of research changes
    private void buildSharingOverAnnouncement() {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(getResources().getString(R.string.no_sharing_msg)).setCancelable(true).setNegativeButton(
                getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog, final int id) {
                        dialog.dismiss();
                    }
                }).setPositiveButton(getResources().getString(R.string.visit_website),
                        new DialogInterface.OnClickListener() {
                            public void onClick(final DialogInterface dialog, final int id) {

                                String url = "http://www.princeton.edu/~jrpalmer/spacemapper";
                                Intent i = new Intent(Intent.ACTION_VIEW);
                                i.setData(Uri.parse(url));
                                startActivity(i);

                            }
                        });
        final AlertDialog alert = builder.create();
        alert.show();

    }

    private void buildProAnnouncement() {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setMessage(getResources().getString(R.string.user_id) + "\n" + PropertyHolder.getUserId() + "\n\n"
                + getResources().getString(R.string.pro_welcome)).setCancelable(true)
                .setPositiveButton(getResources().getString(R.string.ok), new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog, final int id) {

                        cancelNotification(context);
                        Intent i = new Intent(Settings.this, DebriefingSurvey.class);
                        startActivity(i);
                    }
                });
        final AlertDialog alert = builder.create();
        alert.show();

    }

    public void cancelNotification(Context context) {
        NotificationManager notificationManager = (NotificationManager) context
                .getSystemService(Context.NOTIFICATION_SERVICE);
        notificationManager.cancel(Util.PRO_CONVERSION_NOTIFICATION);

    }

}