ForkMe-Mobile/app/src/main/java/dlei/forkme/model/LocationData.java
public class LocationData {

    private Double latitude;
    private Double longitude;
    private Integer id;

    public Double getLatitude() {
        return latitude;
    }

    public void setLatitude(Double latitude) {
        this.latitude = latitude;
    }

    public Double getlongitude() {
        return longitude;
    }

    public void setlongitude(Double _longitude) {
        this.longitude = longitude;
    }

    public Integer getId() {
        return id;
    }

     public void setId(Integer id) {
        this.id = id;
    }
}
ForkMe-Mobile/app/src/main/java/dlei/forkme/datastore/DatabaseHelper.java
public class DatabaseHelper extends SQLiteOpenHelper {

    public static DatabaseHelper sDbInstance = null;

    public static final String sDatabaseName = "AppSettings";
    public static final int sDatabaseVersion = 1;

    private DatabaseHelper(Context context) {
        super(context, sDatabaseName, null, sDatabaseVersion);
    }

    /**
     * Singleton pattern so only 1 object of DatabaseHelper exists.
     * @param context activity context.
     * @return instance of DatabaseHelper.
     */
    public static synchronized DatabaseHelper getDbInstance(Context context) {
        if (sDbInstance == null) {
            sDbInstance = new DatabaseHelper(context);
            Log.d("DatabaseHelper: ", "getDbInstance() created new instance");
        }
        return sDbInstance;
    }

    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        try {
            sqLiteDatabase.execSQL(AppSettings.CREATE_TABLE_SQL);
            Log.d("DatabaseHelper: ", "onCreate() created db");
        } catch (SQLException e) {
            Log.wtf("Error: ", String.format("Create Table Statement: %s\nException: %s",
                    AppSettings.CREATE_TABLE_SQL, e));
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
        try {
            sqLiteDatabase.execSQL("DROP TABLE IF EXISTS " + AppSettings.TABLE_NAME); // Drop table.
            onCreate(sqLiteDatabase); // Re make table.
        } catch (SQLException e) {
            // Shouldn't happen, if it does log what a terrible message.
            Log.wtf("Error: ", String.format("onUpdate Error, Exception %s", e));
        }
        // db.close();  // Close database connection.
    }

    /**
     * Insert settings for a user into persistant storage.
     */
    public void insertSettings() {
        if (AppSettings.sUserLogin.equals("")) {
            Log.wtf("Error: ", "DatabaseHelper.insertSettings(): user log in is null");
            return;
        }
        Log.i("DatabaseHelper: ", "insertSettings(): inserting settings");
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(AppSettings.USER_ID_COL, AppSettings.sUserLogin);
        values.put(AppSettings.TIMEFRAME_COL, AppSettings.sTimeframe);
        values.put(AppSettings.SORT_BY_COL, AppSettings.sSortBy);
        values.put(AppSettings.LANGUAGE_COL, AppSettings.sLanguage);
        values.put(AppSettings.LOCATION_DISABLED_FOREVER_COL, AppSettings.sLocationDisabledForever);
        values.put(AppSettings.FIND_PEOPLE_MESSAGE_COL, AppSettings.sFindPeopleMessage);
        values.put(AppSettings.PRIVATE_REPOS_COL, AppSettings.sShowPrivateRepositories);
        long result = db.insert(AppSettings.TABLE_NAME, null, values);
        if (result == -1) {
            Log.w("Error: ", String.format("Adding settings for user %s", AppSettings.sUserLogin));
        }
    }

    /**
     * Update language for a user in persistant storage.
     */
    public void updateLanguage() {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(AppSettings.LANGUAGE_COL, AppSettings.sLanguage);
        db.update(AppSettings.TABLE_NAME, values, AppSettings.USER_ID_COL + "='" + AppSettings.sUserLogin +"'",
                null);
        db.close();
    }

    /**
     * Update timeframe preference for a user in persistant storage.
     */
    public void updateTimeframe() {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(AppSettings.TIMEFRAME_COL, AppSettings.sTimeframe);
        db.update(AppSettings.TABLE_NAME, values, AppSettings.USER_ID_COL + "='" + AppSettings.sUserLogin +"'",
                null);
        db.close();
    }

    /**
     * Update stort by preference for a user in persistant storage.
     */
    public void updateSortBy() {
        SQLiteDatabase db = this.getWritableDatabase();
        ContentValues values = new ContentValues();
        values.put(AppSettings.SORT_BY_COL, AppSettings.sSortBy);
        db.update(AppSettings.TABLE_NAME, values, AppSettings.USER_ID_COL + "='" + AppSettings.sUserLogin +"'",
                null);
        db.close();
    }

    /**
     * Loads settings for a user from SQLite db.
     * @throws NoDataException Thrown when no data returned.
     * @throws TooMuchDataException Thrown when too much data returned.
     */
    public void loadSettings() throws NoDataException, TooMuchDataException{
        SQLiteDatabase db = this.getWritableDatabase();

        String baseQuery = "SELECT %s, %s, %s, %s, %s, %s from %s WHERE %s=?";

        String query = String.format(baseQuery,
                AppSettings.TIMEFRAME_COL, AppSettings.SORT_BY_COL, AppSettings.LANGUAGE_COL,
                AppSettings.LOCATION_DISABLED_FOREVER_COL, AppSettings.FIND_PEOPLE_MESSAGE_COL, AppSettings.PRIVATE_REPOS_COL,
                AppSettings.TABLE_NAME,
                AppSettings.USER_ID_COL);
        Log.i("UserLogin: ", AppSettings.sUserLogin);

        Cursor cursor = db.rawQuery(query, new String[]{AppSettings.sUserLogin});

        cursor.moveToFirst();
        int rows = cursor.getCount();
        if (rows == 0) {
            cursor.close();
            db.close();
            throw new NoDataException(String.format(
                    "User with login %s does not exist", AppSettings.sUserLogin));
        } else if (rows > 1) {
            cursor.close();
            db.close();
            throw new TooMuchDataException(String.format(
                    "Only 1 row should be returned for user %s", AppSettings.sUserLogin));
        } else {
            // Update settings for a user.
            Log.i("Check has data worked: ", "Language: " + cursor.getString(2));
            Log.i("Check has data worked: ", "Timeframe: " + cursor.getString(1));

            AppSettings.setTimeframe(cursor.getString(0));
            AppSettings.setSortBy(cursor.getString(1));
            AppSettings.setLanguage(cursor.getString(2));
            AppSettings.setLocationDisabledForever(cursor.getInt(3));
            AppSettings.setFindPeopleAllowedMessage(cursor.getString(4));
            AppSettings.setShowPrivateRepositories(cursor.getInt(5));
            cursor.close();
            db.close();
        }

    }
}
ForkMe-Mobile/app/src/main/java/dlei/forkme/endpoints/ForkMeBackendApi.java
public interface ForkMeBackendApi {

    // Get all repositories v1.
    @GET("/all_repos")
    Call<RepositoryResponse> getAllRepositories();

    // Get single repository v1.
    @GET("/all_repos/repositories/{id}")
    Call<Repository> getRepository(@Path("id") int id);

    // Get all repositories v2.
    @GET("/repositories")
    Call<List<Repository>> getRepositoriesArray();

    // Post location data v2.
    @POST("/locations")
    Call<ResponseBody> postLocation(@Body PostLocationDataBody data);

    // Get developers v2.
    @GET("/developers/{login}")
    Call<List<DeveloperContactInfo>> getDevelopers(@Path("login") String login);

}
ForkMe-Mobile/app/src/main/java/dlei/forkme/helpers/LocationHelper.java
public class LocationHelper {

    /**
     * Checks if location permissions has been granted to application.
     * @param context Activity context.
     * @return true if has location permissions, else false.
     */
    public static boolean hasLocationPermissions(Context context) {

        boolean hasLocationPermissions = ContextCompat
                .checkSelfPermission(context,
                        Manifest.permission.ACCESS_FINE_LOCATION
                ) == PackageManager.PERMISSION_GRANTED;
        return hasLocationPermissions;
    }

}
ForkMe-Mobile/app/src/main/java/dlei/forkme/endpoints/BaseUrls.java
public class BaseUrls {
    public static String githubApi = "https://api.github.com/";
    public static String forkMeBackendApi = "https://forkme-backend-api2.herokuapp.com/";
    public static String forkMeBackendApiDeprecated = "https://forkme-backend.herokuapp.com/";
}
ForkMe-Mobile/app/src/main/java/dlei/forkme/state/AppSettings.java
public class AppSettings {
    // Setting attributes.
    public static String sLanguage = "All";
    public static String sSortBy = "Stars";
    public static String sTimeframe = "1 Month";
    public static String sUserLogin = "";
    public static int sLocationDisabledForever = 0;
    public static String sFindPeopleMessage = "N/A";
    public static int sShowPrivateRepositories = 0;
    public static String sOAuthToken = "";
    public static String sUserName = "";
    public static String sUserAvatarUrl = "";
    public static String sUserEmail;

    // Database attributes.
    public static final String TABLE_NAME = "settings";
    public static final String TIMEFRAME_COL = "timeframe";
    public static final String SORT_BY_COL = "sort_by";
    public static final String LANGUAGE_COL = "language";
    public static final String LOCATION_DISABLED_FOREVER_COL = "location_disabled_forever";
    public static final String FIND_PEOPLE_MESSAGE_COL = "message";
    public static final String PRIVATE_REPOS_COL = "private_repos";
    public static final String USER_ID_COL = "user";

    public static final String CREATE_TABLE_SQL =
            "CREATE TABLE " +
            TABLE_NAME + " (" +
            USER_ID_COL + SqlSyntax.TYPE_STRING + SqlSyntax.PRIMARY_KEY + ", " +
            TIMEFRAME_COL + SqlSyntax.TYPE_STRING + SqlSyntax.NOT_NULL + ", " +
            SORT_BY_COL + SqlSyntax.TYPE_STRING + SqlSyntax.NOT_NULL + ", " +
            LANGUAGE_COL + SqlSyntax.TYPE_STRING + SqlSyntax.NOT_NULL + ", " +
            LOCATION_DISABLED_FOREVER_COL + SqlSyntax.TYPE_INTEGER + SqlSyntax.NOT_NULL + ", " +
            FIND_PEOPLE_MESSAGE_COL + SqlSyntax.TYPE_STRING + SqlSyntax.NOT_NULL + ", " +
            PRIVATE_REPOS_COL + SqlSyntax.TYPE_INTEGER + SqlSyntax.NOT_NULL +
            ")";

    public static void setLanguage(String language) {
        sLanguage = language;
    }

    public static void setSortBy(String sortBy) {
        sSortBy = sortBy;
    }

    public static void setTimeframe(String timeframe) {
        sTimeframe = timeframe;
    }

    public static void setLocationDisabledForever(int i) {
        if (i > 1 || i < 0) {
            Log.wtf("AppSettings: ", "setShowPrivateRepositories: Invalid value " + i);
            return;
        }
        sLocationDisabledForever = i;
    }

    public static void setFindPeopleAllowedMessage(String findPeopleAllowedMessage) {
        sFindPeopleMessage = findPeopleAllowedMessage;
    }

    public static void setShowPrivateRepositories(int i) {
        if (i > 1 || i < 0) {
            Log.wtf("AppSettings: ", "setShowPrivateRepositories: Invalid value " + i);
            return;
        }
        sShowPrivateRepositories = i;
    }

    public static void updateLanguage(String language) {
        sLanguage = language;
        Log.i("AppSettings: ", "updateLanguage(): " + language);
    }

    public static void updateTimeframe(String timeframe) {
        sTimeframe = timeframe;
        Log.i("AppSettings: ", "updateTimeframe(): " + timeframe);
    }

    public static void updateSortBy(String sortBy) {
        sSortBy = sortBy;
        Log.i("AppSettings: ", "updateSortBy(): " + sortBy);
    }

    public static void updateLocationDisabledForever(int i) {
        if (i > 1 || i < 0) {
            Log.wtf("AppSettings: ", "updateLocationDisabledForever(): Invalid value " + i);
            return;
        }
        Log.i("AppSettings: ", "updateLocationDisabledForever(): " + i);
        sLocationDisabledForever = i;
    }

    public static void setOAuthToken(String token) {
        sOAuthToken = token;
    }

    public static void setUserLogin(String userLogin) {
        sUserLogin = userLogin;
    }

    public static void setUserName(String userName) {
        sUserName = userName;
    }

    public static void setUserAvatarUrl(String userAvatarUrl) {
        sUserAvatarUrl  = userAvatarUrl;
    }

    public static void setUserEmail(String email) { sUserEmail = email; }


}
ForkMe-Mobile/app/src/main/java/dlei/forkme/helpers/NetworkAsyncCheck.java
public class NetworkAsyncCheck extends AsyncTask<Void, Void, Boolean> {
    private View view;

    public NetworkAsyncCheck(View view) {
        this.view = view;
        Log.i("NetworkAsyncCheck: ", "Starting");
    }

    protected Boolean doInBackground(Void... params) {
        Log.i("NetworkAsyncCheck: ", "Doing");
        try {
            InetAddress ipAddress = InetAddress.getByName("www.google.com");
            return !ipAddress.equals("") ? Boolean.TRUE : Boolean.FALSE;
        } catch (Exception e) {
            return Boolean.FALSE;
        }
    }

    protected void onPostExecute(Boolean result) {
        Log.i("NetWorkASyncCheck: ", " Done");
        if (result == Boolean.FALSE) {
            Snackbar.make(view, String.format(Locale.getDefault(), NetworkHelper.noConnectionMessage, "the internet"), Snackbar.LENGTH_INDEFINITE)
                    .setAction("CLOSE", new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {}
                    })
                    .setActionTextColor(ContextCompat.getColor(view.getContext(), R.color.colorAccent))
                    .show();
        }
    }

}
ForkMe-Mobile/app/src/main/java/dlei/forkme/helpers/NetworkHelper.java
public class NetworkHelper {

    static String noConnectionMessage = "Please connect to %s, this app requires internet access.";

    /**
     * Return null if not connected to a network, else returns an async task to check the network has internet connection.
     * Note: This checks for both valid network and valid internet connection.
     * @param view any view in the activity that called this, used to make snackbar.
     * @return null or NetworkHelper.NetworkAsyncCheck.
     */
    public static NetworkAsyncCheck checkNetworkConnection(View view) {
        Context context = view.getContext();
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);

        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        boolean isConnectedToNetwork = activeNetwork != null &&
                activeNetwork.isConnectedOrConnecting();

        if (!isConnectedToNetwork) {
            Snackbar.make(view, String.format(Locale.getDefault(), noConnectionMessage, "a network"), Snackbar.LENGTH_INDEFINITE)
                    .setAction("CLOSE", new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {}
                    })
                    .setActionTextColor(ContextCompat.getColor(context, R.color.colorAccent))
                    .show();
            return null;
        }
        return new NetworkAsyncCheck(view);
    }

}
ForkMe-Mobile/app/src/main/java/dlei/forkme/datastore/TooMuchDataException.java
public class TooMuchDataException extends Exception {
    public TooMuchDataException(String s) {
        super(s);
    }
}
ForkMe-Mobile/app/src/main/java/dlei/forkme/datastore/NoDataException.java
public class NoDataException extends Exception {
    public NoDataException(String s) {
        super(s);
    }
}
ForkMe-Mobile/app/src/main/java/dlei/forkme/model/json/PostLocationDataBody.java
public class PostLocationDataBody {
    String login;
    double latitude;
    double longitude;
    String message;
    String email;
    String name;
    String avatarUrl;

    public PostLocationDataBody(String login, double latitude, double longitude, String message,
                                String email, String name, String avatarUrl) {
        this.login = login;
        this.latitude = latitude;
        this.longitude = longitude;
        this.message = message;
        this.email = email;
        this.name = name;
        this.avatarUrl = avatarUrl;
    }
}


Question: import android.Manifest;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TextInputEditText;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.os.Bundle;
import android.support.v7.widget.AppCompatButton;
import android.support.v7.widget.AppCompatSpinner;
import android.support.v7.widget.AppCompatTextView;
import android.support.v7.widget.SwitchCompat;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Locale;
import dlei.forkme.R;
import dlei.forkme.datastore.DatabaseHelper;
import dlei.forkme.datastore.NoDataException;
import dlei.forkme.datastore.TooMuchDataException;
import dlei.forkme.endpoints.BaseUrls;
import dlei.forkme.endpoints.ForkMeBackendApi;
import dlei.forkme.helpers.LocationHelper;
import dlei.forkme.helpers.NetworkAsyncCheck;
import dlei.forkme.helpers.NetworkHelper;
import dlei.forkme.model.LocationData;
import dlei.forkme.model.json.PostLocationDataBody;
import dlei.forkme.state.AppSettings;
import okhttp3.OkHttpClient;
import okhttp3.Response;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
                        .create()
                        .show();
            }  else {
                // No explanation needed, we can request the permission.
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission. ACCESS_FINE_LOCATION},
                        MY_PERMISSIONS_REQUEST_LOCATION);
            }
        } else {
            Log.wtf("SettingActivity: ", " askForLocationPermissions() Already have permissions.");
            getLocation();
        }
    }


    /**
     * Called when the user responds to a permission request.
     * @param requestCode code assigned to permission request.
     * @param permissions permissions requested.
     * @param grantResults results of permission requests.
     */
    public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_LOCATION: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0
                        && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    // Permission is granted.
                    Log.d("SettingsActivity: ", "onRequestPermissionsResult() " +
                            "Location Permissions: granted");
                    String isCheckedStr = "True";
                    mSwitchText.setText(isCheckedStr);
                    mLocationSwitch.setClickable(false);
                    // Only enable to turn of locations if locations permissions is revoked from outside.
                } else {
                    // Permission denied.
                    Log.wtf("SettingsActivity: ", "onRequestPermissionsResult() " +
                            "Location Permissions: denied, test: " + permissions[0]);

                    boolean showRationale = shouldShowRequestPermissionRationale(permissions[0]);
                    if (!showRationale) {
                        // User also selected never show again.
                        Log.wtf("SettingsActivity: ", "onRequestPermissionsResultI() " +
                                "Location Permissions: never show again clicked, disabled forever.");
                        // Disable switch button.
                        mLocationSwitch.setEnabled(false);
                        mSwitchText.setText(getResources().getText(R.string.disabled));
                        // Make LocationDisabledForever true.
                        AppSettings.updateLocationDisabledForever(1);
                    }
                    // Update switch to be false.
                    mLocationSwitch.setChecked(false);
                }
                return;
            }

        }

    }

    // Location code adapted from:
    // https://stackoverflow.com/questions/10524381/gps-android-get-positioning-only-once
    // https://stackoverflow.com/questions/40142331/how-to-request-location-permission-on-android-6/40142454

    /**
     * Determine if location should be asked from GPS. We only want to get location once so we can determine
     * what city the user is in. Only get new location if the old location if more than 2 days old.
     */
    public void getLocation() {
        try {
            Location location = mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            // location time retrieved > time in milliseconds - 2000 (less than 2 days old).
            // 1.4 days.
            if (location != null && location.getTime() < Calendar.getInstance().getTimeInMillis() + 2 * 60 * 1000) {
                // Use olg location.
                Log.d("SettingActivity: ", "getLocation(): Old location, latitude: " + location.getLatitude() +
                        ", longitude: " + location.getLongitude() + ", time: " + location.getTime());
                postLocationInformation(location);
            } else {
                // Ask for location updates.
                Log.d("SettingActivity: ", "getLocation(): Request location updates.");
                // Bug fix for not being called onLocationChanged()
                // https://stackoverflow.com/questions/9007600/onlocationchanged-callback-is-never-called
                mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
                mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, this);
            }
        } catch (SecurityException e) {
            Log.wtf("SettingActivity: ", "Failed " + e.getMessage());
            return;
        }
    }

    /**
     * Location updates have been requested, this is triggered when we get a location update.
     * We stop updates after this one update.
     * @param location new location.
     */
    public void onLocationChanged(Location location) {
        Log.d("SettingActivity: ", "onLocationChanged() called");
        if (location != null) {
            Log.d("SettingActivity: ", "onLocationChanged(): Location update, latitude: "
                    + location.getLatitude() + ", longitude: " + location.getLongitude());
            mLocationManager.removeUpdates(this);   // Stop updates.
            postLocationInformation(location);

        }
    }

    // Required functions for location.
    public void onProviderDisabled(String arg0) {}
    public void onProviderEnabled(String arg0) {}
    public void onStatusChanged(String arg0, int arg1, Bundle arg2) {}

    /**
     * Post location along with user information to ForkMe backend.
     * @param location retrieved from GPS.
     */
    public void postLocationInformation(Location location) {
        double latitude = location.getLatitude();
        double longitude = location.getLongitude();
Answer:         PostLocationDataBody dataBody = new PostLocationDataBody(