Deleted files, added files, fixed for android v6

master
Keith Irwin 6 years ago
parent 8112e672d5
commit d9444a192d
No known key found for this signature in database
GPG Key ID: 378933C743E2BBC0

79
.gitignore vendored

@ -0,0 +1,79 @@
# Created by https://www.gitignore.io/api/android,linux
### Android ###
# Built application files
*.apk
*.ap_
# Files for the ART/Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
out/
# Gradle files
.gradle/
build/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
# Android Studio Navigation editor temp files
.navigation/
# Android Studio captures folder
captures/
# Intellij
*.iml
.idea/workspace.xml
.idea/tasks.xml
.idea/gradle.xml
.idea/libraries
# Keystore files
*.jks
# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
# Google Services (e.g. APIs or Firebase)
google-services.json
# Freeline
freeline.py
freeline/
freeline_project_description.json
### Android Patch ###
gen-external-apklibs
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
# End of https://www.gitignore.io/api/android,linux

@ -0,0 +1,231 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectCodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS">
<value>
<option name="CLASS_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
<option name="NAMES_COUNT_TO_USE_IMPORT_ON_DEMAND" value="99" />
<option name="PACKAGES_TO_USE_IMPORT_ON_DEMAND">
<value />
</option>
<option name="IMPORT_LAYOUT_TABLE">
<value>
<package name="android" withSubpackages="true" static="false" />
<emptyLine />
<package name="com" withSubpackages="true" static="false" />
<emptyLine />
<package name="junit" withSubpackages="true" static="false" />
<emptyLine />
<package name="net" withSubpackages="true" static="false" />
<emptyLine />
<package name="org" withSubpackages="true" static="false" />
<emptyLine />
<package name="java" withSubpackages="true" static="false" />
<emptyLine />
<package name="javax" withSubpackages="true" static="false" />
<emptyLine />
<package name="" withSubpackages="true" static="false" />
<emptyLine />
<package name="" withSubpackages="true" static="true" />
<emptyLine />
</value>
</option>
<option name="RIGHT_MARGIN" value="100" />
<AndroidXmlCodeStyleSettings>
<option name="USE_CUSTOM_SETTINGS" value="true" />
</AndroidXmlCodeStyleSettings>
<Objective-C-extensions>
<option name="GENERATE_INSTANCE_VARIABLES_FOR_PROPERTIES" value="ASK" />
<option name="RELEASE_STYLE" value="IVAR" />
<option name="TYPE_QUALIFIERS_PLACEMENT" value="BEFORE" />
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions>
<pair source="cpp" header="h" />
<pair source="c" header="h" />
</extensions>
</Objective-C-extensions>
<XML>
<option name="XML_KEEP_LINE_BREAKS" value="false" />
<option name="XML_ALIGN_ATTRIBUTES" value="false" />
<option name="XML_SPACE_INSIDE_EMPTY_TAG" value="true" />
</XML>
<codeStyleSettings language="XML">
<option name="FORCE_REARRANGE_MODE" value="1" />
<indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" />
</indentOptions>
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_width</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_height</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:layout_.*</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:width</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:height</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</value>
</option>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default (1)" />
</component>
</project>

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
<entry name="!?*.aj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>

@ -0,0 +1,3 @@
<component name="CopyrightManager">
<settings default="" />
</component>

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/Tracman.iml" filepath="$PROJECT_DIR$/Tracman.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
</modules>
</component>
</project>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

1
app/.gitignore vendored

@ -1 +0,0 @@
/build

@ -0,0 +1,46 @@
apply plugin: 'com.android.application'
android {
signingConfigs {
config {
keyAlias 'TracmanKey'
keyPassword 'Gyt223qw!'
storeFile file('/home/keith/code/Android/Tracman/app/keystore.jks')
storePassword 'Gyt223qw!'
}
}
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
applicationId "us.keithirwin.tracman"
minSdkVersion 14
targetSdkVersion 23
versionCode 9
versionName "0.1.8"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.config
zipAlignEnabled true
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.2.0'
compile 'com.android.support:support-v4:23.2.0'
compile 'com.android.support:design:23.2.0'
compile 'com.google.android.gms:play-services-location:9.8.0'
compile 'com.google.android.gms:play-services-auth:9.8.0'
compile ('com.github.nkzawa:socket.io-client:0.4.1'){
exclude group: 'org.json', module: 'json'
}
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta3'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta3'
}
apply plugin: 'com.google.gms.google-services'

@ -16,6 +16,7 @@
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".LoginActivity">
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.MAIN"/>
@ -23,21 +24,14 @@
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:parentActivityName=".LoginActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="us.keithirwin.tracman.LoginActivity"/>
</activity>
<activity
android:name=".SettingsActivity"
android:label="@string/settings_name"
android:parentActivityName=".MainActivity">
android:parentActivityName=".LoginActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity"/>
android:value=".LoginActivity"/>
</activity>
<service

@ -1,5 +1,7 @@
package us.keithirwin.tracman;
import android.Manifest;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
@ -8,13 +10,18 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.BitmapFactory;
//import android.content.pm.PackageManager;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
//import android.support.v4.app.ActivityCompat;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.NotificationCompat;
//import android.support.v4.content.ContextCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import com.google.android.gms.common.ConnectionResult;
@ -32,6 +39,7 @@ import org.json.JSONObject;
import java.net.URISyntaxException;
public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
public LocationService() {}
@ -44,6 +52,7 @@ public class LocationService extends Service implements GoogleApiClient.Connecti
Location mLastLocation;
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
@ -139,14 +148,19 @@ public class LocationService extends Service implements GoogleApiClient.Connecti
private int getPrioritySetting() {
return Integer.parseInt(sharedPref.getString("broadcast_priority", "100"));
}
private int getIntervalSetting() {
return Integer.parseInt(
sharedPref.getString("broadcast_frequency",
getResources().getString(R.string.pref_default_broadcast_frequency)));
}
public static boolean checkLocationPermission(final Context context) {
return ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
void connectLocationUpdates(Integer interval, Integer priority) {
// Set update parameters
if (mLocationRequest != null) {
mLocationRequest.setPriority(priority);
mLocationRequest.setInterval(interval * 1000); // 1000 = 1 second
@ -155,19 +169,41 @@ public class LocationService extends Service implements GoogleApiClient.Connecti
connectLocationUpdates(getIntervalSetting(), getPrioritySetting());
}
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient,
mLocationRequest,
this);
// Get permission
if (!checkLocationPermission(this)) {
Log.d(TAG, "Location permission denied");
} else {
mGoogleApiClient.connect();
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
Log.d(TAG, "Location permission granted");
// Request location updates
if (mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient,
mLocationRequest,
this);
} else {
mGoogleApiClient.connect();
}
// Get last location
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
}
// if ( ContextCompat.checkSelfPermission( this, android.Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) {
// ActivityCompat.requestPermissions( this, new String[] { android.Manifest.permission.ACCESS_FINE_LOCATION },
// LocationService.MY_FINE_LOCATION_PERMISSION );
// } else {
//
//
//
// }
// Set location if there is one
if (mLastLocation != null) {
onLocationChanged(mLastLocation);
}
}
@Override

@ -56,12 +56,9 @@ public class LoginActivity extends AppCompatActivity implements
// Configure sign-in to request the user's ID and basic profile, included in DEFAULT_SIGN_IN.
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(GOOGLE_WEB_CLIENT_ID)
.requestEmail()
.build();
// Set up buttons
SignInButton signInButton = (SignInButton) findViewById(R.id.google_sign_in_button);
signInButton.setStyle(SignInButton.SIZE_WIDE, SignInButton.COLOR_DARK, gso.getScopeArray());
// Build a GoogleApiClient with access to the Google Sign-In API and the
// options specified by gso.
mGoogleApiClient = new GoogleApiClient.Builder(this)
@ -69,6 +66,10 @@ public class LoginActivity extends AppCompatActivity implements
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
// Set up buttons
SignInButton signInButton = (SignInButton) findViewById(R.id.google_sign_in_button);
signInButton.setStyle(SignInButton.SIZE_WIDE, SignInButton.COLOR_AUTO);
// Button listeners
findViewById(R.id.google_sign_in_button).setOnClickListener(this);
}
@ -127,6 +128,7 @@ public class LoginActivity extends AppCompatActivity implements
.url(SERVER_ADDRESS+"auth/google/idtoken?id_token="+token)
.build();
Log.d(TAG, "Attempting Tracman signin with token: " + token);
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Request request, IOException throwable) {
@ -140,7 +142,7 @@ public class LoginActivity extends AppCompatActivity implements
if (!res.isSuccessful()) {
showError(R.string.login_no_user_error);
res.body().close();
throw new IOException("Unexpected code " + res);
throw new IOException("Unexpected code: " + res);
} else {
Log.d(TAG, "Response code: " + res.code());
String userString = res.body().string();
@ -170,7 +172,7 @@ public class LoginActivity extends AppCompatActivity implements
editor.putString("loggedInUserSk", userSK);
editor.commit();
startActivity(new Intent(getBaseContext(), MainActivity.class));
startActivity(new Intent(getBaseContext(), SettingsActivity.class));
}
}
});
@ -195,7 +197,7 @@ public class LoginActivity extends AppCompatActivity implements
}
}
private void googleSignIn() {
private void signIn() {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
@ -235,7 +237,7 @@ public class LoginActivity extends AppCompatActivity implements
public void onClick(View v) {
switch (v.getId()) {
case R.id.google_sign_in_button:
googleSignIn();
signIn();
break;
}
}

@ -1,186 +0,0 @@
package us.keithirwin.tracman;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.support.v4.widget.DrawerLayout;
import values.AboutFragment;
import values.MainFragment;
public class MainActivity extends AppCompatActivity implements
NavigationDrawerFragment.NavigationDrawerCallbacks,
MainFragment.OnMapButtonPressedListener,
AboutFragment.OnBackButtonPressedListener {
private static final String TAG = "MainActivity";
// private CharSequence mTitle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (BuildConfig.DEBUG){ Log.d(TAG, "Created in debug mode"); }
setContentView(R.layout.activity_main);
NavigationDrawerFragment mNavigationDrawerFragment = (NavigationDrawerFragment)
getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
// mTitle = getTitle();
// Set up the drawer.
Log.d(TAG, "Setting up drawer");
mNavigationDrawerFragment.setUp(
R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout)
);
// Check if gps enabled and start location service
Log.d(TAG, "Checking if gps enabled");
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
if (sharedPref.getBoolean("gps_switch", false)) {
Log.d(TAG, "Starting LocationService");
this.startService(new Intent(this, LocationService.class));
}
}
@Override
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
Log.v(TAG, "onNavigationDrawerItemSelected() called");
Fragment fragment;
FragmentManager fragmentManager = getSupportFragmentManager();
switch(position) {
default:
case 0:
Log.d(TAG, "Sending intent to go to main fragment");
// Get user ID and name
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
final String mUserID = sharedPref.getString("loggedInUserId", null);
final String mUserName = sharedPref.getString("loggedInUserName", null);
if (mUserID == null) {
startActivity(new Intent(this, LoginActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP));
}
fragment = MainFragment.newInstance(mUserName, mUserID);
break;
case 1:
Log.v(TAG, "Sending intent to go to Settings Activity");
fragment = null;
startActivity(new Intent(this, SettingsActivity.class)
.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP));
break;
case 2:
Log.v(TAG, "Sending intent to go to about fragment");
fragment = AboutFragment.newInstance();
break;
case 3:
Log.v(TAG, "Sending intent to go to logout fragment");
fragment = null;
Log.d(TAG, "Sending intent to log out");
// Stop LocationService
stopService(new Intent(this, LocationService.class));
// Send back to login screen
startActivity(new Intent(this, LoginActivity.class)
.putExtra("method", "signOut")
.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP));
break;
}
if (fragment!=null) {
fragmentManager.beginTransaction()
.replace(R.id.container, fragment)
.commit();
}
}
public void onSectionAttached(int number) {
switch (number) {
case 0:
// mTitle = getString(R.string.main_name);
// Toast.makeText(this, "main", Toast.LENGTH_SHORT).show();
break;
case 1:
// mTitle = getString(R.string.settings_name);
// Log.d(TAG, "Sending intent to go to settings");
// startActivity(new Intent(this, SettingsActivity.class)
// .setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP));
break;
case 2:
// mTitle = getString(R.string.about_name);
break;
// case 3:
// break;
}
}
public void goBack() {
onNavigationDrawerItemSelected(0);
}
public void showMap(String UserId) {
String url = "https://tracman.org/trac/id/" + UserId;
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
}
// public void restoreActionBar() {
// ActionBar actionBar = getActionBar();
// actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
// actionBar.setDisplayShowTitleEnabled(true);
// actionBar.setTitle(mTitle);
// }
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
public PlaceholderFragment() {}
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
((MainActivity) context).onSectionAttached(getArguments().getInt(ARG_SECTION_NUMBER));
}
}
}

@ -1,265 +0,0 @@
package us.keithirwin.tracman;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Toast;
/**
* Fragment used for managing interactions for and presentation of a navigation drawer.
* See the <a href="https://developer.android.com/design/patterns/navigation-drawer.html#Interaction">
* design guidelines</a> for a complete explanation of the behaviors implemented here.
*/
public class NavigationDrawerFragment extends Fragment {
private static final String TAG = "NavDrawerFrag";
/**
* Remember the position of the selected item.
*/
private static final String STATE_SELECTED_POSITION = "selected_navigation_drawer_position";
/**
* A pointer to the current callbacks instance (the Activity).
*/
private NavigationDrawerCallbacks mCallbacks;
/**
* Helper component that ties the action bar to the navigation drawer.
*/
private ActionBarDrawerToggle mDrawerToggle;
private DrawerLayout mDrawerLayout;
private ListView mDrawerListView;
private View mFragmentContainerView;
private int mCurrentSelectedPosition = 0;
// public NavigationDrawerFragment() {}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mCurrentSelectedPosition = savedInstanceState.getInt(STATE_SELECTED_POSITION);
}
// Select either the default item (0) or the last selected item.
selectItem(mCurrentSelectedPosition);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Indicate that this fragment would like to influence the set of actions in the action bar.
setHasOptionsMenu(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mDrawerListView = (ListView) inflater.inflate(
R.layout.drawer, container, false);
mDrawerListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position);
}
});
mDrawerListView.setAdapter(new ArrayAdapter<>(
getActionBar().getThemedContext(),
android.R.layout.simple_list_item_activated_1,
// android.R.id.text1,
new String[]{
getString(R.string.main_name),
getString(R.string.settings_name),
getString(R.string.about_name),
getString(R.string.logout_name)
}));
mDrawerListView.setItemChecked(mCurrentSelectedPosition, true);
return mDrawerListView;
}
// public boolean isDrawerOpen() {
// return mDrawerLayout != null && mDrawerLayout.isDrawerOpen(mFragmentContainerView);
// }
/**
* Users of this fragment must call this method to set up the navigation drawer interactions.
*
* @param fragmentId The android:id of this fragment in its activity's layout.
* @param drawerLayout The DrawerLayout containing this fragment's UI.
*/
public void setUp(int fragmentId, DrawerLayout drawerLayout) {
mFragmentContainerView = getActivity().findViewById(fragmentId);
mDrawerLayout = drawerLayout;
// set a custom shadow that overlays the main content when the drawer opens
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
// set up the drawer's list view with items and click listener
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
// ActionBarDrawerToggle ties together the the proper interactions
// between the navigation drawer and the action bar app icon.
mDrawerToggle = new ActionBarDrawerToggle(
getActivity(), /* host Activity */
mDrawerLayout, /* DrawerLayout object */
R.string.navigation_drawer_open, /* "open drawer" description for accessibility */
R.string.navigation_drawer_close /* "close drawer" description for accessibility */
) {
@Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
if (!isAdded()) {
return;
}
getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
}
@Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
if (!isAdded()) {
return;
}
getActivity().invalidateOptionsMenu(); // calls onPrepareOptionsMenu()
}
};
// Defer code dependent on restoration of previous instance state.
mDrawerLayout.post(new Runnable() {
@Override
public void run() {
mDrawerToggle.syncState();
}
});
mDrawerLayout.addDrawerListener(mDrawerToggle);
}
private void selectItem(int position) {
Log.v(TAG, "selectItem() called");
mCurrentSelectedPosition = position;
if (mDrawerListView != null) {
Log.v(TAG, "mDrawerListView != null"); //
mDrawerListView.setItemChecked(position, true);
}
if (mDrawerLayout != null) {
Log.v(TAG, "mDrawerLayout != null"); //
mDrawerLayout.closeDrawer(mFragmentContainerView);
}
if (mCallbacks != null) {
Log.v(TAG, "mCallbacks != null");
mCallbacks.onNavigationDrawerItemSelected(position);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
mCallbacks = (NavigationDrawerCallbacks) context;
} catch (ClassCastException e) {
throw new ClassCastException("Activity must implement NavigationDrawerCallbacks.");
}
}
@Override
public void onDetach() {
super.onDetach();
mCallbacks = null;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt(STATE_SELECTED_POSITION, mCurrentSelectedPosition);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// Forward the new configuration the drawer toggle component.
mDrawerToggle.onConfigurationChanged(newConfig);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
// Show the global app actions in the action bar. See also
// showGlobalContextActionBar, which controls the top-left area of the action bar.
inflater.inflate(R.menu.global, menu);
showGlobalContextActionBar();
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
if (item.getItemId() == R.id.help_action) {
Toast.makeText(getActivity(), "Help is on the way! ", Toast.LENGTH_SHORT).show();
// TODO: help activity
return true;
} else if (item.getItemId() == R.id.suggestions_action) {
String url = "https://tracman.org/suggestion";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
return true;
} else if (item.getItemId() == R.id.bugs_action) {
String url = "https://tracman.org/bug?source=android";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
startActivity(i);
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* Per the navigation drawer design guidelines, updates the action bar to show the global app
* 'context', rather than just what's in the current screen.
*/
private void showGlobalContextActionBar() {
ActionBar actionBar = getActionBar();
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setTitle(R.string.app_name);
}
private ActionBar getActionBar() {
return ((AppCompatActivity) getActivity()).getSupportActionBar();
}
/**
* Callbacks interface that all activities using this fragment must implement.
*/
public interface NavigationDrawerCallbacks {
/**
* Called when an item in the navigation drawer is selected.
*/
void onNavigationDrawerItemSelected(int position);
}
}

@ -1,16 +1,20 @@
package us.keithirwin.tracman;
import android.Manifest;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Build;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBar;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
@ -19,6 +23,7 @@ import android.view.MenuItem;
import java.util.List;
/**
* A {@link PreferenceActivity} that presents a set of application settings. On
* handset devices, settings are presented as a single list. On tablets,
@ -33,6 +38,8 @@ import java.util.List;
public class SettingsActivity extends AppCompatPreferenceActivity {
private static final String TAG = "SettingsActivity";
private static int MY_FINE_LOCATION_PERMISSION = 425;
/**
* A preference value change listener that updates the preference's summary
* to reflect its new value.
@ -105,16 +112,33 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
}
}
private void showLocationPermissionDialog() {
if (!LocationService.checkLocationPermission(this)) {
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_FINE_LOCATION_PERMISSION);
}
}
@Override
protected void onStop() {
Log.d(TAG, "onStop called");
super.onStop();
// Restart service so settings can take effect
stopService(new Intent(this, LocationService.class));
SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
if (sharedPref.getBoolean("gps_switch", false)) {
// Ask for location permissions (can't be done in service, only activity)
showLocationPermissionDialog();
// Start location tracking service
Log.d(TAG, "Starting LocationService");
startService(new Intent(this, LocationService.class));
}
}

@ -1,95 +0,0 @@
package values;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import us.keithirwin.tracman.R;
/**
* A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link AboutFragment.OnBackButtonPressedListener} interface
* to handle interaction events.
* Use the {@link AboutFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class AboutFragment extends Fragment {
private OnBackButtonPressedListener mListener;
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @return A new instance of fragment AboutFragment.
*/
public static AboutFragment newInstance() {
AboutFragment fragment = new AboutFragment();
return fragment;
} public AboutFragment() {}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getActivity().setTitle(R.string.about_name);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_about, container, false);
TextView tv = (TextView) view.findViewById(R.id.about_license);
tv.setMovementMethod(LinkMovementMethod.getInstance());
view.findViewById(R.id.about_back_button).setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
goBack();
}
});
return view;
}
public void goBack() {
if (mListener != null) {
mListener.goBack();
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnBackButtonPressedListener) {
mListener = (OnBackButtonPressedListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p/>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnBackButtonPressedListener {
void goBack();
}
}

@ -1,108 +0,0 @@
package values;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import us.keithirwin.tracman.R;
/**
* A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* {@link MainFragment.OnMapButtonPressedListener} interface
* to handle interaction events.
* Use the {@link MainFragment#newInstance} factory method to
* create an instance of this fragment.
*/
public class MainFragment extends Fragment {
private static final String USER_NAME = "UserName";
private static final String USER_ID = "UserId";
private String mUserName, mUserId;
private OnMapButtonPressedListener mButtonPressedListener;
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param userName Name of the logged-in user.
* @param userID ID of the logged-in user.
* @return A new instance of fragment MainFragment.
*/
public static MainFragment newInstance(String userName, String userID) {
MainFragment fragment = new MainFragment();
Bundle args = new Bundle();
args.putString(USER_NAME, userName);
args.putString(USER_ID, userID);
fragment.setArguments(args);
return fragment;
} public MainFragment() {}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mUserName = getArguments().getString(USER_NAME);
mUserId = getArguments().getString(USER_ID);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, container, false);
if (mUserName!=null) {
TextView tv = (TextView) view.findViewById(R.id.named_welcome);
tv.setText(getString(R.string.named_welcome, " "+mUserName));
}
view.findViewById(R.id.tracpage_button).setOnClickListener( new View.OnClickListener() {
public void onClick(View v) {
showMap();
}
});
return view;
}
public void showMap () {
if (mButtonPressedListener != null) {
mButtonPressedListener.showMap(mUserId);
}
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnMapButtonPressedListener) {
mButtonPressedListener = (OnMapButtonPressedListener) context;
} else {
throw new RuntimeException(context.toString() + " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mButtonPressedListener = null;
}
/**
* This interface must be implemented by activities that contain this
* fragment to allow an interaction in this fragment to be communicated
* to the activity and potentially other fragments contained in that
* activity.
* <p/>
* See the Android Training lesson <a href=
* "http://developer.android.com/training/basics/fragments/communicating.html"
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnMapButtonPressedListener {
void showMap(String UserId);
}
}

@ -1,23 +0,0 @@
<!-- A DrawerLayout is intended to be used as the top-level content view using match_parent for both width and height to consume the full space available. -->
<android.support.v4.widget.DrawerLayout
android:id="@+id/drawer_layout"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="us.keithirwin.tracman.MainActivity">
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<fragment
android:id="@+id/navigation_drawer"
android:name="us.keithirwin.tracman.NavigationDrawerFragment"
android:layout_width="@dimen/navigation_drawer_width"
android:layout_height="match_parent"
android:layout_gravity="start"
tools:layout="@layout/drawer"/>
</android.support.v4.widget.DrawerLayout>

@ -1,9 +0,0 @@
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#333"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
tools:context="us.keithirwin.tracman.NavigationDrawerFragment"/>

@ -1,95 +0,0 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="values.AboutFragment">
<LinearLayout
android:id="@+id/main_layout"
android:orientation="vertical"
android:weightSum="6"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="us.keithirwin.tracman.MainActivity"
android:clickable="true">
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/logo_description"
android:padding="5dp"
android:src="@drawable/logo_by"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true" />
<TextView
android:id="@+id/about_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="60dp"
android:layout_marginStart="60dp"
android:gravity="center"