commit a81902980b5ec90c8f047b8ca053625eeb28449e Author: keith24 Date: Mon Mar 21 20:30:53 2016 -0400 init commit diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/app-release.apk b/app/app-release.apk new file mode 100644 index 0000000..28ae28b Binary files /dev/null and b/app/app-release.apk differ diff --git a/app/keystore.jks b/app/keystore.jks new file mode 100644 index 0000000..1109e72 Binary files /dev/null and b/app/keystore.jks differ diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..7813b38 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,29 @@ +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in /home/keith/.AndroidStudio1.4/sdk/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the proguardFiles +# directive in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +#-keep class org.codehaus.** {*;} +#-dontwarn -dontwarn org.codehaus.** +#-keep class com.ocpsoft.** {*;} +#-dontwarn com.ocpsoft.** +#-keep class java.nio.** {*;} +#-dontwarn java.nio.** + +#-dontwarn com.squareup.** +#-dontwarn org.json.** + +-dontwarn * + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} \ No newline at end of file diff --git a/app/src/androidTest/java/us/keithirwin/tracman/ApplicationTest.java b/app/src/androidTest/java/us/keithirwin/tracman/ApplicationTest.java new file mode 100644 index 0000000..a97d70a --- /dev/null +++ b/app/src/androidTest/java/us/keithirwin/tracman/ApplicationTest.java @@ -0,0 +1,13 @@ +package us.keithirwin.tracman; + +import android.app.Application; +import android.test.ApplicationTestCase; + +/** + * Testing Fundamentals + */ +public class ApplicationTest extends ApplicationTestCase { + public ApplicationTest() { + super(Application.class); + } +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..00cc7a9 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/java/us/keithirwin/tracman/AppCompatPreferenceActivity.java b/app/src/main/java/us/keithirwin/tracman/AppCompatPreferenceActivity.java new file mode 100644 index 0000000..a2d552a --- /dev/null +++ b/app/src/main/java/us/keithirwin/tracman/AppCompatPreferenceActivity.java @@ -0,0 +1,109 @@ +package us.keithirwin.tracman; + +import android.content.res.Configuration; +import android.os.Bundle; +import android.preference.PreferenceActivity; +import android.support.annotation.LayoutRes; +import android.support.annotation.Nullable; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatDelegate; +import android.support.v7.widget.Toolbar; +import android.view.MenuInflater; +import android.view.View; +import android.view.ViewGroup; + +/** + * A {@link android.preference.PreferenceActivity} which implements and proxies the necessary calls + * to be used with AppCompat. + */ +public abstract class AppCompatPreferenceActivity extends PreferenceActivity { + + private AppCompatDelegate mDelegate; + + @Override + protected void onCreate(Bundle savedInstanceState) { + getDelegate().installViewFactory(); + getDelegate().onCreate(savedInstanceState); + super.onCreate(savedInstanceState); + } + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + getDelegate().onPostCreate(savedInstanceState); + } + + public ActionBar getSupportActionBar() { + return getDelegate().getSupportActionBar(); + } + + public void setSupportActionBar(@Nullable Toolbar toolbar) { + getDelegate().setSupportActionBar(toolbar); + } + + @Override + public MenuInflater getMenuInflater() { + return getDelegate().getMenuInflater(); + } + + @Override + public void setContentView(@LayoutRes int layoutResID) { + getDelegate().setContentView(layoutResID); + } + + @Override + public void setContentView(View view) { + getDelegate().setContentView(view); + } + + @Override + public void setContentView(View view, ViewGroup.LayoutParams params) { + getDelegate().setContentView(view, params); + } + + @Override + public void addContentView(View view, ViewGroup.LayoutParams params) { + getDelegate().addContentView(view, params); + } + + @Override + protected void onPostResume() { + super.onPostResume(); + getDelegate().onPostResume(); + } + + @Override + protected void onTitleChanged(CharSequence title, int color) { + super.onTitleChanged(title, color); + getDelegate().setTitle(title); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + getDelegate().onConfigurationChanged(newConfig); + } + + @Override + protected void onStop() { + super.onStop(); + getDelegate().onStop(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + getDelegate().onDestroy(); + } + + public void invalidateOptionsMenu() { + getDelegate().invalidateOptionsMenu(); + } + + private AppCompatDelegate getDelegate() { + if (mDelegate == null) { + mDelegate = AppCompatDelegate.create(this, null); + } + return mDelegate; + } +} diff --git a/app/src/main/java/us/keithirwin/tracman/BootReceiver.java b/app/src/main/java/us/keithirwin/tracman/BootReceiver.java new file mode 100644 index 0000000..703d718 --- /dev/null +++ b/app/src/main/java/us/keithirwin/tracman/BootReceiver.java @@ -0,0 +1,20 @@ +package us.keithirwin.tracman; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; + +public class BootReceiver extends BroadcastReceiver { + public BootReceiver() {} + + @Override + public void onReceive(Context context, Intent intent) { + // Starts location service on boot + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + if (prefs.getBoolean("pref_start_boot", true)) { + context.startService(new Intent(context, LocationService.class)); + } + } +} diff --git a/app/src/main/java/us/keithirwin/tracman/LocationService.java b/app/src/main/java/us/keithirwin/tracman/LocationService.java new file mode 100644 index 0000000..9db726c --- /dev/null +++ b/app/src/main/java/us/keithirwin/tracman/LocationService.java @@ -0,0 +1,247 @@ +package us.keithirwin.tracman; + +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.SharedPreferences; +import android.graphics.BitmapFactory; +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.NotificationCompat; +import android.util.Log; + +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.location.LocationListener; +import com.google.android.gms.location.LocationRequest; +import com.google.android.gms.location.LocationServices; + +import com.github.nkzawa.emitter.Emitter; +import com.github.nkzawa.socketio.client.IO; +import com.github.nkzawa.socketio.client.Socket; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.net.URISyntaxException; + +public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks, + GoogleApiClient.OnConnectionFailedListener, LocationListener { + public LocationService() {} + private String TAG = "LocationService"; + + private Socket mSocket; + private String mUserID; + private SharedPreferences sharedPref; + Location mLastLocation; + private GoogleApiClient mGoogleApiClient; + private LocationRequest mLocationRequest; + synchronized void buildGoogleApiClient() { + mGoogleApiClient = new GoogleApiClient.Builder(this) + .addConnectionCallbacks(this) + .addOnConnectionFailedListener(this) + .addApi(LocationServices.API) + .build(); + } + + @Nullable + private NotificationManager mNotificationManager; + private final NotificationCompat.Builder mNotificationBuilder = new NotificationCompat.Builder(this); + private void setupNotifications(Boolean persist) { + if (mNotificationManager == null) { + mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); + } + PendingIntent notificationIntent = PendingIntent.getActivity(this, 0, + new Intent(this, SettingsActivity.class) + .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP), + 0); + mNotificationBuilder + .setPriority(-1) + .setSmallIcon(R.drawable.logo_white) +// .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.logo_by)) + .setCategory(NotificationCompat.CATEGORY_SERVICE) + .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) + .setContentTitle(getText(R.string.app_name)) +// .setWhen(System.currentTimeMillis()) + .setContentIntent(notificationIntent) + .setOngoing(persist); + } + private void showNotification(CharSequence text, Boolean active) { + mNotificationBuilder + .setTicker(text) + .setContentText(text); + if (active) { + mNotificationBuilder.setSmallIcon(R.drawable.logo_white); + } else { + mNotificationBuilder.setSmallIcon(R.drawable.logo_trans); + } + if (mNotificationManager != null) { + mNotificationManager.notify(1, mNotificationBuilder.build()); + } + } + + private final BroadcastReceiver LowPowerReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + connectLocationUpdates(300, LocationRequest.PRIORITY_NO_POWER); + Log.d(TAG, "Priority and interval lowered due to low power"); + } + }; + + @Override + public void onCreate() { + super.onCreate(); + Log.d(TAG, "onCreate called"); + + // Get preferences + sharedPref = PreferenceManager.getDefaultSharedPreferences(this); + + setupNotifications(true); + showNotification(getText(R.string.connecting), false); + Log.d(TAG, "Notification set up"); + + buildGoogleApiClient(); + Log.d(TAG, "Google API Client built"); + mGoogleApiClient.connect(); + Log.d(TAG, "Connected to Google API Client"); + + IntentFilter lowPowerFilter = new IntentFilter(); + lowPowerFilter.addAction("android.intent.action.BATTERY_LOW"); + registerReceiver(LowPowerReceiver, lowPowerFilter); + Log.d(TAG, "LowPowerReceiver activated"); + + mUserID = sharedPref.getString("loggedInUserId", null); + final String SERVER_ADDRESS = "https://tracman.org/"; + + // Connect to socket + try { + mSocket = IO.socket(SERVER_ADDRESS); + mSocket.on("activate", onActivate); + mSocket.connect(); + mSocket.emit("room", "app-"+mUserID); + Log.d(TAG, "Connected to socket.io server "+SERVER_ADDRESS); + } catch (URISyntaxException e) { + showNotification(getText(R.string.server_connection_error), false); + Log.e(TAG, "Failed to connect to sockets server " + SERVER_ADDRESS, e); + } + showNotification(getText(R.string.connected), false); + } + + 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))); + } + + void connectLocationUpdates(Integer interval, Integer priority) { + if (mLocationRequest != null) { + mLocationRequest.setPriority(priority); + mLocationRequest.setInterval(interval * 1000); // 1000 = 1 second + } else{ + mLocationRequest = LocationRequest.create(); + connectLocationUpdates(getIntervalSetting(), getPrioritySetting()); + } + + if (mGoogleApiClient.isConnected()) { + LocationServices.FusedLocationApi.requestLocationUpdates( + mGoogleApiClient, + mLocationRequest, + this); + } else { + mGoogleApiClient.connect(); + } + mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); + + if (mLastLocation != null) { + onLocationChanged(mLastLocation); + } + } + + @Override + public void onConnected(Bundle bundle) { + Log.d(TAG, "onConnected called"); + + mLocationRequest = LocationRequest.create(); + connectLocationUpdates(getIntervalSetting(), getPrioritySetting()); + showNotification(getString(R.string.realtime_updates), true); + } + + @Override + public IBinder onBind(Intent intent) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void onConnectionFailed(ConnectionResult connectionResult) { + Log.e(TAG, "onConnectionFailed: " + connectionResult); + showNotification(getText(R.string.google_connection_error), false); + buildGoogleApiClient(); + } + + private Emitter.Listener onActivate = new Emitter.Listener() { + @Override + public void call(final Object... args) { + if (args[0].toString().equals("true")) { + Log.d(TAG, "Activating realtime updates"); + connectLocationUpdates(getIntervalSetting(), getPrioritySetting()); + showNotification(getString(R.string.realtime_updates), true); + } else { + Log.d(TAG, "Deactivating realtime updates"); + connectLocationUpdates(300, LocationRequest.PRIORITY_NO_POWER); + showNotification(getString(R.string.occasional_updates), false); + } + } + }; + + @Override + public void onLocationChanged(Location location) { + JSONObject mLocationView = new JSONObject(); + try { + mLocationView.put("usr", mUserID); + mLocationView.put("lat", String.valueOf(location.getLatitude())); + mLocationView.put("lon", String.valueOf(location.getLongitude())); + mLocationView.put("dir", String.valueOf(location.getBearing())); + mLocationView.put("spd", String.valueOf(location.getSpeed())); + } catch (JSONException e) { + Log.e(TAG, "Failed to put JSON data"); + } + mSocket.emit("app", mLocationView); +// Log.v(TAG, "Location updated: " + mLocationView.toString()); + } + + @Override + public void onConnectionSuspended(int i) { + Log.d(TAG, "onConnectionSuspended called"); + showNotification(getText(R.string.google_connection_error), false); + } + + @Override + public void onDestroy() { + super.onDestroy(); + Log.d(TAG, "onDestroy executed"); + + mSocket.disconnect(); + Log.d(TAG, "Disconnected from sockets"); + + mGoogleApiClient.disconnect(); + Log.d(TAG, "Google API disconnected"); + + unregisterReceiver(LowPowerReceiver); + Log.d(TAG, "LowPowerReceiver deactivated"); + + setupNotifications(false); + showNotification(getText(R.string.disconnected), false); + Log.d(TAG, "Notification changed"); + } +} \ No newline at end of file diff --git a/app/src/main/java/us/keithirwin/tracman/LoginActivity.java b/app/src/main/java/us/keithirwin/tracman/LoginActivity.java new file mode 100644 index 0000000..d2235e0 --- /dev/null +++ b/app/src/main/java/us/keithirwin/tracman/LoginActivity.java @@ -0,0 +1,239 @@ +package us.keithirwin.tracman; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.text.method.LinkMovementMethod; +import android.util.Log; +import android.view.View; +import android.widget.TextView; + +import com.google.android.gms.auth.api.Auth; +import com.google.android.gms.auth.api.signin.GoogleSignInAccount; +import com.google.android.gms.auth.api.signin.GoogleSignInOptions; +import com.google.android.gms.auth.api.signin.GoogleSignInResult; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.SignInButton; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.common.api.OptionalPendingResult; +import com.google.android.gms.common.api.ResultCallback; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; + +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Callback; +import okhttp3.Response; + +public class LoginActivity extends AppCompatActivity implements + GoogleApiClient.OnConnectionFailedListener, + View.OnClickListener { + private static final String TAG = "SignInActivity"; + private static final int RC_SIGN_IN = 9001; + private final String SERVER_ADDRESS = "https://tracman.org/"; + private static final String GOOGLE_WEB_CLIENT_ID = "483494341936-hrn0ms1tebgdtfs5f4i6ebmkt3qmo16o.apps.googleusercontent.com"; + + private GoogleApiClient mGoogleApiClient; + private ProgressDialog mProgressDialog; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Set up layout + setContentView(R.layout.activity_login); + setTitle(R.string.login_name); + TextView tv = (TextView) findViewById(R.id.login_description); + tv.setMovementMethod(LinkMovementMethod.getInstance()); + + // 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) + .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) + .enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */) + .addApi(Auth.GOOGLE_SIGN_IN_API, gso) + .build(); + + // Button listeners + findViewById(R.id.google_sign_in_button).setOnClickListener(this); + } + + @Override + public void onStart() { + super.onStart(); + + if (getIntent().hasExtra("method")) { + if (getIntent().getStringExtra("method").equals("signOut")) { + Log.d(TAG, "Got intent to sign out"); + } + + } else { // Try to sign in + OptionalPendingResult opr = Auth.GoogleSignInApi.silentSignIn(mGoogleApiClient); + if (opr.isDone()) { + // If the user's cached credentials are valid, the OptionalPendingResult will be "done" + // and the GoogleSignInResult will be available instantly. + Log.d(TAG, "Got cached sign-in"); + GoogleSignInResult result = opr.get(); + handleSignInResult(result); + } else { + // If the user has not previously signed in on this device or the sign-in has expired, + // this asynchronous branch will attempt to sign in the user silently. Cross-device + // single sign-on will occur in this branch. + showProgressDialog(); + opr.setResultCallback(new ResultCallback() { + @Override + public void onResult(GoogleSignInResult googleSignInResult) { + hideProgressDialog(); + handleSignInResult(googleSignInResult); + } + }); + } + } + + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + + // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...); + if (requestCode == RC_SIGN_IN) { + GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data); + handleSignInResult(result); + } + } + + private void AuthenticateGoogle(final String token) throws Exception { + final OkHttpClient client = new OkHttpClient(); + + Request request = new Request.Builder() + .url(SERVER_ADDRESS+"auth/google/idtoken?id_token="+token) + .build(); + + client.newCall(request).enqueue(new Callback() { + @Override + public void onFailure(Request request, IOException throwable) { + Log.e(TAG, "Failed to connect to server: " + SERVER_ADDRESS + "auth/google/idtoken?id_token=" + token); + showError(R.string.server_connection_error); + throwable.printStackTrace(); + } + + @Override + public void onResponse(Response res) throws IOException { + if (!res.isSuccessful()) { + showError(R.string.login_no_user_error); + res.body().close(); + throw new IOException("Unexpected code " + res); + } else { + Log.d(TAG, "Response code: " + res.code()); + String userString = res.body().string(); + System.out.println("Full response: " + userString); + + String userID, userName; + try { + JSONObject user = new JSONObject(userString); + userID = user.getString("_id"); + userName = user.getString("name"); + Log.v(TAG, "User retrieved with ID: " + userID); + + } catch (JSONException e) { + Log.e(TAG, "Unable to parse user JSON: ", e); + Log.e(TAG, "JSON String used: " + userString); + userID = null; + userName = null; + } + Log.v(TAG, "UserID: " + userID); + + // Save user as loggedInUser + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); + SharedPreferences.Editor editor = sharedPref.edit(); + editor.putString("loggedInUser", userString); + editor.putString("loggedInUserId", userID); + editor.putString("loggedInUserName", userName); + editor.commit(); + + startActivity(new Intent(getBaseContext(), MainActivity.class)); + } + } + }); + } + + private void handleSignInResult(GoogleSignInResult result) { + Log.d(TAG, "handleSignInResult:" + result.isSuccess()); + if (result.isSuccess()) { // Signed in successfully + GoogleSignInAccount acct = result.getSignInAccount(); + String googleToken = acct.getIdToken(); + Log.v(TAG, "Google token: " + googleToken); + try { + AuthenticateGoogle(acct.getIdToken()); + } catch (Exception e) { + Log.e(TAG, "Error sending ID token to backend.", e); + } + } else { + Log.e(TAG, "Failed to log in: "+result.getStatus().getStatusCode()); + if (result.getStatus().getStatusCode()!=4) { + showError(R.string.google_connection_error); + } + } + } + + private void googleSignIn() { + Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient); + startActivityForResult(signInIntent, RC_SIGN_IN); + } + + @Override + public void onConnectionFailed(ConnectionResult connectionResult) { + showError(R.string.disconnected); + Log.d(TAG, "onConnectionFailed:" + connectionResult); + } + + private void showProgressDialog() { + if (mProgressDialog == null) { + mProgressDialog = new ProgressDialog(this); + mProgressDialog.setMessage(getString(R.string.loading)); + mProgressDialog.setIndeterminate(true); + } + mProgressDialog.show(); + } + + private void hideProgressDialog() { + if (mProgressDialog != null && mProgressDialog.isShowing()) { + mProgressDialog.hide(); + } + } + + private void showError(final int errorText) { + final TextView errorTextView = (TextView)findViewById(R.id.login_error); + runOnUiThread(new Runnable() { + @Override + public void run() { + errorTextView.setText(getText(errorText).toString()); + } + }); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.google_sign_in_button: + googleSignIn(); + break; + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/us/keithirwin/tracman/MainActivity.java b/app/src/main/java/us/keithirwin/tracman/MainActivity.java new file mode 100644 index 0000000..2f604cf --- /dev/null +++ b/app/src/main/java/us/keithirwin/tracman/MainActivity.java @@ -0,0 +1,182 @@ +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); + setContentView(R.layout.activity_main); + + NavigationDrawerFragment mNavigationDrawerFragment = (NavigationDrawerFragment) + getSupportFragmentManager().findFragmentById(R.id.navigation_drawer); + mTitle = getTitle(); + + // Set up the drawer. + mNavigationDrawerFragment.setUp( + R.id.navigation_drawer, + (DrawerLayout) findViewById(R.id.drawer_layout)); + + // Check if gps enabled and start location service + 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)); + } + + } + +} diff --git a/app/src/main/java/us/keithirwin/tracman/NavigationDrawerFragment.java b/app/src/main/java/us/keithirwin/tracman/NavigationDrawerFragment.java new file mode 100644 index 0000000..ae577e5 --- /dev/null +++ b/app/src/main/java/us/keithirwin/tracman/NavigationDrawerFragment.java @@ -0,0 +1,265 @@ +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 + * design guidelines 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); + } +} diff --git a/app/src/main/java/us/keithirwin/tracman/SettingsActivity.java b/app/src/main/java/us/keithirwin/tracman/SettingsActivity.java new file mode 100644 index 0000000..ec35794 --- /dev/null +++ b/app/src/main/java/us/keithirwin/tracman/SettingsActivity.java @@ -0,0 +1,232 @@ +package us.keithirwin.tracman; + + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +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.v7.app.ActionBar; +import android.preference.PreferenceFragment; +import android.preference.PreferenceManager; +import android.util.Log; +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, + * settings are split by category, with category headers shown to the left of + * the list of settings. + *

+ * See + * Android Design: Settings for design guidelines and the Settings + * API Guide for more information on developing a Settings UI. + */ +public class SettingsActivity extends AppCompatPreferenceActivity { + private static final String TAG = "SettingsActivity"; + + /** + * A preference value change listener that updates the preference's summary + * to reflect its new value. + */ + private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object value) { + String stringValue = value.toString(); + + if (preference instanceof ListPreference) { + // For list preferences, look up the correct display value in + // the preference's 'entries' list. + ListPreference listPreference = (ListPreference) preference; + int index = listPreference.findIndexOfValue(stringValue); + + // Set the summary to reflect the new value. + preference.setSummary( + index >= 0 + ? listPreference.getEntries()[index] + : null); + } else { + // For all other preferences, set the summary to the value's + // simple string representation. + preference.setSummary(stringValue); + } + return true; + } + }; + + /** + * Helper method to determine if the device has an extra-large screen. For + * example, 10" tablets are extra-large. + */ + private static boolean isXLargeTablet(Context context) { + return (context.getResources().getConfiguration().screenLayout + & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE; + } + + /** + * Binds a preference's summary to its value. More specifically, when the + * preference's value is changed, its summary (line of text below the + * preference title) is updated to reflect the value. The summary is also + * immediately updated upon calling this method. The exact display format is + * dependent on the type of preference. + * + */ + private static void bindPreferenceSummaryToValue(Preference preference) { + // Set the listener to watch for value changes. + preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener); + + // Trigger the listener immediately with the preference's + // current value. + sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, + PreferenceManager + .getDefaultSharedPreferences(preference.getContext()) + .getString(preference.getKey(), "")); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setupActionBar(); + Log.d(TAG, "activity onCreate called"); + + // Get User ID + SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); + String mUserID = sharedPref.getString("loggedInUserId", null); + if (mUserID == null) { + startActivity(new Intent(this, LoginActivity.class).setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)); + } + } + + @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)) { + Log.d(TAG, "Starting LocationService"); + startService(new Intent(this, LocationService.class)); + } + } + + /** + * Set up the {@link android.app.ActionBar}, if the API is available. + */ + private void setupActionBar() { + ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + // Show the Up button in the action bar. + actionBar.setDisplayHomeAsUpEnabled(true); + } + } + + /** + * {@inheritDoc} + */ + @Override + public boolean onIsMultiPane() { + return isXLargeTablet(this); + } + + /** + * {@inheritDoc} + */ + @Override + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public void onBuildHeaders(List

target) { + loadHeadersFromResource(R.xml.pref_headers, target); + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId()==android.R.id.home) { + // Respond to the action bar's Up/Home button + onBackPressed(); + return true; + } + return super.onOptionsItemSelected(item); + } + + /** + * This method stops fragment injection in malicious applications. + * Make sure to deny any unknown fragments here. + */ + protected boolean isValidFragment(String fragmentName) { + return PreferenceFragment.class.getName().equals(fragmentName) + || GeneralPreferenceFragment.class.getName().equals(fragmentName); +// || MapPreferenceFragment.class.getName().equals(fragmentName) +// || NotificationPreferenceFragment.class.getName().equals(fragmentName); + } + + /** + * This fragment shows general preferences only. It is used when the + * activity is showing a two-pane settings UI. + */ + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public static class GeneralPreferenceFragment extends PreferenceFragment { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.pref_general); + setHasOptionsMenu(true); + + // Bind the summary of server address preference to its value + bindPreferenceSummaryToValue(findPreference("broadcast_frequency")); + bindPreferenceSummaryToValue(findPreference("broadcast_priority")); + } + } + + /** + * This fragment shows notification preferences only. It is used when the + * activity is showing a two-pane settings UI. + */ +// @TargetApi(Build.VERSION_CODES.HONEYCOMB) +// public static class NotificationPreferenceFragment extends PreferenceFragment { +// @Override +// public void onCreate(Bundle savedInstanceState) { +// super.onCreate(savedInstanceState); +// addPreferencesFromResource(R.xml.pref_notification); +// setHasOptionsMenu(true); +// +// // Bind the summaries of EditText/List/Dialog/Ringtone preferences +// // to their values. When their values change, their summaries are +// // updated to reflect the new value, per the Android Design +// // guidelines. +// bindPreferenceSummaryToValue(findPreference("notifications_new_message_ringtone")); +// } +// } + + /** + * This fragment shows map preferences only. It is used when the + * activity is showing a two-pane settings UI. + */ +// @TargetApi(Build.VERSION_CODES.HONEYCOMB) +// public static class MapPreferenceFragment extends PreferenceFragment { +// @Override +// public void onCreate(Bundle savedInstanceState) { +// super.onCreate(savedInstanceState); +// addPreferencesFromResource(R.xml.pref_map); +// setHasOptionsMenu(true); +// +// // Bind the summaries of EditText/List/Dialog/Ringtone preferences +// // to their values. When their values change, their summaries are +// // updated to reflect the new value, per the Android Design +// // guidelines. +// bindPreferenceSummaryToValue(findPreference("sync_frequency")); +// } +// } +} diff --git a/app/src/main/java/values/AboutFragment.java b/app/src/main/java/values/AboutFragment.java new file mode 100644 index 0000000..a3b5be8 --- /dev/null +++ b/app/src/main/java/values/AboutFragment.java @@ -0,0 +1,95 @@ +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. + *

+ * See the Android Training lesson Communicating with Other Fragments for more information. + */ + public interface OnBackButtonPressedListener { + void goBack(); + } +} diff --git a/app/src/main/java/values/MainFragment.java b/app/src/main/java/values/MainFragment.java new file mode 100644 index 0000000..e105d2a --- /dev/null +++ b/app/src/main/java/values/MainFragment.java @@ -0,0 +1,108 @@ +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. + *

+ * See the Android Training lesson Communicating with Other Fragments for more information. + */ + public interface OnMapButtonPressedListener { + void showMap(String UserId); + } +} diff --git a/app/src/main/res/drawable-hdpi/drawer_shadow.9.png b/app/src/main/res/drawable-hdpi/drawer_shadow.9.png new file mode 100644 index 0000000..236bff5 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/drawer_shadow.9.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_bug_report_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_bug_report_black_24dp.png new file mode 100644 index 0000000..1bccb1d Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_bug_report_black_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_bug_report_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_bug_report_white_24dp.png new file mode 100644 index 0000000..0c963e1 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_bug_report_white_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_drawer.png b/app/src/main/res/drawable-hdpi/ic_drawer.png new file mode 100644 index 0000000..c59f601 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_drawer.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_exit_to_app_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_exit_to_app_black_24dp.png new file mode 100644 index 0000000..ad0f63e Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_exit_to_app_black_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_exit_to_app_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_exit_to_app_white_24dp.png new file mode 100644 index 0000000..52565d0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_exit_to_app_white_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_feedback_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_feedback_black_24dp.png new file mode 100644 index 0000000..f031685 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_feedback_black_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_feedback_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_feedback_white_24dp.png new file mode 100644 index 0000000..a34168c Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_feedback_white_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_help_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_help_black_24dp.png new file mode 100644 index 0000000..374fafd Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_help_black_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_help_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_help_white_24dp.png new file mode 100644 index 0000000..5664f95 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_help_white_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_info_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_info_black_24dp.png new file mode 100644 index 0000000..da56077 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_info_black_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_info_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_info_white_24dp.png new file mode 100644 index 0000000..00f53ed Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_info_white_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_map_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_map_black_24dp.png new file mode 100644 index 0000000..c81d0e0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_map_black_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_map_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_map_white_24dp.png new file mode 100644 index 0000000..b7631d7 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_map_white_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_notifications_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_notifications_black_24dp.png new file mode 100644 index 0000000..e200012 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_notifications_black_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_notifications_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_notifications_white_24dp.png new file mode 100644 index 0000000..d792f83 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_notifications_white_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_settings_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_settings_black_24dp.png new file mode 100644 index 0000000..acf1ddf Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_settings_black_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_settings_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_settings_white_24dp.png new file mode 100644 index 0000000..97ded33 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_settings_white_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_sync_black_24dp.png b/app/src/main/res/drawable-hdpi/ic_sync_black_24dp.png new file mode 100644 index 0000000..a5ebdbd Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_sync_black_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_sync_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_sync_white_24dp.png new file mode 100644 index 0000000..f0072e1 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_sync_white_24dp.png differ diff --git a/app/src/main/res/drawable-hdpi/logo_black.png b/app/src/main/res/drawable-hdpi/logo_black.png new file mode 100644 index 0000000..bfb1072 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/logo_black.png differ diff --git a/app/src/main/res/drawable-hdpi/logo_by.png b/app/src/main/res/drawable-hdpi/logo_by.png new file mode 100644 index 0000000..4d1ec12 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/logo_by.png differ diff --git a/app/src/main/res/drawable-hdpi/logo_trans.png b/app/src/main/res/drawable-hdpi/logo_trans.png new file mode 100644 index 0000000..fce078c Binary files /dev/null and b/app/src/main/res/drawable-hdpi/logo_trans.png differ diff --git a/app/src/main/res/drawable-hdpi/logo_white.png b/app/src/main/res/drawable-hdpi/logo_white.png new file mode 100644 index 0000000..a49aded Binary files /dev/null and b/app/src/main/res/drawable-hdpi/logo_white.png differ diff --git a/app/src/main/res/drawable-ldpi/logo_by.png b/app/src/main/res/drawable-ldpi/logo_by.png new file mode 100644 index 0000000..f33afce Binary files /dev/null and b/app/src/main/res/drawable-ldpi/logo_by.png differ diff --git a/app/src/main/res/drawable-mdpi/drawer_shadow.9.png b/app/src/main/res/drawable-mdpi/drawer_shadow.9.png new file mode 100644 index 0000000..ffe3a28 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/drawer_shadow.9.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_bug_report_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_bug_report_black_24dp.png new file mode 100644 index 0000000..58aef66 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_bug_report_black_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_bug_report_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_bug_report_white_24dp.png new file mode 100644 index 0000000..86e15f0 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_bug_report_white_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_drawer.png b/app/src/main/res/drawable-mdpi/ic_drawer.png new file mode 100644 index 0000000..1ed2c56 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_drawer.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_exit_to_app_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_exit_to_app_black_24dp.png new file mode 100644 index 0000000..dee407b Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_exit_to_app_black_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_exit_to_app_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_exit_to_app_white_24dp.png new file mode 100644 index 0000000..461be00 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_exit_to_app_white_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_feedback_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_feedback_black_24dp.png new file mode 100644 index 0000000..8be6849 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_feedback_black_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_feedback_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_feedback_white_24dp.png new file mode 100644 index 0000000..389e927 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_feedback_white_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_help_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_help_black_24dp.png new file mode 100644 index 0000000..f6e789b Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_help_black_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_help_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_help_white_24dp.png new file mode 100644 index 0000000..db69962 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_help_white_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_info_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_info_black_24dp.png new file mode 100644 index 0000000..5ef3dc0 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_info_black_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_info_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_info_white_24dp.png new file mode 100644 index 0000000..17faafb Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_info_white_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_map_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_map_black_24dp.png new file mode 100644 index 0000000..bcc500e Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_map_black_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_map_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_map_white_24dp.png new file mode 100644 index 0000000..4edb178 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_map_white_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_notifications_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_notifications_black_24dp.png new file mode 100644 index 0000000..b36475d Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_notifications_black_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_notifications_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_notifications_white_24dp.png new file mode 100644 index 0000000..2a5c93c Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_notifications_white_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_settings_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_settings_black_24dp.png new file mode 100644 index 0000000..c59419c Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_settings_black_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_settings_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_settings_white_24dp.png new file mode 100644 index 0000000..8909c35 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_settings_white_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_sync_black_24dp.png b/app/src/main/res/drawable-mdpi/ic_sync_black_24dp.png new file mode 100644 index 0000000..9685e8e Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_sync_black_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_sync_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_sync_white_24dp.png new file mode 100644 index 0000000..92cf0a7 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_sync_white_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/logo_black.png b/app/src/main/res/drawable-mdpi/logo_black.png new file mode 100644 index 0000000..0821807 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/logo_black.png differ diff --git a/app/src/main/res/drawable-mdpi/logo_by.png b/app/src/main/res/drawable-mdpi/logo_by.png new file mode 100644 index 0000000..ca7cfc7 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/logo_by.png differ diff --git a/app/src/main/res/drawable-mdpi/logo_trans.png b/app/src/main/res/drawable-mdpi/logo_trans.png new file mode 100644 index 0000000..39c43db Binary files /dev/null and b/app/src/main/res/drawable-mdpi/logo_trans.png differ diff --git a/app/src/main/res/drawable-mdpi/logo_white.png b/app/src/main/res/drawable-mdpi/logo_white.png new file mode 100644 index 0000000..6e95a12 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/logo_white.png differ diff --git a/app/src/main/res/drawable-v21/ic_info_black_24dp.xml b/app/src/main/res/drawable-v21/ic_info_black_24dp.xml new file mode 100644 index 0000000..2d5b793 --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_info_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-v21/ic_notifications_black_24dp.xml b/app/src/main/res/drawable-v21/ic_notifications_black_24dp.xml new file mode 100644 index 0000000..c386cfa --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_notifications_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable-v21/ic_sync_black_24dp.xml b/app/src/main/res/drawable-v21/ic_sync_black_24dp.xml new file mode 100644 index 0000000..56d17a2 --- /dev/null +++ b/app/src/main/res/drawable-v21/ic_sync_black_24dp.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xhdpi/drawer_shadow.9.png b/app/src/main/res/drawable-xhdpi/drawer_shadow.9.png new file mode 100644 index 0000000..fabe9d9 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/drawer_shadow.9.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_bug_report_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_bug_report_black_24dp.png new file mode 100644 index 0000000..107f74a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_bug_report_black_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_bug_report_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_bug_report_white_24dp.png new file mode 100644 index 0000000..36b826b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_bug_report_white_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_drawer.png b/app/src/main/res/drawable-xhdpi/ic_drawer.png new file mode 100644 index 0000000..a5fa74d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_drawer.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_exit_to_app_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_exit_to_app_black_24dp.png new file mode 100644 index 0000000..5a536d5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_exit_to_app_black_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_exit_to_app_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_exit_to_app_white_24dp.png new file mode 100644 index 0000000..07847bd Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_exit_to_app_white_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_feedback_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_feedback_black_24dp.png new file mode 100644 index 0000000..63bec23 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_feedback_black_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_feedback_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_feedback_white_24dp.png new file mode 100644 index 0000000..0063b2f Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_feedback_white_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_help_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_help_black_24dp.png new file mode 100644 index 0000000..d3542c6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_help_black_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_help_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_help_white_24dp.png new file mode 100644 index 0000000..2d11cf4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_help_white_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_info_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_info_black_24dp.png new file mode 100644 index 0000000..46ed12a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_info_black_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_info_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_info_white_24dp.png new file mode 100644 index 0000000..1cedec1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_info_white_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_map_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_map_black_24dp.png new file mode 100644 index 0000000..a3ecc71 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_map_black_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_map_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_map_white_24dp.png new file mode 100644 index 0000000..301162e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_map_white_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_notifications_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_notifications_black_24dp.png new file mode 100644 index 0000000..7de8581 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_notifications_black_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_notifications_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_notifications_white_24dp.png new file mode 100644 index 0000000..9718ccf Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_notifications_white_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_settings_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_settings_black_24dp.png new file mode 100644 index 0000000..e84e188 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_settings_black_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_settings_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_settings_white_24dp.png new file mode 100644 index 0000000..5caedc8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_settings_white_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_sync_black_24dp.png b/app/src/main/res/drawable-xhdpi/ic_sync_black_24dp.png new file mode 100644 index 0000000..860a5db Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_sync_black_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_sync_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_sync_white_24dp.png new file mode 100644 index 0000000..7a7a771 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_sync_white_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/logo_black.png b/app/src/main/res/drawable-xhdpi/logo_black.png new file mode 100644 index 0000000..f08598a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/logo_black.png differ diff --git a/app/src/main/res/drawable-xhdpi/logo_by.png b/app/src/main/res/drawable-xhdpi/logo_by.png new file mode 100644 index 0000000..152d83b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/logo_by.png differ diff --git a/app/src/main/res/drawable-xhdpi/logo_trans.png b/app/src/main/res/drawable-xhdpi/logo_trans.png new file mode 100644 index 0000000..9a5bfe4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/logo_trans.png differ diff --git a/app/src/main/res/drawable-xhdpi/logo_white.png b/app/src/main/res/drawable-xhdpi/logo_white.png new file mode 100644 index 0000000..c2a567e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/logo_white.png differ diff --git a/app/src/main/res/drawable-xxhdpi/drawer_shadow.9.png b/app/src/main/res/drawable-xxhdpi/drawer_shadow.9.png new file mode 100644 index 0000000..b91e9d7 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/drawer_shadow.9.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_bug_report_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_bug_report_black_24dp.png new file mode 100644 index 0000000..af8c82e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_bug_report_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_bug_report_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_bug_report_white_24dp.png new file mode 100644 index 0000000..766bac4 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_bug_report_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_drawer.png b/app/src/main/res/drawable-xxhdpi/ic_drawer.png new file mode 100644 index 0000000..9c4685d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_drawer.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_exit_to_app_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_exit_to_app_black_24dp.png new file mode 100644 index 0000000..53b79d4 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_exit_to_app_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_exit_to_app_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_exit_to_app_white_24dp.png new file mode 100644 index 0000000..c04fe6e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_exit_to_app_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_feedback_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_feedback_black_24dp.png new file mode 100644 index 0000000..e68ceb9 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_feedback_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_feedback_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_feedback_white_24dp.png new file mode 100644 index 0000000..25810dd Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_feedback_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_help_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_help_black_24dp.png new file mode 100644 index 0000000..645822e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_help_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_help_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_help_white_24dp.png new file mode 100644 index 0000000..d491817 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_help_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_info_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_info_black_24dp.png new file mode 100644 index 0000000..a81eeb9 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_info_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_info_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_info_white_24dp.png new file mode 100644 index 0000000..0db1429 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_info_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_map_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_map_black_24dp.png new file mode 100644 index 0000000..827c9fc Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_map_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_map_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_map_white_24dp.png new file mode 100644 index 0000000..0c38abe Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_map_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_notifications_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_notifications_black_24dp.png new file mode 100644 index 0000000..ab8a9c4 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_notifications_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_notifications_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_notifications_white_24dp.png new file mode 100644 index 0000000..cbd0c1e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_notifications_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.png new file mode 100644 index 0000000..3023ff8 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_settings_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png new file mode 100644 index 0000000..eabb0a2 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_sync_black_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_sync_black_24dp.png new file mode 100644 index 0000000..f799008 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_sync_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_sync_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_sync_white_24dp.png new file mode 100644 index 0000000..be061bf Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_sync_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/logo_black.png b/app/src/main/res/drawable-xxhdpi/logo_black.png new file mode 100644 index 0000000..83dfef4 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/logo_black.png differ diff --git a/app/src/main/res/drawable-xxhdpi/logo_by.png b/app/src/main/res/drawable-xxhdpi/logo_by.png new file mode 100644 index 0000000..046ae5d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/logo_by.png differ diff --git a/app/src/main/res/drawable-xxhdpi/logo_trans.png b/app/src/main/res/drawable-xxhdpi/logo_trans.png new file mode 100644 index 0000000..a8604a3 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/logo_trans.png differ diff --git a/app/src/main/res/drawable-xxhdpi/logo_white.png b/app/src/main/res/drawable-xxhdpi/logo_white.png new file mode 100644 index 0000000..7ac5931 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/logo_white.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_bug_report_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_bug_report_black_24dp.png new file mode 100644 index 0000000..6eb1474 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_bug_report_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_bug_report_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_bug_report_white_24dp.png new file mode 100644 index 0000000..e0b5b19 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_bug_report_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_exit_to_app_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_exit_to_app_black_24dp.png new file mode 100644 index 0000000..e30632b Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_exit_to_app_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_exit_to_app_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_exit_to_app_white_24dp.png new file mode 100644 index 0000000..27a9d7b Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_exit_to_app_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_feedback_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_feedback_black_24dp.png new file mode 100644 index 0000000..1343fa8 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_feedback_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_feedback_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_feedback_white_24dp.png new file mode 100644 index 0000000..cf4fd98 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_feedback_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_help_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_help_black_24dp.png new file mode 100644 index 0000000..7c48230 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_help_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_help_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_help_white_24dp.png new file mode 100644 index 0000000..8eb7241 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_help_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_info_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_info_black_24dp.png new file mode 100644 index 0000000..c8f86b9 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_info_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_info_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_info_white_24dp.png new file mode 100644 index 0000000..7d11d1e Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_info_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_map_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_map_black_24dp.png new file mode 100644 index 0000000..da75c65 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_map_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_map_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_map_white_24dp.png new file mode 100644 index 0000000..0cbfe89 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_map_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_notifications_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_notifications_black_24dp.png new file mode 100644 index 0000000..86f89d7 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_notifications_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_notifications_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_notifications_white_24dp.png new file mode 100644 index 0000000..1e70b63 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_notifications_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.png new file mode 100644 index 0000000..476d5c9 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_settings_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_settings_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_settings_white_24dp.png new file mode 100644 index 0000000..507c5ed Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_settings_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_sync_black_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_sync_black_24dp.png new file mode 100644 index 0000000..b9f56f3 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_sync_black_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_sync_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_sync_white_24dp.png new file mode 100644 index 0000000..f8b1277 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_sync_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/logo_black.png b/app/src/main/res/drawable-xxxhdpi/logo_black.png new file mode 100644 index 0000000..9fd3d69 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/logo_black.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/logo_by.png b/app/src/main/res/drawable-xxxhdpi/logo_by.png new file mode 100644 index 0000000..c55164e Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/logo_by.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/logo_trans.png b/app/src/main/res/drawable-xxxhdpi/logo_trans.png new file mode 100644 index 0000000..e3d926e Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/logo_trans.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/logo_white.png b/app/src/main/res/drawable-xxxhdpi/logo_white.png new file mode 100644 index 0000000..65d376b Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/logo_white.png differ diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..5fdb88d --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..76209c6 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/app/src/main/res/layout/drawer.xml b/app/src/main/res/layout/drawer.xml new file mode 100644 index 0000000..c9c6524 --- /dev/null +++ b/app/src/main/res/layout/drawer.xml @@ -0,0 +1,9 @@ + diff --git a/app/src/main/res/layout/fragment_about.xml b/app/src/main/res/layout/fragment_about.xml new file mode 100644 index 0000000..33ff919 --- /dev/null +++ b/app/src/main/res/layout/fragment_about.xml @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + +