diff --git a/.gitignore b/.gitignore index c195f55..2687c2b 100644 --- a/.gitignore +++ b/.gitignore @@ -89,4 +89,7 @@ db.sqlite3 /requirements/ /static -/.venv \ No newline at end of file +/.venv + + +app\src\main\java\smarttraffic\smartparking\SmartParkingInitialData.java \ No newline at end of file diff --git a/.gradle/5.1.1/executionHistory/executionHistory.bin b/.gradle/5.1.1/executionHistory/executionHistory.bin new file mode 100644 index 0000000..1f64973 Binary files /dev/null and b/.gradle/5.1.1/executionHistory/executionHistory.bin differ diff --git a/.gradle/5.1.1/executionHistory/executionHistory.lock b/.gradle/5.1.1/executionHistory/executionHistory.lock new file mode 100644 index 0000000..cfd3ac5 Binary files /dev/null and b/.gradle/5.1.1/executionHistory/executionHistory.lock differ diff --git a/.gradle/5.1.1/fileChanges/last-build.bin b/.gradle/5.1.1/fileChanges/last-build.bin new file mode 100644 index 0000000..f76dd23 Binary files /dev/null and b/.gradle/5.1.1/fileChanges/last-build.bin differ diff --git a/.gradle/5.1.1/fileContent/fileContent.lock b/.gradle/5.1.1/fileContent/fileContent.lock new file mode 100644 index 0000000..847ddba Binary files /dev/null and b/.gradle/5.1.1/fileContent/fileContent.lock differ diff --git a/.gradle/5.1.1/fileHashes/fileHashes.bin b/.gradle/5.1.1/fileHashes/fileHashes.bin new file mode 100644 index 0000000..e5070ee Binary files /dev/null and b/.gradle/5.1.1/fileHashes/fileHashes.bin differ diff --git a/.gradle/5.1.1/fileHashes/fileHashes.lock b/.gradle/5.1.1/fileHashes/fileHashes.lock new file mode 100644 index 0000000..23aed83 Binary files /dev/null and b/.gradle/5.1.1/fileHashes/fileHashes.lock differ diff --git a/.gradle/5.1.1/fileHashes/resourceHashesCache.bin b/.gradle/5.1.1/fileHashes/resourceHashesCache.bin new file mode 100644 index 0000000..7fab46a Binary files /dev/null and b/.gradle/5.1.1/fileHashes/resourceHashesCache.bin differ diff --git a/.gradle/5.1.1/gc.properties b/.gradle/5.1.1/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/.gradle/5.1.1/javaCompile/classAnalysis.bin b/.gradle/5.1.1/javaCompile/classAnalysis.bin new file mode 100644 index 0000000..6413859 Binary files /dev/null and b/.gradle/5.1.1/javaCompile/classAnalysis.bin differ diff --git a/.gradle/5.1.1/javaCompile/javaCompile.lock b/.gradle/5.1.1/javaCompile/javaCompile.lock new file mode 100644 index 0000000..a981a47 Binary files /dev/null and b/.gradle/5.1.1/javaCompile/javaCompile.lock differ diff --git a/.gradle/5.1.1/javaCompile/taskHistory.bin b/.gradle/5.1.1/javaCompile/taskHistory.bin new file mode 100644 index 0000000..de6ea93 Binary files /dev/null and b/.gradle/5.1.1/javaCompile/taskHistory.bin differ diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 0000000..36b38ab Binary files /dev/null and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/.gradle/buildOutputCleanup/cache.properties b/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 0000000..0ad4fd9 --- /dev/null +++ b/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Wed Jul 03 18:47:24 PYT 2019 +gradle.version=5.1.1 diff --git a/.gradle/buildOutputCleanup/outputFiles.bin b/.gradle/buildOutputCleanup/outputFiles.bin new file mode 100644 index 0000000..4f689d4 Binary files /dev/null and b/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/.gradle/vcs-1/gc.properties b/.gradle/vcs-1/gc.properties new file mode 100644 index 0000000..e69de29 diff --git a/.gradle/vcsWorkingDirs/gc.properties b/.gradle/vcsWorkingDirs/gc.properties new file mode 100644 index 0000000..e69de29 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.iml b/app/app.iml new file mode 100644 index 0000000..475abc7 --- /dev/null +++ b/app/app.iml @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..cb97b36 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,44 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "smarttraffic.smartparking" + minSdkVersion 23 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + //noinspection GradleCompatible + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation "com.android.support:support-compat:28.0.0" + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + implementation 'com.android.support:design:28.0.0' + implementation 'com.jakewharton:butterknife:8.7.0' + annotationProcessor 'com.jakewharton:butterknife-compiler:8.7.0' + implementation 'com.squareup.retrofit2:retrofit:2.4.0' + implementation 'com.squareup.retrofit2:converter-gson:2.4.0' + implementation 'org.osmdroid:osmdroid-android:6.1.0' + implementation 'org.osmdroid:osmdroid-wms:6.1.0' + implementation 'org.osmdroid:osmdroid-mapsforge:6.1.0' + implementation 'org.osmdroid:osmdroid-geopackage:6.1.0' + implementation 'org.jetbrains:annotations-java5:15.0' + implementation 'org.jetbrains:annotations-java5:15.0' + implementation 'com.google.maps.android:android-maps-utils:0.5+' + implementation 'com.google.android.gms:play-services-location:16.0.0' + implementation 'com.google.android.gms:play-services-maps:16.0.0' +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# 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 *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/smarttraffic/smartparking/ExampleInstrumentedTest.java b/app/src/androidTest/java/smarttraffic/smartparking/ExampleInstrumentedTest.java new file mode 100644 index 0000000..3b41671 --- /dev/null +++ b/app/src/androidTest/java/smarttraffic/smartparking/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package smarttraffic.smartparking; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("smarttraffic.smartparking", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..69ef808 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/smarttraffic/smartparking/Constants.java b/app/src/main/java/smarttraffic/smartparking/Constants.java new file mode 100644 index 0000000..fddf510 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/Constants.java @@ -0,0 +1,139 @@ +package smarttraffic.smartparking; + +/** + * Created by Joaquin Olivera on august 19. + * + * @author joaquin + */ + +public class Constants { + + /** + * Add here all variables used at width in the project... + * **/ + public Constants() { + } + + public static final String USER_PASSWORD = "USER_PASSWORD"; + public static final String USER_TOKEN = "USER_TOKEN"; + public static final String CLIENT_NOT_LOGIN = "CLIENT_NOT_LOGIN"; + public static final String CLIENTE_DATA = "CLIENTE_DATA"; + public static final String USER_ID = "USER_ID"; + public static final String USER_URL = "USER_URL"; + public static final String APPLICATION_ID = "1"; + public static final String EVENT_BASIC = "/entities/smartparking/event_types/"; + + public static final int NOT_IN_PARKINGSPOT = -1; + public static final String GEOFENCE_LOTS_SHARED_PREFERENCES = "GEOFENCE_LOTS_SHARED_PREFERENCES"; + private static final String BROADCAST_GEOFENCE_TRIGGER_INTENT = "BROADCAST_GEOFENCE_TRIGGER_INTENT"; + public static final String BROADCAST_TRANSITION_ACTIVITY_INTENT = "BROADCAST_TRANSITION_ACTIVITY_INTENT"; + public static final String GEOFENCE_TRIGGER_ID = "geofenceTriggerId"; + public static final String GEOFENCE_TRANSITION_TYPE = "GEOFENCE_TRANSITION_TYPE"; + + public static final String KEY_DETECTED_ACTIVITIES = "KEY_DETECTED_ACTIVITIES"; + public static final String KEY_ACTIVITY_UPDATES_REQUESTED = "KEY_ACTIVITY_UPDATES_REQUESTED"; + public static final String GEOFENCES_ADDED_KEY = "GEOFENCES_ADDED_KEY"; + private static final long SECONDS_IN_MILLISECONDS = 1000 * 1; + public static final String ACTIVITY_TYPE_TRANSITION = "ACTIVITY_TYPE_TRANSITION"; + public static final String ACTIVITY_CONFIDENCE_TRANSITION = "ACTIVITY_CONFIDENCE_TRANSITION"; + public static final long DETECTION_INTERVAL_IN_MILLISECONDS = SECONDS_IN_MILLISECONDS; // 30 seconds + private static final long MINUTES_IN_MILLISECONDS = SECONDS_IN_MILLISECONDS * 60; + private static final long HOURS_IN_MILLISECONDS = MINUTES_IN_MILLISECONDS * 60; + public static final String BASE_URL = "http://192.168.100.5:8000/"; + private static final String CHANNEL_ID = "SMARTPARKING_CHANNEL_ID"; + private static final String PROXIMITY_INTENT_ACTION = "SMARTPARKING_PROXIMITY_ALERT"; + private static final String NOTIFICATION_SERVICE = "notification"; + private static final String BROADCAST_LOCATION_INTENT = "BROADCAST_LOCATION_INTENT"; + private static final String FROM_PROXIMITY_INTENT = "FROM_PROXIMITY_INTENT"; + private static final String INTENT_FROM = "INTENT_FROM"; + private static final String LATITUD = "LATITUD"; + private static final String LONGITUD = "LONGITUD"; + private static final String RADIOUS = "RADIOUS"; + private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 1; + private static final long DISTANCE_CHANGE_FOR_UPDATES = 100; + private static final long HIGH_FREQUENCY_UPDATES = SECONDS_IN_MILLISECONDS * 1; + private static final long LOW_FREQUENCY_UPDATES = MINUTES_IN_MILLISECONDS * 20; + private static final String PROX_ALERT_INTENT = "smarttraffic.smartparking.services.ProximityAlert"; + public static final String TILE_SERVER = "https://smarttraffic.com.py/tile/"; + public static final int REQUEST_CHECK_SETTINGS = 0x1; + /** + * The desired interval for location updates. Inexact. Updates may be more or less frequent. + */ + + public static String getUserId() { + return USER_ID; + } + + public static String getBroadcastGeofenceTriggerIntent(){ + return BROADCAST_GEOFENCE_TRIGGER_INTENT; + } + public static String getLatitud() { + return LATITUD; + } + + public static String getLongitud() { + return LONGITUD; + } + + public static String getRadious() { + return RADIOUS; + } + public static String getProxAlertIntent() { + return PROX_ALERT_INTENT; + } + + public static String getFromProximityIntent() { + return FROM_PROXIMITY_INTENT; + } + + public static String getIntentFrom() { + return INTENT_FROM; + } + + public static String getBroadcastLocationIntent() { + return BROADCAST_LOCATION_INTENT; + } + + public static long getMinDistanceChangeForUpdates() { + return MIN_DISTANCE_CHANGE_FOR_UPDATES; + } + + public static long getDistanceChangeForUpdates() { + return DISTANCE_CHANGE_FOR_UPDATES; + } + + public static long getHighFrequencyUpdates() { + return HIGH_FREQUENCY_UPDATES; + } + + public static long getLowFrequencyUpdates() { + return LOW_FREQUENCY_UPDATES; + } + + + public static long getSecondsInMilliseconds() { + return SECONDS_IN_MILLISECONDS; + } + + public static long getMinutesInMilliseconds() { + return MINUTES_IN_MILLISECONDS; + } + + public static long getHoursInMilliseconds() { + return HOURS_IN_MILLISECONDS; + } + + public static String getNotificationService() { + return NOTIFICATION_SERVICE; + } + + public static String getProximityIntentAction() { + return PROXIMITY_INTENT_ACTION; + } + + public static String getChannelId() { + return CHANNEL_ID; + } + + +} diff --git a/app/src/main/java/smarttraffic/smartparking/GeofenceErrorMessages.java b/app/src/main/java/smarttraffic/smartparking/GeofenceErrorMessages.java new file mode 100644 index 0000000..a6d6f6b --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/GeofenceErrorMessages.java @@ -0,0 +1,45 @@ +package smarttraffic.smartparking; + +import android.content.Context; +import android.content.res.Resources; + +import com.google.android.gms.common.api.ApiException; +import com.google.android.gms.location.GeofenceStatusCodes; + +/** + * Geofence error codes mapped to error messages. + */ +public class GeofenceErrorMessages { + /** + * Prevents instantiation. + */ + private GeofenceErrorMessages() {} + + /** + * Returns the error string for a geofencing exception. + */ + public static String getErrorString(Context context, Exception e) { + if (e instanceof ApiException) { + return getErrorString(context, ((ApiException) e).getStatusCode()); + } else { + return context.getResources().getString(R.string.unknown_geofence_error); + } + } + + /** + * Returns the error string for a geofencing error code. + */ + public static String getErrorString(Context context, int errorCode) { + Resources mResources = context.getResources(); + switch (errorCode) { + case GeofenceStatusCodes.GEOFENCE_NOT_AVAILABLE: + return mResources.getString(R.string.geofence_not_available); + case GeofenceStatusCodes.GEOFENCE_TOO_MANY_GEOFENCES: + return mResources.getString(R.string.geofence_too_many_geofences); + case GeofenceStatusCodes.GEOFENCE_TOO_MANY_PENDING_INTENTS: + return mResources.getString(R.string.geofence_too_many_pending_intents); + default: + return mResources.getString(R.string.unknown_geofence_error); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/smarttraffic/smartparking/Interceptors/AddCookiesInterceptor.java b/app/src/main/java/smarttraffic/smartparking/Interceptors/AddCookiesInterceptor.java new file mode 100644 index 0000000..0b7400c --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/Interceptors/AddCookiesInterceptor.java @@ -0,0 +1,65 @@ +package smarttraffic.smartparking.Interceptors; + +import android.content.Context; +import android.content.SharedPreferences; +import android.util.Log; + +import java.io.IOException; +import java.util.HashSet; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +/** + * Created by Joaquin Olivera on july 19. + * + * @author joaquin + */ + +public class AddCookiesInterceptor implements Interceptor { + + public static final String LOG_TAG = AddCookiesInterceptor.class.getSimpleName(); + + public static final String SESSION_COOKIES = "SESSION_COOKIES"; + public static final String CSRF_COOKIES = "CSRF_COOKIES"; + public static final String CSRF_TOKEN = "X-CSRFToken"; + public static final String COOKIE = "Cookie"; + public static final String COOKIES_CLIENT = "Cookies Client"; + + private Context context; + + public AddCookiesInterceptor(Context context) { + this.context = context; + } + + @Override + public Response intercept(Interceptor.Chain chain) throws IOException { + + Request.Builder builder = chain.request().newBuilder(); + + SharedPreferences sharedPreferences = context.getSharedPreferences( + COOKIES_CLIENT, Context.MODE_PRIVATE); + HashSet csrfCookies = (HashSet) sharedPreferences.getStringSet( + CSRF_COOKIES, new HashSet()); + HashSet sessionCookies = (HashSet) sharedPreferences.getStringSet( + SESSION_COOKIES, new HashSet()); + String cookiesConcat = new String(); + + for (String cookie : csrfCookies) { + cookiesConcat = cookie.substring(0, cookie.indexOf(";")); + builder.header(CSRF_TOKEN, cookie.substring(10, cookie.indexOf(";"))); + Log.v(LOG_TAG, cookie); + } + + for (String cookie : sessionCookies) { + cookiesConcat = cookiesConcat + "; " + cookie.substring(0, cookie.indexOf(";")); + Log.v(LOG_TAG, cookie); + } + + builder.header(COOKIE, cookiesConcat); + + return chain.proceed(builder.build()); + } + +} \ No newline at end of file diff --git a/app/src/main/java/smarttraffic/smartparking/Interceptors/AddGeoJsonInterceptor.java b/app/src/main/java/smarttraffic/smartparking/Interceptors/AddGeoJsonInterceptor.java new file mode 100644 index 0000000..7815570 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/Interceptors/AddGeoJsonInterceptor.java @@ -0,0 +1,28 @@ +package smarttraffic.smartparking.Interceptors; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.tokenInterceptors + */ + +public class AddGeoJsonInterceptor implements Interceptor { + + public AddGeoJsonInterceptor(){ + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request newRequest = chain.request().newBuilder() + .addHeader("Accept", "application/vnd.geo+json") + .build(); + return chain.proceed(newRequest); + } + +} diff --git a/app/src/main/java/smarttraffic/smartparking/Interceptors/AddSmartParkingTokenInterceptor.java b/app/src/main/java/smarttraffic/smartparking/Interceptors/AddSmartParkingTokenInterceptor.java new file mode 100644 index 0000000..53f59b8 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/Interceptors/AddSmartParkingTokenInterceptor.java @@ -0,0 +1,29 @@ +package smarttraffic.smartparking.Interceptors; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; +import smarttraffic.smartparking.SmartParkingInitialData; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.tokenInterceptors + */ + +public class AddSmartParkingTokenInterceptor implements Interceptor { + + public AddSmartParkingTokenInterceptor(){ + } + + @Override + public Response intercept(Chain chain) throws IOException { + Request newRequest = chain.request().newBuilder() + .addHeader("Authorization", "Token " + + SmartParkingInitialData.getToken()) + .build(); + return chain.proceed(newRequest); + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/Interceptors/AddUserTokenInterceptor.java b/app/src/main/java/smarttraffic/smartparking/Interceptors/AddUserTokenInterceptor.java new file mode 100644 index 0000000..dcac6bc --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/Interceptors/AddUserTokenInterceptor.java @@ -0,0 +1,41 @@ +package smarttraffic.smartparking.Interceptors; + +import android.content.Context; +import android.content.SharedPreferences; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; +import smarttraffic.smartparking.Constants; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.tokenInterceptors + */ + +public class AddUserTokenInterceptor implements Interceptor { + + private Context context; + + public AddUserTokenInterceptor(Context context){ + this.context = context; + } + + @Override + public Response intercept(Chain chain) throws IOException { + SharedPreferences sharedPreferences = context.getSharedPreferences( + Constants.CLIENTE_DATA, Context.MODE_PRIVATE); + String userToken = sharedPreferences.getString(Constants.USER_TOKEN, + Constants.CLIENT_NOT_LOGIN); + + Request newRequest = chain.request().newBuilder() + .addHeader("Authorization", "Token " + + userToken) + .build(); + return chain.proceed(newRequest); + } +} + diff --git a/app/src/main/java/smarttraffic/smartparking/Interceptors/ReceivedCookiesInterceptor.java b/app/src/main/java/smarttraffic/smartparking/Interceptors/ReceivedCookiesInterceptor.java new file mode 100644 index 0000000..57adc3f --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/Interceptors/ReceivedCookiesInterceptor.java @@ -0,0 +1,61 @@ +package smarttraffic.smartparking.Interceptors; + +import android.content.Context; +import android.content.SharedPreferences; +import android.util.Log; + +import java.io.IOException; +import java.util.HashSet; + +import okhttp3.Interceptor; +import okhttp3.Response; + +/** + * Created by Joaquin Olivera on july 19. + * + * @author joaquin + */ + +public class ReceivedCookiesInterceptor implements Interceptor { + public static final String CSRF_COOKIES = "CSRF_COOKIES"; + public static final String SESSION_COOKIES = "SESSION_COOKIES"; + public static final String SET_COOKIE = "Set-Cookie"; + + public static final String LOG_TAG = ReceivedCookiesInterceptor.class.getSimpleName(); + private static final String COOKIES_CLIENT = "Cookies Client"; + + private Context context; + + public ReceivedCookiesInterceptor(Context context) { + this.context = context; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Response originalResponse = chain.proceed(chain.request()); + + if (!originalResponse.headers(SET_COOKIE).isEmpty()) { + SharedPreferences sharedPreferences = context.getSharedPreferences(COOKIES_CLIENT, Context.MODE_PRIVATE); + HashSet sessionCookies = new HashSet(); + HashSet csrfCookies = new HashSet(); + + for (String header : originalResponse.headers(SET_COOKIE)) { + if(header.startsWith("sessionid")){ + sessionCookies.add(header); + }else{ + csrfCookies.add(header); + } + } + + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putStringSet(CSRF_COOKIES, csrfCookies).apply(); + editor.putStringSet(SESSION_COOKIES, sessionCookies).apply(); + editor.commit(); + + Log.v(LOG_TAG, originalResponse.headers().get(SET_COOKIE)); + + } + + return originalResponse; + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/Interceptors/ReceivedTimeStampInterceptor.java b/app/src/main/java/smarttraffic/smartparking/Interceptors/ReceivedTimeStampInterceptor.java new file mode 100644 index 0000000..61e1ca3 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/Interceptors/ReceivedTimeStampInterceptor.java @@ -0,0 +1,46 @@ +package smarttraffic.smartparking.Interceptors; + +import android.content.Context; +import android.content.SharedPreferences; +import android.util.Log; + +import java.io.IOException; + +import okhttp3.Interceptor; +import okhttp3.Response; + + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.Interceptors + */ + +public class ReceivedTimeStampInterceptor implements Interceptor { + + private static final String LOG_TAG = "X-TimeStamp Interceptor"; + + public static final String X_TIMESTAMP = "X-Timestamp"; + + private Context context; + + public ReceivedTimeStampInterceptor(Context context) { + this.context = context; + } + + @Override + public Response intercept(Chain chain) throws IOException { + Response originalResponse = chain.proceed(chain.request()); + SharedPreferences sharedPreferences = context.getSharedPreferences(X_TIMESTAMP, + Context.MODE_PRIVATE); + + SharedPreferences.Editor editor = sharedPreferences.edit(); + editor.putString(X_TIMESTAMP, originalResponse.header(X_TIMESTAMP)).apply(); + editor.commit(); + + Log.v(LOG_TAG, X_TIMESTAMP); + + return originalResponse; + + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/SmartParkingAPI.java b/app/src/main/java/smarttraffic/smartparking/SmartParkingAPI.java new file mode 100644 index 0000000..d240d61 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/SmartParkingAPI.java @@ -0,0 +1,78 @@ +package smarttraffic.smartparking; + +import java.util.HashMap; + +import okhttp3.ResponseBody; +import retrofit2.Call; +import retrofit2.http.Body; +import retrofit2.http.GET; +import retrofit2.http.Header; +import retrofit2.http.PATCH; +import retrofit2.http.POST; +import retrofit2.http.Path; +import smarttraffic.smartparking.activities.ChangePasswordActivity; +import smarttraffic.smartparking.dataModels.Credentials; +import smarttraffic.smartparking.dataModels.Events; +import smarttraffic.smartparking.dataModels.Lots.Lot; +import smarttraffic.smartparking.dataModels.Lots.LotList; +import smarttraffic.smartparking.dataModels.NearbyLocation; +import smarttraffic.smartparking.dataModels.ProfileUser; +import smarttraffic.smartparking.dataModels.ProfileRegistry; +import smarttraffic.smartparking.dataModels.Spots.Spot; +import smarttraffic.smartparking.dataModels.Spots.SpotList; +import smarttraffic.smartparking.dataModels.UserToken; + +public interface SmartParkingAPI { + + /**USERS**/ + + @POST("smartparking/auth-token/") + Call getUserToken(@Body Credentials userCredentials); + + @POST("smartparking/users/") + Call signUpUser(@Body ProfileRegistry profileRegistry); + + @PATCH("smartparking/users/{identifier}/") + Call updateUserProfile(@Path("identifier") Integer userId, + @Body ChangePasswordActivity.Password newProfile); + + /**SPOTS**/ + + @POST("smartparking/spots/{spotId}/reset/") + Call resetFreeSpot(@Path("spotId") Integer spotId); + + @POST("smartparking/spots/{spotId}/set/") + Call setOccupiedSpot(@Path("spotId") Integer spotId); + + @POST("smartparking/spots/nearby/") + Call> getMapNearbySpots(@Body NearbyLocation nearbyLocation); + + @POST("smartparking/spots/nearby/") + Call getGeoJsonNearbySpots(@Body NearbyLocation nearbyLocation); + + @GET("smartparking/spots/") + Call getAllSpots(); + + @GET("smartparking/spots/{spotId}/") + Call getASpot(@Path("spotId") Integer spotId); + + /**LOTS**/ + + @GET("smartparking/lots/") + Call getAllLots(); + + @GET("smartparking/lots/{lotId}/") + Call getALot(@Path("lotId") Integer lotId); + + @GET("smartparking/lots/{lotId}/spots/") + Call> getAllMapSpotsInLot(@Path("lotId") Integer lotId); + + @GET("smartparking/lots/{lotId}/spots/") + Call getAllGeoJsonSpotsInLot(@Path("lotId") Integer lotId); + + /**EVENTS**/ + + @POST("services/events/") + Call setUserEvent(@Header("Content-Type") String content_type, @Body Events event); + +} diff --git a/app/src/main/java/smarttraffic/smartparking/StatesEnumerations.java b/app/src/main/java/smarttraffic/smartparking/StatesEnumerations.java new file mode 100644 index 0000000..41da985 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/StatesEnumerations.java @@ -0,0 +1,24 @@ +package smarttraffic.smartparking; + +/** + * Created by Joaquin on 08/2019. + *

+ * smarttraffic.smartparking + */ + +public enum StatesEnumerations { + FREE("F"), + UNKNOWN("U"), + OCCUPIED("O"); + + private String estado; + + public String getEstado() { + return estado; + } + + StatesEnumerations(String f) { + this.estado = f; + } +} + diff --git a/app/src/main/java/smarttraffic/smartparking/Utils.java b/app/src/main/java/smarttraffic/smartparking/Utils.java new file mode 100644 index 0000000..e43adc7 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/Utils.java @@ -0,0 +1,233 @@ +package smarttraffic.smartparking; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.Resources; +import android.location.Location; +import android.util.Log; +import android.view.Gravity; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.Toast; + +import com.google.android.gms.location.DetectedActivity; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.reflect.TypeToken; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import okhttp3.Headers; +import okhttp3.OkHttpClient; +import okhttp3.ResponseBody; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; +import smarttraffic.smartparking.Interceptors.AddUserTokenInterceptor; +import smarttraffic.smartparking.dataModels.EventProperties; +import smarttraffic.smartparking.dataModels.Events; +import smarttraffic.smartparking.dataModels.Lots.Lot; +import smarttraffic.smartparking.dataModels.Lots.PointGeometry; + +public class Utils { + + private static final String LOG_TAG = "Utils class"; + + public static final String LOTS_SYSTEM = "Lots in the System"; + + private Utils() {} + + /** + * Returns a human readable String corresponding to a detected activity type. + */ + @SuppressLint("StringFormatInvalid") + public static String getActivityString(Context context, int detectedActivityType) { + Resources resources = context.getResources(); + switch(detectedActivityType) { + case DetectedActivity.IN_VEHICLE: + return resources.getString(R.string.in_vehicle); + case DetectedActivity.ON_BICYCLE: + return resources.getString(R.string.on_bicycle); + case DetectedActivity.ON_FOOT: + return resources.getString(R.string.on_foot); + case DetectedActivity.RUNNING: + return resources.getString(R.string.running); + case DetectedActivity.STILL: + return resources.getString(R.string.still); + case DetectedActivity.TILTING: + return resources.getString(R.string.tilting); + case DetectedActivity.UNKNOWN: + return resources.getString(R.string.unknown); + case DetectedActivity.WALKING: + return resources.getString(R.string.walking); + default: + return resources.getString(R.string.unidentifiable_activity, detectedActivityType); + } + } + + public static String detectedActivitiesToJson(ArrayList detectedActivitiesList) { + Type type = new TypeToken>() {}.getType(); + return new Gson().toJson(detectedActivitiesList, type); + } + + static ArrayList detectedActivitiesFromJson(String jsonArray) { + Type listType = new TypeToken>(){}.getType(); + ArrayList detectedActivities = new Gson().fromJson(jsonArray, listType); + if (detectedActivities == null) { + detectedActivities = new ArrayList<>(); + } + return detectedActivities; + } + + public static void saveLotInSharedPreferences(Context context, List lots) { + SharedPreferences prefs = context.getSharedPreferences(LOTS_SYSTEM, + Context.MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + for(Lot lot : lots){ + editor.putInt(lot.getProperties().getName(),lot.getProperties().getIdFromUrl()); + editor.apply(); + } + } + + public static int getLotInSharedPreferences(Context context, String lotName) { + SharedPreferences prefs = context.getSharedPreferences(LOTS_SYSTEM, + Context.MODE_PRIVATE); + int id = prefs.getInt(lotName, -1); + return id; + } + + public static void showToast(String message, Context context) { + Toast toast = Toast.makeText(context, message, Toast.LENGTH_LONG); + toast.setGravity(Gravity.CENTER, 0, 0); + LinearLayout toastContentView = (LinearLayout) toast.getView(); + ImageView imageView = new ImageView(context); + imageView.setImageResource(R.mipmap.smartparking_logo_round); + toastContentView.addView(imageView, 0); + toast.show(); + } + + public static void setNewStateOnSpot(final Context context, boolean isParking, int spotId) { + Gson gson = new GsonBuilder() + .setLenient() + .create(); + + final OkHttpClient okHttpClient = new OkHttpClient.Builder() + .connectTimeout(5, TimeUnit.SECONDS) + .writeTimeout(20, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .addInterceptor(new AddUserTokenInterceptor(context)) + .build(); + + Retrofit retrofit = new Retrofit.Builder() + .client(okHttpClient) + .baseUrl(Constants.BASE_URL) + .addConverterFactory(GsonConverterFactory.create(gson)) + .build(); + + SmartParkingAPI smartParkingAPI = retrofit.create(SmartParkingAPI.class); + if(isParking){ + Call call = smartParkingAPI.setOccupiedSpot(spotId); + call.enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + switch (response.code()) { + case 200: + showToast(String.valueOf(R.string.parked_successfull), context); + break; + default: + showToast(String.valueOf(R.string.unsuccessful), context); + break; + } + } + + @Override + public void onFailure(Call call, Throwable t) { + t.printStackTrace(); + } + }); + }else{ + Call call = smartParkingAPI.resetFreeSpot(spotId); + call.enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + switch (response.code()) { + case 200: + showToast(String.valueOf(R.string.free_successfull), context); + break; + default: + showToast(String.valueOf(R.string.unsuccessful), context); + break; + } + } + + @Override + public void onFailure(Call call, Throwable t) { + t.printStackTrace(); + } + }); + } + + } + + public static void setEntranceEvent(Context context, Location location, String eventType){ + SharedPreferences sharedPreferences = context.getSharedPreferences(Constants.CLIENTE_DATA, + Context.MODE_PRIVATE); + + String userUrl = sharedPreferences.getString(Constants.USER_URL, ""); + Events events = new Events(); + EventProperties properties = new EventProperties(); + PointGeometry geometry = new PointGeometry(); + properties.setApplication(Constants.APPLICATION_ID); + properties.setAgent(userUrl); + properties.setE_type(Constants.BASE_URL + Constants.EVENT_BASIC + eventType); + geometry.setPointCoordinates(location); + events.setType("Feature"); + events.setProperties(properties); + events.setGeometry(geometry); + + Gson gson = new GsonBuilder() + .setLenient() + .create(); + + final OkHttpClient okHttpClient = new OkHttpClient.Builder() + .connectTimeout(5, TimeUnit.SECONDS) + .writeTimeout(20, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .addInterceptor(new AddUserTokenInterceptor(context)) + .build(); + + Retrofit retrofit = new Retrofit.Builder() + .client(okHttpClient) + .baseUrl(Constants.BASE_URL) + .addConverterFactory(GsonConverterFactory.create(gson)) + .build(); + + SmartParkingAPI smartParkingAPI = retrofit.create(SmartParkingAPI.class); + Call call = smartParkingAPI.setUserEvent("application/vnd.geo+json", events); + + call.enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + switch (response.code()) { + case 200: + Log.i(LOG_TAG, "Evento de entrada enviado correctamente"); + break; + default: + Log.e(LOG_TAG, "Evento de entrada enviado incorrectamente"); + } + } + + @Override + public void onFailure(Call call, Throwable t) { + t.printStackTrace(); + Log.e(LOG_TAG, t.toString()); + } + }); + } +} \ No newline at end of file diff --git a/app/src/main/java/smarttraffic/smartparking/activities/ChangePasswordActivity.java b/app/src/main/java/smarttraffic/smartparking/activities/ChangePasswordActivity.java new file mode 100644 index 0000000..c158c0d --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/activities/ChangePasswordActivity.java @@ -0,0 +1,221 @@ +package smarttraffic.smartparking.activities; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.Gravity; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.util.concurrent.TimeUnit; + +import butterknife.BindView; +import butterknife.ButterKnife; +import okhttp3.OkHttpClient; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; +import smarttraffic.smartparking.Constants; +import smarttraffic.smartparking.R; +import smarttraffic.smartparking.SmartParkingAPI; +import smarttraffic.smartparking.dataModels.ProfileUser; +import smarttraffic.smartparking.Interceptors.AddUserTokenInterceptor; + +/** + * Created by Joaquin Olivera on july 19. + * + * @author joaquin + */ + +public class ChangePasswordActivity extends AppCompatActivity { + + private static final String LOG_TAG = "ChangePasswordActivity"; + + private static final String PASSWORDS_NOT_MATCH = "Las contraseñas no coinciden!"; + private static final String CHANGE_SUCCESS = "EXITOSO!"; + private static final String CHANGE_NOT_SUCCESS = "La contraseña actual no coincide con la de su usuario!"; + private static final String SERVER_MISTAQUE = "Las contraseña no se ha podido cambiar."; + + @BindView(R.id.changePasswordButton) + Button changePassButton; + @BindView(R.id.currentPassword) + EditText currentPassword; + @BindView(R.id.newPassword1) + EditText firstNewPassword; + @BindView(R.id.newPassword2) + EditText secondNewPassword; + @BindView(R.id.passwordNotMatch) + TextView passwordNotMatch; + + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.change_password_layout); + ButterKnife.bind(this); + final SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences( + Constants.CLIENTE_DATA, Context.MODE_PRIVATE); + + final String userPassword = sharedPreferences.getString(Constants.USER_PASSWORD, ""); + + firstNewPassword.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + //Not needed... + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + //Not needed... + } + + @Override + public void afterTextChanged(Editable s) { + if(!firstNewPassword.getText().toString().equals( + secondNewPassword.getText().toString())){ + passwordNotMatch.setVisibility(View.VISIBLE); + }else{ + passwordNotMatch.setVisibility(View.INVISIBLE); + } + } + }); + + secondNewPassword.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + //Not needed... + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + //Not needed... + } + + @Override + public void afterTextChanged(Editable s) { + if(!firstNewPassword.getText().toString().equals( + secondNewPassword.getText().toString())){ + passwordNotMatch.setVisibility(View.VISIBLE); + + }else{ + passwordNotMatch.setVisibility(View.INVISIBLE); + } + } + }); + + changePassButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Log.v(LOG_TAG, "User trying to change his password"); + if(currentPassword.getText().toString().equals(userPassword)){ + changeProfileUser(sharedPreferences); + }else{ + showToast(PASSWORDS_NOT_MATCH); + } + } + }); + } + + private void changeProfileUser(SharedPreferences sharedPreferences) { + Password password = new Password(); + password.setNewPassword(firstNewPassword.getText().toString()); + Gson gson = new GsonBuilder() + .setLenient() + .create(); + + final OkHttpClient okHttpClient = new OkHttpClient.Builder() + .connectTimeout(5, TimeUnit.SECONDS) + .writeTimeout(20, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .addInterceptor(new AddUserTokenInterceptor(this)) + .build(); + + Retrofit retrofit = new Retrofit.Builder() + .client(okHttpClient) + .baseUrl(Constants.BASE_URL) + .addConverterFactory(GsonConverterFactory.create(gson)) + .build(); + + int userId = sharedPreferences.getInt(Constants.USER_ID, -1); + + SmartParkingAPI smartParkingAPI = retrofit.create(SmartParkingAPI.class); + Call call = smartParkingAPI.updateUserProfile(userId, password); + + call.enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + switch (response.code()) { + case 200: + showToast(CHANGE_SUCCESS); + Intent intent = new Intent(ChangePasswordActivity.this, + HomeActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + break; + case 400: + showToast(CHANGE_NOT_SUCCESS); + break; + default: + break; + } + } + @Override + public void onFailure(Call call, Throwable t) { + t.printStackTrace(); + showToast(SERVER_MISTAQUE); + Log.e(LOG_TAG,t.toString()); + } + }); + + } + + + @Override + public void onStart() { + super.onStart(); + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + } + + // Show images in Toast prompt. + private void showToast(String message) { + Toast toast = Toast.makeText(this, message, Toast.LENGTH_LONG); + toast.setGravity(Gravity.CENTER, 0, 0); + LinearLayout toastContentView = (LinearLayout) toast.getView(); + ImageView imageView = new ImageView(this); + imageView.setImageResource(R.mipmap.smartparking_logo_round); + toastContentView.addView(imageView, 0); + toast.show(); + } + + public class Password { + private String password; + + public String getNewPassword() { + return password; + } + + public void setNewPassword(String newPassword) { + this.password = newPassword; + } + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/activities/HomeActivity.java b/app/src/main/java/smarttraffic/smartparking/activities/HomeActivity.java new file mode 100644 index 0000000..ac7c4d6 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/activities/HomeActivity.java @@ -0,0 +1,1121 @@ +package smarttraffic.smartparking.activities; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.IntentSender; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.graphics.Color; +import android.location.Location; +import android.location.LocationManager; +import android.net.Uri; +import android.os.Handler; +import android.os.Looper; +import android.preference.PreferenceManager; +import android.provider.Settings; +import android.support.annotation.NonNull; +import android.support.design.widget.Snackbar; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.LocalBroadcastManager; +import android.support.v7.app.AlertDialog; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.util.Base64; +import android.util.DisplayMetrics; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; +import android.view.View; +import android.widget.ImageButton; +import android.widget.Toast; +import android.support.v7.widget.Toolbar; + +import com.google.android.gms.common.api.ApiException; +import com.google.android.gms.common.api.ResolvableApiException; +import com.google.android.gms.location.ActivityRecognitionClient; +import com.google.android.gms.location.DetectedActivity; +import com.google.android.gms.location.FusedLocationProviderClient; +import com.google.android.gms.location.Geofence; +import com.google.android.gms.location.GeofencingClient; +import com.google.android.gms.location.GeofencingRequest; +import com.google.android.gms.location.LocationCallback; +import com.google.android.gms.location.LocationRequest; +import com.google.android.gms.location.LocationResult; +import com.google.android.gms.location.LocationServices; +import com.google.android.gms.location.LocationSettingsRequest; +import com.google.android.gms.location.LocationSettingsResponse; +import com.google.android.gms.location.LocationSettingsStatusCodes; +import com.google.android.gms.location.SettingsClient; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; +import com.google.android.gms.tasks.Task; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.maps.android.PolyUtil; + +import org.osmdroid.api.IMapController; +import org.osmdroid.config.Configuration; +import org.osmdroid.tileprovider.tilesource.OnlineTileSourceBase; +import org.osmdroid.util.GeoPoint; +import org.osmdroid.util.MapTileIndex; +import org.osmdroid.views.MapView; +import org.osmdroid.views.overlay.ItemizedIconOverlay; +import org.osmdroid.views.overlay.ItemizedOverlayWithFocus; +import org.osmdroid.views.overlay.OverlayItem; +import org.osmdroid.views.overlay.Polygon; +import org.osmdroid.views.overlay.ScaleBarOverlay; +import org.osmdroid.views.overlay.compass.CompassOverlay; +import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider; +import org.osmdroid.views.overlay.gestures.RotationGestureOverlay; +import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider; +import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.TimeUnit; + +import butterknife.BindView; +import butterknife.ButterKnife; + +import okhttp3.OkHttpClient; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; +import smarttraffic.smartparking.BuildConfig; +import smarttraffic.smartparking.Constants; +import smarttraffic.smartparking.Interceptors.AddGeoJsonInterceptor; +import smarttraffic.smartparking.Interceptors.AddUserTokenInterceptor; +import smarttraffic.smartparking.Interceptors.ReceivedTimeStampInterceptor; +import smarttraffic.smartparking.R; +import smarttraffic.smartparking.SmartParkingAPI; +import smarttraffic.smartparking.SmartParkingInitialData; +import smarttraffic.smartparking.StatesEnumerations; +import smarttraffic.smartparking.Utils; +import smarttraffic.smartparking.dataModels.Lots.Lot; +import smarttraffic.smartparking.dataModels.Lots.LotList; +import smarttraffic.smartparking.dataModels.Lots.LotProperties; +import smarttraffic.smartparking.dataModels.NearbyLocation; +import smarttraffic.smartparking.dataModels.NearbyPoint; +import smarttraffic.smartparking.dataModels.Point; +import smarttraffic.smartparking.dataModels.Spots.Spot; +import smarttraffic.smartparking.dataModels.Spots.SpotList; +import smarttraffic.smartparking.dataModels.Spots.SpotProperties; +import smarttraffic.smartparking.receivers.GeofenceBroadcastReceiver; +import smarttraffic.smartparking.services.DetectedActivitiesService; +import smarttraffic.smartparking.services.GeofenceTransitionsJobIntentService; + +import static smarttraffic.smartparking.Interceptors.ReceivedTimeStampInterceptor.X_TIMESTAMP; + +/** + * Created by Joaquin Olivera on july 19. + * + * @author joaquin + */ + +public class HomeActivity extends AppCompatActivity { + + private static final String LOG_TAG = "HomeActivity"; + + @BindView(R.id.mapFragment) + MapView mapView; + @BindView(R.id.toolbar) + Toolbar toolbar; + @BindView(R.id.buttonRecenter) + ImageButton buttonRecenter; + + + private FusedLocationProviderClient mFusedLocationClient; + private ActivityRecognitionClient mActivityRecognitionClient; + + private SettingsClient mSettingsClient; + int activityTransition; + int geofenceTransition; + int confidence; + boolean dialogSendAllready = false; + private LocationRequest mLocationRequest; + private LocationSettingsRequest mLocationSettingsRequest; + private LocationCallback mLocationCallback; + private Location mCurrentLocation; + private List spots = new ArrayList(); + private ArrayList geofencesTrigger = new ArrayList<>(); + private BroadcastReceiver broadcastReceiver; + private BroadcastReceiver geofenceReceiver; + private GeofencingClient geofencingClient; + private PendingIntent mGeofencePendingIntent; + private static final int REQUEST_PERMISSIONS_REQUEST_CODE = 34; + //MAP... + private MyLocationNewOverlay mLocationOverlay; + private CompassOverlay mCompassOverlay; + private ScaleBarOverlay mScaleBarOverlay; + private RotationGestureOverlay mRotationGestureOverlay; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.home_layout); + ButterKnife.bind(this); + + setMapView(); + + createLocationCallback(); + createLocationRequest(Constants.getSecondsInMilliseconds() * 2, + Constants.getSecondsInMilliseconds()); + buildLocationSettingsRequest(); + + mSettingsClient = LocationServices.getSettingsClient(this); + geofencingClient = LocationServices.getGeofencingClient(this); + mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this); + mActivityRecognitionClient = new ActivityRecognitionClient(this); + + if (getIntent().getExtras() == null) { + addParkingLotsGeofences(); + } + + buttonRecenter.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(mLocationOverlay != null){ + mapView.getController().setCenter(mLocationOverlay.getMyLocation()); + } + } + }); + + broadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(Constants.BROADCAST_TRANSITION_ACTIVITY_INTENT)) { + activityTransition = intent.getIntExtra(Constants.ACTIVITY_TYPE_TRANSITION, -1); + confidence = intent.getIntExtra(Constants.ACTIVITY_CONFIDENCE_TRANSITION, -1); + } + } + }; + + geofenceReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(Constants.getBroadcastGeofenceTriggerIntent())) { + geofencesTrigger = intent.getStringArrayListExtra( + GeofenceTransitionsJobIntentService.GEOFENCE_TRIGGED); + geofenceTransition = intent.getIntExtra( + GeofenceTransitionsJobIntentService.TRANSITION, + -1); + managerOfTransitions(); + } + } + }; + setSupportActionBar(toolbar); + } + + private void setMapView() { + + final String basic = + "Basic " + Base64.encodeToString(SmartParkingInitialData.getCredentials().getBytes(), Base64.NO_WRAP); + final Map AuthHeader = new HashMap<>(); + AuthHeader.put("Authorization", basic); + SharedPreferences preferencesManager = PreferenceManager.getDefaultSharedPreferences(this); + SharedPreferences.Editor editor = preferencesManager.edit(); + for (final Map.Entry entry : AuthHeader.entrySet()) { + final String key = "osmdroid.additionalHttpRequestProperty." + entry.getKey(); + editor.putString(key, entry.getValue()).apply(); + } + + editor.commit(); + + Configuration.getInstance().load(this, PreferenceManager.getDefaultSharedPreferences( + this)); + + mapView.setTileSource(new OnlineTileSourceBase("SMARTPARKING CartoDB", + 16, 22, 256, ".png", + new String[]{Constants.TILE_SERVER}) { + @Override + public String getTileURLString(long pMapTileIndex) { + return getBaseUrl() + + MapTileIndex.getZoom(pMapTileIndex) + + "/" + MapTileIndex.getX(pMapTileIndex) + + "/" + MapTileIndex.getY(pMapTileIndex) + + mImageFilenameEnding; + } + }); + + + IMapController mapController = mapView.getController(); + + setGralMapConfiguration(mapController); + //scale bar + setScaleBar(); + + setLocationOverlay(); + + setCompassGestureOverlays(); +// setMarkersOnMap(); + //add all overlays + addOverlays(); + } + + private void setMarkersOnMap() { + ArrayList items = new ArrayList(); + OverlayItem overlayItem = new OverlayItem("Title1", "Description", + new GeoPoint(-25.30604186, -57.59168641)); +// overlayItem.setMarker(getDrawable(R.drawable.about_menu)); + items.add(overlayItem); + //the overlay + ItemizedOverlayWithFocus mOverlay = new ItemizedOverlayWithFocus(items, + new ItemizedIconOverlay.OnItemGestureListener() { + @Override + public boolean onItemSingleTapUp(final int index, final OverlayItem item) { + //do something + return true; + } + + @Override + public boolean onItemLongPress(final int index, final OverlayItem item) { + return false; + } + }, this); + mOverlay.setFocusItemsOnTap(true); + + mapView.getOverlays().add(mOverlay); + } + + private void addOverlays() { + mapView.getOverlays().add(mRotationGestureOverlay); + mapView.getOverlays().add(mCompassOverlay); + mapView.getOverlays().add(mLocationOverlay); + mapView.getOverlays().add(mScaleBarOverlay); + } + + private void setGralMapConfiguration(IMapController mapController) { + mapView.setTilesScaledToDpi(true); + mapView.setBuiltInZoomControls(true); + mapView.setMultiTouchControls(true); + mapView.setFlingEnabled(true); + mapController.setZoom(17); + } + + private void setScaleBar() { + final DisplayMetrics dm = this.getResources().getDisplayMetrics(); + mScaleBarOverlay = new ScaleBarOverlay(mapView); + mScaleBarOverlay.setCentred(true); + //play around with these values to get the location on screen in the right place for your application + mScaleBarOverlay.setScaleBarOffset(dm.widthPixels / 2, 10); + } + + private void setLocationOverlay() { + mLocationOverlay = new MyLocationNewOverlay(new GpsMyLocationProvider(this), mapView); + mLocationOverlay.enableMyLocation(); + mLocationOverlay.enableFollowLocation(); + mLocationOverlay.setOptionsMenuEnabled(true); + } + + private void setCompassGestureOverlays() { + //add compass + mCompassOverlay = new CompassOverlay(this, new InternalCompassOrientationProvider(this), mapView); + mCompassOverlay.enableCompass(); + + //rotation gestures + mRotationGestureOverlay = new RotationGestureOverlay(this, mapView); + mRotationGestureOverlay.setEnabled(true); + } + + private void drawPolygon(List geoPoints, String status) { + Polygon polygon = new Polygon(); + String color = "#C0C0C0"; + if (status.equals(StatesEnumerations.FREE.getEstado())) { + color = "#00FF00"; + } else if (status.equals(StatesEnumerations.OCCUPIED.getEstado())) { + color = "#FF0000"; + } + polygon.setFillColor(Color.parseColor(color)); + polygon.setStrokeColor(Color.parseColor(color)); + geoPoints.add(geoPoints.get(0)); //forces the loop to close + polygon.setPoints(geoPoints); + mapView.getOverlayManager().add(polygon); + } + + private List spotToListOfGeoPoints(Spot spot) { + List polygon = new ArrayList<>(); + List polygonPoints = spot.getGeometry().getPolygonPoints(); + if (polygonPoints != null) { + for (Point point : polygonPoints) { + polygon.add(new GeoPoint(point.getLatitud(), point.getLongitud())); + } + } + return polygon; + } + + private void managerOfTransitions() { + getSpotsFromGeofence(geofencesTrigger, false); + final Handler handler = new Handler(); + final long delay = Constants.getMinutesInMilliseconds(); + Runnable cronJob = new Runnable() { + public void run() { + getSpotsFromGeofence(geofencesTrigger, true); + handler.postDelayed(this, delay); + } + }; + switch (geofenceTransition) { + case Geofence.GEOFENCE_TRANSITION_ENTER: + Log.i(LOG_TAG, "Enter Transition"); + if (checkPermissions()) { + startLocationUpdates(mLocationRequest); + } else if (!checkPermissions()) { + requestPermissions(); + } + handler.postDelayed(cronJob, delay); + requestActivityUpdates(); + Utils.setEntranceEvent(this, mCurrentLocation, "enter_lot"); + break; + case Geofence.GEOFENCE_TRANSITION_EXIT: + Log.i(LOG_TAG, "Exit Transition"); + stopLocationUpdates(); + removeActivityUpdates(); + handler.removeCallbacks(cronJob); + Utils.setEntranceEvent(this, mCurrentLocation,"exit_lot"); + break; + case Geofence.GEOFENCE_TRANSITION_DWELL: + Log.i(LOG_TAG, "Dwell Transition"); + break; + default: + Log.i(LOG_TAG, "No transition detected"); + } + } + + private void getSpotsFromGeofence(ArrayList geofencesTrigger, boolean isForUpdate) { + if(geofencesTrigger != null) { + if(isForUpdate){ + for (String geofenceTrigger : geofencesTrigger) { + updatesSpotsFromGeofence(); + } + }else{ + for (String geofenceTrigger : geofencesTrigger) { + getSpotsGeographicValues(geofenceTrigger); + } + } + } + } + + private void getSpotsGeographicValues(String geofencesTrigger) { + Gson gson = new GsonBuilder() + .setLenient() + .create(); + + final OkHttpClient okHttpClient = new OkHttpClient.Builder() + .connectTimeout(5, TimeUnit.SECONDS) + .writeTimeout(20, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .addInterceptor(new AddGeoJsonInterceptor()) + .addInterceptor(new AddUserTokenInterceptor(this)) + .build(); + + Retrofit retrofit = new Retrofit.Builder() + .client(okHttpClient) + .baseUrl(Constants.BASE_URL) + .addConverterFactory(GsonConverterFactory.create(gson)) + .build(); + int lotId = Utils.getLotInSharedPreferences(HomeActivity.this, geofencesTrigger); + SmartParkingAPI smartParkingAPI = retrofit.create(SmartParkingAPI.class); + Call call = smartParkingAPI.getAllGeoJsonSpotsInLot(lotId); + + call.enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + switch (response.code()) { + case 200: + SpotList testSpots = response.body(); + spots = testSpots.getFeatures(); + if(spots != null){ + for (Spot spot : spots) { + drawPolygon(spotToListOfGeoPoints(spot), spot.getProperties().getState()); + } + } + break; + default: + Toast.makeText(HomeActivity.this, "Por alguna razón no fue posible la conexión", + Toast.LENGTH_SHORT).show(); + break; + } + } + + @Override + public void onFailure(Call call, Throwable t) { + t.printStackTrace(); + Log.e(LOG_TAG, t.toString()); + } + }); + } + + private void updatesSpotsFromGeofence() { + SharedPreferences sharedPreferences = this.getSharedPreferences( + X_TIMESTAMP,MODE_PRIVATE); + NearbyPoint point = new NearbyPoint(); + if(mCurrentLocation != null){ + point.setLat(mCurrentLocation.getLatitude()); + point.setLon(mCurrentLocation.getLongitude()); + } + NearbyLocation nearbyLocation = new NearbyLocation(); + nearbyLocation.setPoint(point); + nearbyLocation.setPrevious_timestamp(sharedPreferences.getString( + X_TIMESTAMP, + "1559447999")); + Gson gson = new GsonBuilder() + .setLenient() + .create(); + + final OkHttpClient okHttpClient = new OkHttpClient.Builder() + .connectTimeout(5, TimeUnit.SECONDS) + .writeTimeout(20, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .addInterceptor(new ReceivedTimeStampInterceptor(this)) + .addInterceptor(new AddUserTokenInterceptor(this)) + .addInterceptor(new AddGeoJsonInterceptor()) + .build(); + + Retrofit retrofit = new Retrofit.Builder() + .client(okHttpClient) + .baseUrl(Constants.BASE_URL) + .addConverterFactory(GsonConverterFactory.create(gson)) + .build(); + + SmartParkingAPI smartParkingAPI = retrofit.create(SmartParkingAPI.class); + Call call = smartParkingAPI.getGeoJsonNearbySpots(nearbyLocation); + + call.enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + switch (response.code()) { + case 200: + List changedSpots = response.body().getFeatures(); + if(changedSpots != null){ + for (Spot spot : changedSpots) { + drawPolygon(spotToListOfGeoPoints(spot), spot.getProperties().getState()); + } + } + break; + default: + Toast.makeText(HomeActivity.this, "Por alguna razón no fue posible la conexión", + Toast.LENGTH_SHORT).show(); + break; + } + } + + @Override + public void onFailure(Call call, Throwable t) { + t.printStackTrace(); + Log.e(LOG_TAG, t.toString()); + } + }); + } + + @Override + public void onStart() { + super.onStart(); + if (!checkPermissions()) { + requestPermissions(); + } + } + + @Override + protected void onStop() { + super.onStop(); + removeActivityUpdates(); + stopLocationUpdates(); + } + + @Override + protected void onResume() { + super.onResume(); + LocalBroadcastManager.getInstance(this).registerReceiver(broadcastReceiver, + new IntentFilter(Constants.BROADCAST_TRANSITION_ACTIVITY_INTENT)); + LocalBroadcastManager.getInstance(this).registerReceiver(geofenceReceiver, + new IntentFilter(Constants.getBroadcastGeofenceTriggerIntent())); +// managerOfTransitions(); + mapView.onResume(); + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + } + + @Override + protected void onPause() { + super.onPause(); + LocalBroadcastManager.getInstance(this).unregisterReceiver(broadcastReceiver); + LocalBroadcastManager.getInstance(this).unregisterReceiver(geofenceReceiver); + stopLocationUpdates(); + removeActivityUpdates(); + mapView.onPause(); + } + + private void addParkingLotsGeofences() { + Gson gson = new GsonBuilder() + .setLenient() + .create(); + + final OkHttpClient okHttpClient = new OkHttpClient.Builder() + .connectTimeout(5, TimeUnit.SECONDS) + .writeTimeout(20, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .addInterceptor(new AddUserTokenInterceptor(this)) + .build(); + + Retrofit retrofit = new Retrofit.Builder() + .client(okHttpClient) + .baseUrl(Constants.BASE_URL) + .addConverterFactory(GsonConverterFactory.create(gson)) + .build(); + SmartParkingAPI smartParkingAPI = retrofit.create(SmartParkingAPI.class); + Call call = smartParkingAPI.getAllLots(); + + call.enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + switch (response.code()) { + case 200: + List lots = response.body().getFeatures(); + Utils.saveLotInSharedPreferences(HomeActivity.this, lots); + ArrayList geofenceList = new ArrayList<>(); + for (Lot lot : lots) { + LotProperties properties = lot.getProperties(); + Point center = properties.getCenter().getCenterPoint(); + geofenceList.add(generateGeofence(center.getLatitud(), + center.getLongitud(), + properties.getRadio(), + properties.getName())); + } + Toast.makeText(HomeActivity.this, "Se han agregado todos los geofences", + Toast.LENGTH_SHORT).show(); + addGeofences(geofenceList); + break; + default: + Toast.makeText(HomeActivity.this, "Por problemas de conexion no " + + "se han conseguido los predios del sistema", + Toast.LENGTH_SHORT).show(); + break; + } + } + + @Override + public void onFailure(Call call, Throwable t) { + t.printStackTrace(); + Log.e(LOG_TAG, t.toString()); + } + }); + } + + /** + * This sample hard codes geofence data. A real app might dynamically create geofences based on + * the user's location. + */ + private Geofence generateGeofence(double latitude, double longitud, float radius, String nameId) { + Geofence geofence = new Geofence.Builder() + .setRequestId(nameId) + .setCircularRegion( + latitude, + longitud, + radius + ) + .setExpirationDuration(Geofence.NEVER_EXPIRE) + .setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER | + Geofence.GEOFENCE_TRANSITION_EXIT) + .build(); + return geofence; + } + + /** + * Return the current state of the permissions needed. + */ + private boolean checkPermissions() { + int permissionState = ActivityCompat.checkSelfPermission(this, + Manifest.permission.ACCESS_FINE_LOCATION); + return permissionState == PackageManager.PERMISSION_GRANTED; + } + + private void requestPermissions() { + boolean shouldProvideRationale = + ActivityCompat.shouldShowRequestPermissionRationale(this, + Manifest.permission.ACCESS_FINE_LOCATION); + // Provide an additional rationale to the user. This would happen if the user denied the + // request previously, but didn't check the "Don't ask again" checkbox. + if (shouldProvideRationale) { + Log.i(LOG_TAG, "Displaying permission rationale to provide additional context."); + showSnackbar(R.string.permission_rationale, android.R.string.ok, + new View.OnClickListener() { + @Override + public void onClick(View view) { + // Request permission + ActivityCompat.requestPermissions(HomeActivity.this, + new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, + REQUEST_PERMISSIONS_REQUEST_CODE); + } + }); + } else { + Log.i(LOG_TAG, "Requesting permission"); + // Request permission. It's possible this can be auto answered if device policy + // sets the permission in a given state or the user denied the permission + // previously and checked "Never ask again". + ActivityCompat.requestPermissions(HomeActivity.this, + new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, + REQUEST_PERMISSIONS_REQUEST_CODE); + } + } + + /** + * Shows a {@link Snackbar} using {@code text}. + * + * @param text The Snackbar text. + */ + private void showSnackbar(final String text) { + View container = findViewById(android.R.id.content); + if (container != null) { + Snackbar.make(container, text, Snackbar.LENGTH_LONG).show(); + } + } + + /** + * Shows a {@link Snackbar}. + * + * @param mainTextStringId The id for the string resource for the Snackbar text. + * @param actionStringId The text of the action item. + * @param listener The listener associated with the Snackbar action. + */ + private void showSnackbar(final int mainTextStringId, final int actionStringId, + View.OnClickListener listener) { + Snackbar.make( + findViewById(android.R.id.content), + getString(mainTextStringId), + Snackbar.LENGTH_INDEFINITE) + .setAction(getString(actionStringId), listener).show(); + } + + /** + * Adds geofences. This method should be called after the user has granted the location + * permission. + */ + @SuppressWarnings("MissingPermission") + private void addGeofences(ArrayList geofenceArrayList) { + if (!checkPermissions()) { + showSnackbar(getString(R.string.insufficient_permissions)); + return; + } + geofencingClient.addGeofences(getGeofencingRequest(geofenceArrayList), getGeofencePendingIntent()); + } + + /** + * Removes geofences. This method should be called after the user has granted the location + * permission. + */ + @SuppressWarnings("MissingPermission") + private void removeGeofences() { + if (!checkPermissions()) { + showSnackbar(getString(R.string.insufficient_permissions)); + return; + } + geofencingClient.removeGeofences(getGeofencePendingIntent()); + } + + /** + * Gets a PendingIntent to send with the request to add or remove Geofences. Location Services + * issues the Intent inside this PendingIntent whenever a geofence transition occurs for the + * current list of geofences. + * + * @return A PendingIntent for the IntentService that handles geofence transitions. + */ + private PendingIntent getGeofencePendingIntent() { + // Reuse the PendingIntent if we already have it. + if (mGeofencePendingIntent != null) { + return mGeofencePendingIntent; + } + Intent intent = new Intent(this, GeofenceBroadcastReceiver.class); + // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling + // addGeofences() and removeGeofences(). + mGeofencePendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); + return mGeofencePendingIntent; + } + + /** + * Builds and returns a GeofencingRequest. Specifies the list of geofences to be monitored. + * Also specifies how the geofence notifications are initially triggered. + */ + private GeofencingRequest getGeofencingRequest(ArrayList geofenceList) { + GeofencingRequest.Builder builder = new GeofencingRequest.Builder(); + builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER); + builder.addGeofences(geofenceList); + return builder.build(); + } + + private GeofencingRequest getGeofenceRequest(Spot spot) { + List points = spot.getGeometry().getPolygonPoints(); + GeofencingRequest.Builder builder = new GeofencingRequest.Builder(); + builder.setInitialTrigger(GeofencingRequest.INITIAL_TRIGGER_ENTER); + builder.addGeofence(generateGeofence(points.get(0).getLatitud(), points.get(0).getLongitud(), + 15, "ParkinSpot" + spot.getProperties().getIdFromUrl())); + return builder.build(); + } + + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, + int[] grantResults) { + Log.i(LOG_TAG, "onRequestPermissionResult"); + if (requestCode == REQUEST_PERMISSIONS_REQUEST_CODE) { + if (grantResults.length <= 0) { + // If user interaction was interrupted, the permission request is cancelled and you + // receive empty arrays. + Log.i(LOG_TAG, "User interaction was cancelled."); + } else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + Log.i(LOG_TAG, "Permission granted."); + } else { + showSnackbar(R.string.permission_denied_explanation, R.string.settings, + new View.OnClickListener() { + @Override + public void onClick(View view) { + // Build intent that displays the App settings screen. + Intent intent = new Intent(); + intent.setAction( + Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + Uri uri = Uri.fromParts("package", + BuildConfig.APPLICATION_ID, null); + intent.setData(uri); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } + }); + } + } + } + + /** + * Removes location updates from the FusedLocationApi. + */ + private void stopLocationUpdates() { + mFusedLocationClient.removeLocationUpdates(mLocationCallback) + .addOnCompleteListener(this, new OnCompleteListener() { + @Override + public void onComplete(Task task) { + } + }); + } + + /** + * Requests location updates from the FusedLocationApi. Note: we don't call this unless location + * runtime permission has been granted. + */ + private void startLocationUpdates(LocationRequest locationRequest) { + // Begin by checking if the device has the necessary location settings. + mSettingsClient.checkLocationSettings(mLocationSettingsRequest) + .addOnSuccessListener(this, new OnSuccessListener() { + @SuppressLint("MissingPermission") + @Override + public void onSuccess(LocationSettingsResponse locationSettingsResponse) { + Log.i(LOG_TAG, "All location settings are satisfied."); + mFusedLocationClient.requestLocationUpdates(mLocationRequest, + mLocationCallback, Looper.myLooper()); + } + }) + .addOnFailureListener(this, new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + int statusCode = ((ApiException) e).getStatusCode(); + switch (statusCode) { + case LocationSettingsStatusCodes.RESOLUTION_REQUIRED: + Log.i(LOG_TAG, "Location settings are not satisfied. Attempting to upgrade " + + "location settings "); + try { + ResolvableApiException rae = (ResolvableApiException) e; + rae.startResolutionForResult(HomeActivity.this, Constants.REQUEST_CHECK_SETTINGS); + } catch (IntentSender.SendIntentException sie) { + Log.i(LOG_TAG, "PendingIntent unable to execute request."); + } + break; + case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE: + String errorMessage = "Location settings are inadequate, and cannot be " + + "fixed here. Fix in Settings."; + Log.e(LOG_TAG, errorMessage); + Toast.makeText(HomeActivity.this, errorMessage, Toast.LENGTH_LONG).show(); + } + } + }); + } + + /** + * Creates a callback for receiving location events. + */ + private void createLocationCallback() { + mLocationCallback = new LocationCallback() { + @Override + public void onLocationResult(LocationResult locationResult) { + super.onLocationResult(locationResult); + mCurrentLocation = locationResult.getLastLocation(); + checkForUserLocation(mCurrentLocation); + } + }; + } + + /** + - Is User in a spot? + - Is the user STILL in that spot? + * THEN, THE USER COULD BE: + * PARKING: + * - Is the spot free? + * THEN: show dialog for secure the action... + *FREEING A SPOT: + * - Is the spot occupied by the SAME user? + * THEN: show dialog for secure the action...**/ + private void checkForUserLocation(Location mCurrentLocation) { + int spotId = isPointInsideParkingSpot(spots, mCurrentLocation); + if (spotId != Constants.NOT_IN_PARKINGSPOT && + activityTransition != DetectedActivity.UNKNOWN) { + Spot spot = getSpotFromId(spots, spotId); + SpotProperties spotProperties = spot.getProperties(); + if (spotProperties.getState().equals(StatesEnumerations.FREE.getEstado()) || + spotProperties.getState().equals(StatesEnumerations.UNKNOWN.getEstado())) { + if(!dialogSendAllready){ + confirmationOfActionDialog(spotId, true); + } + } else { + if(!dialogSendAllready){ + confirmationOfActionDialog(spotId, false); + } + } + final Timer timer = new Timer(); + timer.schedule(new TimerTask() { + public void run() { + dialogSendAllready = false; + timer.cancel(); + } + }, Constants.getMinutesInMilliseconds()); + } + } + + private Spot getSpotFromId(List spots, int spotId) { + Spot result = new Spot(); + for (Spot spot : spots) { + if (spot.getProperties().getIdFromUrl() == spotId) { + result = spot; + } + } + return result; + } + + /** + * Show a dialog tha could be: + * OCCUPYING a spot OR FREEING ONE + * **/ + @SuppressWarnings("MissingPermission") + private void confirmationOfActionDialog(final int spotIdIn, final boolean isParking) { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + if (isParking) { + builder.setMessage(R.string.are_you_parking) + .setPositiveButton(R.string.button_accept, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + Utils.setNewStateOnSpot(HomeActivity.this, isParking, spotIdIn); +// geofencingClient.addGeofences(getGeofenceRequest(spotIn), +// getGeofencePendingIntent()); + } + }) + .setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + // User cancelled the dialog + } + }); + }else{ + builder.setMessage(R.string.are_you_vacating_a_place) + .setPositiveButton(R.string.button_accept, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + Utils.setNewStateOnSpot(HomeActivity.this, isParking, spotIdIn); +// List geofencesToRemove = new ArrayList<>(); +// geofencesToRemove.add("ParkinSpot" + spotIn.getId()); +// geofencingClient.removeGeofences(geofencesToRemove); + } + }) + .setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + // User cancelled the dialog + } + }); + } + final AlertDialog alertDialog = builder.create(); + alertDialog.show(); + dialogSendAllready = true; + + final Timer timer = new Timer(); + timer.schedule(new TimerTask() { + public void run() { + alertDialog.dismiss(); + Utils.setNewStateOnSpot(HomeActivity.this, isParking, spotIdIn); + timer.cancel(); + } + }, 15000); + } + + public boolean isPointInsidePolygon(Spot spot, Location location){ + return PolyUtil.containsLocation(location.getLatitude(),location.getLongitude(),spot.toLatLngList(), + true); + } + + public int isPointInsideParkingSpot(List ParkingSpot, Location location){ + for(Spot spot : ParkingSpot){ + if (isPointInsidePolygon(spot, location)){ + return spot.getProperties().getIdFromUrl(); + } + } + return Constants.NOT_IN_PARKINGSPOT; + } + /** + * Sets up the location request. Android has two location request settings: + * {@code ACCESS_COARSE_LOCATION} and {@code ACCESS_FINE_LOCATION}. These settings control + * the accuracy of the current location. This sample uses ACCESS_FINE_LOCATION, as defined in + * the AndroidManifest.xml. + *

+ * When the ACCESS_FINE_LOCATION setting is specified, combined with a fast update + * interval (5 seconds), the Fused Location Provider API returns location updates that are + * accurate to within a few feet. + *

+ * These settings are appropriate for mapping applications that show real-time location + * updates. + */ + private void createLocationRequest(long interval, long fastestInterval) { + mLocationRequest = new LocationRequest(); + mLocationRequest.setInterval(interval); + mLocationRequest.setFastestInterval(fastestInterval); + mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); + } + /** + * Uses a {@link com.google.android.gms.location.LocationSettingsRequest.Builder} to build + * a {@link com.google.android.gms.location.LocationSettingsRequest} that is used for checking + * if a device has the needed location settings. + */ + private void buildLocationSettingsRequest() { + LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder(); + builder.addLocationRequest(mLocationRequest); + mLocationSettingsRequest = builder.build(); + } + /** + * Registers for activity recognition updates using + * {@link ActivityRecognitionClient#requestActivityUpdates(long, PendingIntent)}. + * Registers success and failure callbacks. + */ + public void requestActivityUpdates() { + Task task = mActivityRecognitionClient.requestActivityUpdates( + Constants.DETECTION_INTERVAL_IN_MILLISECONDS, + getActivityDetectionPendingIntent()); + + task.addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(Void result) { + setUpdatesRequestedState(true); + } + }); + task.addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + Log.w(LOG_TAG, getString(R.string.activity_updates_not_enabled)); + setUpdatesRequestedState(false); + } + }); + } + /** + * Removes activity recognition updates using + * {@link ActivityRecognitionClient#removeActivityUpdates(PendingIntent)}. Registers success and + * failure callbacks. + */ + public void removeActivityUpdates() { + @SuppressLint("MissingPermission") + Task task = mActivityRecognitionClient.removeActivityUpdates( + getActivityDetectionPendingIntent()); + task.addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(Void result) { + setUpdatesRequestedState(false); + // Reset the display. + } + }); + + task.addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + Log.w(LOG_TAG, "Failed to enable activity recognition."); + Toast.makeText(HomeActivity.this, + getString(R.string.activity_updates_not_removed), + Toast.LENGTH_SHORT).show(); + setUpdatesRequestedState(true); + } + }); + } + /** + * Gets a PendingIntent to be sent for each activity detection. + */ + private PendingIntent getActivityDetectionPendingIntent() { + Intent intent = new Intent(this, DetectedActivitiesService.class); + // We use FLAG_UPDATE_CURRENT so that we get the same pending intent back when calling + // requestActivityUpdates() and removeActivityUpdates(). + return PendingIntent.getService(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); + } + /** + * Sets the boolean in SharedPreferences that tracks whether we are requesting activity + * updates. + */ + private void setUpdatesRequestedState(boolean requesting) { + PreferenceManager.getDefaultSharedPreferences(this) + .edit() + .putBoolean(Constants.KEY_ACTIVITY_UPDATES_REQUESTED, requesting) + .apply(); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Inflate the menu; this adds items to the action bar if it is present. + getMenuInflater().inflate(R.menu.menu_main, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences( + Constants.CLIENTE_DATA, Context.MODE_PRIVATE); + final SharedPreferences.Editor editor = sharedPreferences.edit(); + int id = item.getItemId(); + //noinspection SimplifiableIfStatement + if (id == R.id.menu_changepass) { + Intent changePassIntent = new Intent(HomeActivity.this, ChangePasswordActivity.class); + startActivity(changePassIntent); + return true; + }else if(id == R.id.menu_logout){ + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setMessage(R.string.are_you_sure_logout) + .setPositiveButton(R.string.button_accept, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + editor.putString(Constants.USER_TOKEN, Constants.CLIENT_NOT_LOGIN).apply(); + editor.commit(); + Intent logoutIntent = new Intent(HomeActivity.this, LoginActivity.class); + logoutIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(logoutIntent); + } + }) + .setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + // User cancelled the dialog + } + }); + // Create the AlertDialog object and return it + builder.create().show(); + + return true; + } + return super.onOptionsItemSelected(item); + } + +} diff --git a/app/src/main/java/smarttraffic/smartparking/activities/InitActivity.java b/app/src/main/java/smarttraffic/smartparking/activities/InitActivity.java new file mode 100644 index 0000000..069536c --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/activities/InitActivity.java @@ -0,0 +1,106 @@ +package smarttraffic.smartparking.activities; + +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.view.Gravity; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.Toast; + + +import smarttraffic.smartparking.Constants; +import smarttraffic.smartparking.R; + +/** + * Created by Joaquin Olivera on july 19. + * + * @author joaquin + */ + +public class InitActivity extends AppCompatActivity { + + private boolean withInternetConnection; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.init_layout); + + final SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences( + Constants.CLIENTE_DATA, Context.MODE_PRIVATE); + + final ProgressDialog progressDialog = new ProgressDialog(InitActivity.this, + R.style.AppTheme_Dark_Dialog); + progressDialog.setIndeterminate(true); + progressDialog.setMessage("Inicializando aplicación..."); + progressDialog.show(); + + new android.os.Handler().postDelayed( + new Runnable() { + public void run() { + if (isNetworkAvailable()) { + setWithInternetConnection(true); + initializeFirstActivity(sharedPreferences); + } else { + setWithInternetConnection(false); + showToast(getString(R.string.no_network_connection)); + } + progressDialog.dismiss(); + } + }, 2000); + } + + private boolean isNetworkAvailable() { + ConnectivityManager connectivityManager + = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo(); + return activeNetworkInfo != null && activeNetworkInfo.isConnected(); + } + + public void setWithInternetConnection(boolean withInternetConnection) { + this.withInternetConnection = withInternetConnection; + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + } + + private void initializeFirstActivity(SharedPreferences sharedPreferences) { + String userToken = sharedPreferences.getString(Constants.USER_TOKEN, + Constants.CLIENT_NOT_LOGIN); + if(userToken.equals(Constants.CLIENT_NOT_LOGIN)){ + Intent registration = new Intent(InitActivity.this, + RegistryActivity.class); + startActivity(registration); + }else{ + Intent registration = new Intent(InitActivity.this, + HomeActivity.class); + startActivity(registration); + } + finish(); + } + + private void showToast(String message) { + Toast toast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG); + toast.setGravity(Gravity.CENTER, 0, 0); + LinearLayout toastContentView = (LinearLayout) toast.getView(); + ImageView imageView = new ImageView(getApplicationContext()); + imageView.setImageResource(R.mipmap.smartparking_logo_round); + toastContentView.addView(imageView, 0); + toast.show(); + } + +} + diff --git a/app/src/main/java/smarttraffic/smartparking/activities/LoginActivity.java b/app/src/main/java/smarttraffic/smartparking/activities/LoginActivity.java new file mode 100644 index 0000000..01d950a --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/activities/LoginActivity.java @@ -0,0 +1,144 @@ +package smarttraffic.smartparking.activities; + +import android.app.ProgressDialog; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; +import android.view.Gravity; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import butterknife.BindView; +import butterknife.ButterKnife; + +import smarttraffic.smartparking.R; +import smarttraffic.smartparking.receivers.LoginReceiver; +import smarttraffic.smartparking.services.LoginService; + +/** + * Created by Joaquin Olivera on july 19. + * + * @author joaquin + */ + +public class LoginActivity extends AppCompatActivity { + + private static final String LOG_TAG = "LoginActivity"; + + // binds the elements of the login_layout + @BindView(R.id.usernameLogin) + EditText usernameText; + @BindView(R.id.passwordLogin) + EditText passwordText; + @BindView(R.id.loginButton) + Button loginButton; + @BindView(R.id.linkSignUp) + TextView goSignUp; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + setContentView(R.layout.login_layout); + super.onCreate(savedInstanceState); + ButterKnife.bind(this); + + loginButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if(checkCredentialsInput()){ + makeLoginHappen(); + // function that makes the makeLoginHappen process... + } + } + }); + + goSignUp.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent intent = new Intent(LoginActivity.this, RegistryActivity.class); + startActivity(intent); + } + }); + + IntentFilter filter = new IntentFilter(); + filter.addAction(LoginService.LOGIN_ACTION); + filter.addAction(LoginService.BAD_LOGIN_ACTION); + LoginReceiver loginReceiver = new LoginReceiver(); + registerReceiver(loginReceiver, filter); + + Intent intent = getIntent(); + String statusRegistry = intent.getStringExtra("status_registro"); + if(statusRegistry != null){ + showToast(statusRegistry); + } + } + + private void makeLoginHappen() { + Log.d(LOG_TAG, "User trying to make the login"); + + loginButton.setEnabled(false); + + final ProgressDialog progressDialog = new ProgressDialog(LoginActivity.this, + R.style.AppTheme_Dark_Dialog); + progressDialog.setIndeterminate(true); + progressDialog.setMessage("Verificando..."); + sendLoginRequest(); + progressDialog.show(); + + new android.os.Handler().postDelayed( + new Runnable() { + public void run() { + /**Here the service get the request of Login...**/ + loginButton.setEnabled(true); + progressDialog.dismiss(); + } + }, 2000); + eraseCredentials(); + } + + private void eraseCredentials() { + usernameText.setText(""); + passwordText.setText(""); + } + + private void sendLoginRequest() { + Intent loginIntent = new Intent(LoginActivity.this, LoginService.class); + loginIntent.putExtra("username", usernameText.getText().toString()); + loginIntent.putExtra("password", passwordText.getText().toString()); + startService(loginIntent); + } + + @Override + public void onBackPressed() { + // disable going back... + moveTaskToBack(true); + } + + // Show images in Toast prompt. + private void showToast(String message) { + Toast toast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG); + toast.setGravity(Gravity.CENTER, 0, 0); + LinearLayout toastContentView = (LinearLayout) toast.getView(); + ImageView imageView = new ImageView(getApplicationContext()); + imageView.setImageResource(R.mipmap.smartparking_logo_round); + toastContentView.addView(imageView, 0); + toast.show(); + } + + private boolean checkCredentialsInput(){ + if(usernameText.getText().toString() != null){ + return true; + }else{ + showToast("El USERNAME no puede estar vacio!"); + return false; + } + } + +} diff --git a/app/src/main/java/smarttraffic/smartparking/activities/RegistryActivity.java b/app/src/main/java/smarttraffic/smartparking/activities/RegistryActivity.java new file mode 100644 index 0000000..ada4a6d --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/activities/RegistryActivity.java @@ -0,0 +1,270 @@ +package smarttraffic.smartparking.activities; + +import android.app.DatePickerDialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.annotation.RequiresApi; +import android.support.v7.app.AppCompatActivity; +import android.text.method.HideReturnsTransformationMethod; +import android.text.method.PasswordTransformationMethod; +import android.util.Log; +import android.view.Gravity; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.DatePicker; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.TextView; +import android.widget.Toast; + +import java.util.Calendar; +import java.util.Random; + +import butterknife.BindView; +import butterknife.ButterKnife; +import smarttraffic.smartparking.R; +import smarttraffic.smartparking.receivers.RegistrationReceiver; +import smarttraffic.smartparking.services.RegistrationService; + +/** + * Created by Joaquin Olivera on july 19. + * + * @author joaquin + */ + +public class RegistryActivity extends AppCompatActivity { + + /** + * The user register and get a profile on the system... + * **/ + + private static final String LOG_TAG = "RegistryActivity"; + + private static final String CERO = "0"; + private static final String GUION = "-"; + + @BindView(R.id.usernameSignUp) + TextView usernameInput; + @BindView(R.id.passwordSignUp) + EditText passwordInput; + @BindView(R.id.birthDate) + TextView birthDate; + @BindView(R.id.maleRadButton) + RadioButton maleRadButton; + @BindView(R.id.femaleRadButton) + RadioButton femaleRadButton; + @BindView(R.id.datePickerButton) + ImageButton datePickerButton; + @BindView(R.id.sexRadioGroup) + RadioGroup sexSelectRadioGroup; + @BindView(R.id.acceptTermsCheckBox) + CheckBox termsAndConditions; + @BindView(R.id.textInTermsAndCond) + TextView textInTermsAndCond; + @BindView(R.id.signUpButton) + Button signInButton; + @BindView(R.id.goToLogin) + Button goToLogin; + @BindView(R.id.passModeButton) + ImageButton passwordModeButton; + @BindView(R.id.setRandomUser) + ImageButton randomUser; + + public final Calendar calendar = Calendar.getInstance(); + private final int MAX_LENGTH = 10; + public static Random RANDOM = new Random(); + public static final String DATA = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + final int actuallMonth = calendar.get(Calendar.MONTH); + final int actuallDay = calendar.get(Calendar.DAY_OF_MONTH); + final int actuallYear = calendar.get(Calendar.YEAR); + private boolean showPasswordText = false; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.registry_layout); + ButterKnife.bind(this); + +// signInButton.setEnabled(false); + //TODO:make EULAActivity... +// textInTermsAndCond.setOnClickListener(new View.OnClickListener() { +// @Override +// public void onClick(View v) { +// Intent intent = new Intent(RegistryActivity.this, EulaActivity.class); +// startActivity(intent); +// } +// }); + + IntentFilter filter = new IntentFilter(); + filter.addAction(RegistrationService.REGISTRATION_OK); + filter.addAction(RegistrationService.BAD_REGISTRATION); + RegistrationReceiver registrationReceiver = new RegistrationReceiver(); + registerReceiver(registrationReceiver, filter); + + datePickerButton.setOnClickListener(new View.OnClickListener() { + @RequiresApi(api = Build.VERSION_CODES.N) + @Override + public void onClick(View v) { + getDatePickedUp(); + } + }); + signInButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + createRegister(); + } + }); + goToLogin.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + goToLoginActivity(); + } + }); + passwordModeButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Context context = getApplicationContext(); + //TODO: if image is showText set TO don't ShowText + // and set password text Visual for user... + if(!showPasswordText){ + passwordModeButton.setImageDrawable( + context.getDrawable(R.drawable.dontshowtext)); + //Show Password: + passwordInput.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); + showPasswordText = !showPasswordText; + }else{ + passwordModeButton.setImageDrawable(context.getDrawable(R.drawable.showtext)); + //Hide Password: + passwordInput.setTransformationMethod(PasswordTransformationMethod.getInstance()); + showPasswordText = !showPasswordText; + } + } + }); + randomUser.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + usernameInput.setText(randomString()); + } + }); + } + + private void goToLoginActivity() { + Intent intent = new Intent(RegistryActivity.this, LoginActivity.class); + startActivity(intent); + } + + @RequiresApi(api = Build.VERSION_CODES.N) + private void getDatePickedUp() { + DatePickerDialog datePickerDialog = new DatePickerDialog(this, R.style.datepicker, new DatePickerDialog.OnDateSetListener() { + @Override + public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) { + final int mesActual = month + 1; + String diaFormateado = (dayOfMonth < 10)? CERO + String.valueOf(dayOfMonth):String.valueOf(dayOfMonth); + String mesFormateado = (mesActual < 10)? CERO + String.valueOf(mesActual):String.valueOf(mesActual); + birthDate.setText(year + GUION + mesFormateado + GUION + diaFormateado); + } + + }, actuallYear, actuallMonth, actuallDay); + datePickerDialog.show(); + } + + private void createRegister() { + Log.d(LOG_TAG, "User trying to registry"); + + signInButton.setEnabled(false); + + final ProgressDialog progressDialog = new ProgressDialog(RegistryActivity.this, + R.style.AppTheme_Dark_Dialog); + progressDialog.setIndeterminate(true); + progressDialog.setMessage("Creando el registro..."); + + if(dataIsCorrectlyComplete()){ + sendRegistrationPetition(); + progressDialog.show(); + new android.os.Handler().postDelayed( + new Runnable() { + public void run() { + /**Here the service get the request of registration...**/ + signInButton.setEnabled(true); + progressDialog.dismiss(); + } + }, 3000); + } + } + + private boolean dataIsCorrectlyComplete() { + if(termsAndConditions.isChecked()){ + if(passwordInput.getText().toString().length() > 5){ + if(maleRadButton.isChecked() || femaleRadButton.isChecked()){ + if(!birthDate.getText().toString().isEmpty()){ + return true; + }else{ + showToast("Favor ponga su EDAD(en años)!"); + return false; + } + }else{ + showToast("Es necesario elegir alguna opcion de SEXO!"); + return false; + } + }else{ + showToast("La CONTRASEÑA debe tener al menos 6 caracteres!"); + return false; + } + }else{ + showToast("Tienes que aceptar los TERMINOS y CONDICIONES!"); + return false; + } + } + + private void sendRegistrationPetition() { + Intent registryIntent = new Intent(RegistryActivity.this, RegistrationService.class); + registryIntent.putExtra("username", usernameInput.getText().toString()); + registryIntent.putExtra("password", passwordInput.getText().toString()); + registryIntent.putExtra("birth_date", birthDate.getText().toString()); + if(onRadioButtonClicked() != null){ + registryIntent.putExtra("sex", onRadioButtonClicked()); + } + startService(registryIntent); + } + + public String onRadioButtonClicked() { + if(femaleRadButton.isChecked()){ + return "F"; + }else if(maleRadButton.isChecked()){ + return "M"; + }else{ + return null; + } + } + + // Show images in Toast prompt. + private void showToast(String message) { + Toast toast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG); + toast.setGravity(Gravity.CENTER, 0, 0); + LinearLayout toastContentView = (LinearLayout) toast.getView(); + ImageView imageView = new ImageView(getApplicationContext()); + imageView.setImageResource(R.mipmap.smartparking_logo_round); + toastContentView.addView(imageView, 0); + toast.show(); + } + + private String randomString() { + StringBuilder sb = new StringBuilder(MAX_LENGTH); + + for (int i = 0; i < MAX_LENGTH; i++) { + sb.append(DATA.charAt(RANDOM.nextInt(DATA.length()))); + } + return sb.toString(); + } + +} diff --git a/app/src/main/java/smarttraffic/smartparking/activities/ResetPassActivity.java b/app/src/main/java/smarttraffic/smartparking/activities/ResetPassActivity.java new file mode 100644 index 0000000..72f232b --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/activities/ResetPassActivity.java @@ -0,0 +1,155 @@ +package smarttraffic.smartparking.activities; + +import android.app.DatePickerDialog; +import android.app.ProgressDialog; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.annotation.RequiresApi; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; +import android.view.Gravity; +import android.view.View; +import android.widget.Button; +import android.widget.DatePicker; +import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RadioButton; +import android.widget.TextView; +import android.widget.Toast; + +import java.util.Calendar; + +import butterknife.BindView; +import butterknife.ButterKnife; +import smarttraffic.smartparking.R; + +/** + * Created by Joaquin Olivera on july 19. + * + * @author joaquin + */ + +public class ResetPassActivity extends AppCompatActivity { + + /** + * Reset Password if user lost it... + * **/ + + private static final String LOG_TAG = "ResetPassActivity"; + private static final String CERO = "0"; + private static final String GUION = "-"; + private static final String FAIL_RESET_MESSAGE = "Algo sucedio durante el proceso de " + + "recuperacion de la contraseña"; + + @BindView(R.id.birthDateResetPass) + TextView birthDate; + @BindView(R.id.usernameResetPass) + EditText username; + @BindView(R.id.resetPassButton) + Button resetPass; + @BindView(R.id.datePickerButtonResetPass) + ImageButton datePickerButton; + @BindView(R.id.maleResetPass) + RadioButton maleRadioButton; + @BindView(R.id.femaleResetPass) + RadioButton femaleRadioButton; + + public final Calendar calendar = Calendar.getInstance(); + + final int actuallMonth = calendar.get(Calendar.MONTH); + final int actuallDay = calendar.get(Calendar.DAY_OF_MONTH); + final int actuallYear = calendar.get(Calendar.YEAR); + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.reset_password_layout); + ButterKnife.bind(this); + + datePickerButton.setOnClickListener(new View.OnClickListener() { + @RequiresApi(api = Build.VERSION_CODES.N) + @Override + public void onClick(View v) { + getDatePickedUp(); + } + }); + + resetPass.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + resetUsersPassword(); + } + }); + + } + + @RequiresApi(api = Build.VERSION_CODES.N) + private void getDatePickedUp() { + DatePickerDialog datePickerDialog = new DatePickerDialog(this, R.style.datepicker, new DatePickerDialog.OnDateSetListener() { + @Override + public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) { + final int mesActual = month + 1; + String diaFormateado = (dayOfMonth < 10)? CERO + String.valueOf(dayOfMonth):String.valueOf(dayOfMonth); + String mesFormateado = (mesActual < 10)? CERO + String.valueOf(mesActual):String.valueOf(mesActual); + birthDate.setText(year + GUION + mesFormateado + GUION + diaFormateado); + } + + }, actuallYear, actuallMonth, actuallDay); + datePickerDialog.show(); + } + + private void resetUsersPassword() { + Log.d(LOG_TAG, "User trying to reset password!"); + + resetPass.setEnabled(false); + + final ProgressDialog progressDialog = new ProgressDialog(ResetPassActivity.this, + R.style.AppTheme_Dark_Dialog); + progressDialog.setIndeterminate(true); + progressDialog.setMessage("Realizando las consultas pertinentes..."); + + //TODO: with data introduce, consult if user exists with those data... + sendResetPassRequest(); + progressDialog.show(); + new android.os.Handler().postDelayed( + new Runnable() { + public void run() { + resetPass.setEnabled(true); + progressDialog.dismiss(); + } + }, 3000); + } + + private void sendResetPassRequest() { + //TODO: request the DB if a user with data introduced exists... + /** + * @params: username, onRadioButtonClicked(), birthDate + * **/ + } + + + // Show images in Toast prompt. + private void showToast(String message) { + Toast toast = Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG); + toast.setGravity(Gravity.CENTER, 0, 0); + LinearLayout toastContentView = (LinearLayout) toast.getView(); + ImageView imageView = new ImageView(getApplicationContext()); + imageView.setImageResource(R.mipmap.smartparking_logo_round); + toastContentView.addView(imageView, 0); + toast.show(); + } + + public String onRadioButtonClicked() { + if(femaleRadioButton.isChecked()){ + return "F"; + }else if(maleRadioButton.isChecked()){ + return "M"; + }else{ + return null; + } + } + +} diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/Credentials.java b/app/src/main/java/smarttraffic/smartparking/dataModels/Credentials.java new file mode 100644 index 0000000..eed8e55 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/Credentials.java @@ -0,0 +1,40 @@ +package smarttraffic.smartparking.dataModels; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.dataModels + */ + +public class Credentials { + + private String username; + private String password; + + public Credentials() { + } + + @Override + public String toString() { + return "Credentials{" + + "username='" + username + '\'' + + ", password='" + password + '\'' + + '}'; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/EventProperties.java b/app/src/main/java/smarttraffic/smartparking/dataModels/EventProperties.java new file mode 100644 index 0000000..0688409 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/EventProperties.java @@ -0,0 +1,50 @@ +package smarttraffic.smartparking.dataModels; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.dataModels + */ + +public class EventProperties { + + private String application; + private String e_type; + private String agent; + + public EventProperties() { + } + + @Override + public String toString() { + return "EventProperties{" + + "application=" + application + + ", e_type='" + e_type + '\'' + + ", agent='" + agent + '\'' + + '}'; + } + + public String getApplication() { + return application; + } + + public void setApplication(String application) { + this.application = application; + } + + public String getE_type() { + return e_type; + } + + public void setE_type(String e_type) { + this.e_type = e_type; + } + + public String getAgent() { + return agent; + } + + public void setAgent(String agent) { + this.agent = agent; + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/Events.java b/app/src/main/java/smarttraffic/smartparking/dataModels/Events.java new file mode 100644 index 0000000..dd742f3 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/Events.java @@ -0,0 +1,52 @@ +package smarttraffic.smartparking.dataModels; + +import smarttraffic.smartparking.dataModels.Lots.PointGeometry; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.dataModels + */ + +public class Events { + + private String type; + private EventProperties properties; + private PointGeometry geometry; + + public Events() { + } + + @Override + public String toString() { + return "Events{" + + "type='" + type + '\'' + + ", properties=" + properties + + ", geometry=" + geometry + + '}'; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public EventProperties getProperties() { + return properties; + } + + public void setProperties(EventProperties properties) { + this.properties = properties; + } + + public PointGeometry getGeometry() { + return geometry; + } + + public void setGeometry(PointGeometry geometry) { + this.geometry = geometry; + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/Lots/Lot.java b/app/src/main/java/smarttraffic/smartparking/dataModels/Lots/Lot.java new file mode 100644 index 0000000..add3ce4 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/Lots/Lot.java @@ -0,0 +1,50 @@ +package smarttraffic.smartparking.dataModels.Lots; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.dataModels + */ + +public class Lot { + + private String type; + private LotProperties properties; + private PointGeometry geometry; + + public Lot() { + } + + @Override + public String toString() { + return "Lot{" + + "type='" + type + '\'' + + ", properties=" + properties + + ", geometry=" + geometry + + '}'; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public LotProperties getProperties() { + return properties; + } + + public void setProperties(LotProperties properties) { + this.properties = properties; + } + + public PointGeometry getGeometry() { + return geometry; + } + + public void setGeometry(PointGeometry geometry) { + this.geometry = geometry; + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/Lots/LotList.java b/app/src/main/java/smarttraffic/smartparking/dataModels/Lots/LotList.java new file mode 100644 index 0000000..ce41257 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/Lots/LotList.java @@ -0,0 +1,44 @@ +package smarttraffic.smartparking.dataModels.Lots; + +import java.util.List; + +import smarttraffic.smartparking.dataModels.Lots.Lot; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.dataModels + */ + +public class LotList { + + private String type; + private List features; + + public LotList() { + } + + @Override + public String toString() { + return "LotList{" + + "type='" + type + '\'' + + ", features=" + features + + '}'; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public List getFeatures() { + return features; + } + + public void setFeatures(List features) { + this.features = features; + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/Lots/LotProperties.java b/app/src/main/java/smarttraffic/smartparking/dataModels/Lots/LotProperties.java new file mode 100644 index 0000000..154e034 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/Lots/LotProperties.java @@ -0,0 +1,66 @@ +package smarttraffic.smartparking.dataModels.Lots; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.dataModels + */ + +public class LotProperties { + + private String url; + private float radio; + private String name; + private PointGeometry center; + + public LotProperties() { + } + + @Override + public String toString() { + return "LotProperties{" + + "url='" + url + '\'' + + ", radio=" + radio + + ", name='" + name + '\'' + + ", center=" + center + + '}'; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public float getRadio() { + return radio; + } + + public void setRadio(float radio) { + this.radio = radio; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public PointGeometry getCenter() { + return center; + } + + public void setCenter(PointGeometry center) { + this.center = center; + } + + public int getIdFromUrl() { + String[] parts = getUrl().split("/"); + return Integer.parseInt(parts[parts.length - 1]); + } + +} diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/Lots/PointGeometry.java b/app/src/main/java/smarttraffic/smartparking/dataModels/Lots/PointGeometry.java new file mode 100644 index 0000000..87e14bd --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/Lots/PointGeometry.java @@ -0,0 +1,76 @@ +package smarttraffic.smartparking.dataModels.Lots; + +import android.location.Location; + +import java.util.ArrayList; +import java.util.List; + +import smarttraffic.smartparking.dataModels.Point; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.dataModels + */ + +public class PointGeometry { + + private String type = "Point"; + private List coordinates; + + public PointGeometry() { + } + + @Override + public String toString() { + return "PointGeometry{" + + "type='" + type + '\'' + + ", coordinates=" + coordinates + + '}'; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public List getCoordinates() { + return coordinates; + } + + public void setCoordinates(List coordinates) { + this.coordinates = coordinates; + } + + public Point getCenterPoint(){ + if(getCoordinates() != null){ + Point centerPoint = new Point(getCoordinates().get(0), getCoordinates().get(1)); + return centerPoint; + } + return null; + } + + public Point getPointCoordinates(){ + if(getCoordinates() != null){ + Point centerPoint = new Point(getCoordinates().get(1), getCoordinates().get(0)); + return centerPoint; + } + return null; + } + + public void setPointCoordinates(Location location){ + List points = new ArrayList(); + if(location != null){ + points.add(location.getLongitude()); + points.add(location.getLatitude()); + }else{ + points.add((double) 0); + points.add((double) 0); + } + + setCoordinates(points); + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/NearbyLocation.java b/app/src/main/java/smarttraffic/smartparking/dataModels/NearbyLocation.java new file mode 100644 index 0000000..85f584c --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/NearbyLocation.java @@ -0,0 +1,44 @@ +package smarttraffic.smartparking.dataModels; + +import java.sql.Timestamp; +import java.util.Date; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.dataModels + */ + +public class NearbyLocation { + + private NearbyPoint point; + private String previous_timestamp; + + public NearbyLocation() { + } + + @Override + public String toString() { + return "NearbyLocation{" + + "point=" + point + + ", previous_timestamp=" + previous_timestamp + + '}'; + } + + public NearbyPoint getPoint() { + return point; + } + + public void setPoint(NearbyPoint point) { + this.point = point; + } + + public String getPrevious_timestamp() { + return previous_timestamp; + } + + public void setPrevious_timestamp(String previous_timestamp) { + this.previous_timestamp = previous_timestamp; + } +} + diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/NearbyPoint.java b/app/src/main/java/smarttraffic/smartparking/dataModels/NearbyPoint.java new file mode 100644 index 0000000..db3a2fc --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/NearbyPoint.java @@ -0,0 +1,40 @@ +package smarttraffic.smartparking.dataModels; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.dataModels + */ + +public class NearbyPoint { + + private double lon; + private double lat; + + public NearbyPoint() { + } + + @Override + public String toString() { + return "NearbyPoint{" + + "lon=" + lon + + ", lat=" + lat + + '}'; + } + + public double getLon() { + return lon; + } + + public void setLon(double lon) { + this.lon = lon; + } + + public double getLat() { + return lat; + } + + public void setLat(double lat) { + this.lat = lat; + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/Point.java b/app/src/main/java/smarttraffic/smartparking/dataModels/Point.java new file mode 100644 index 0000000..501b14f --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/Point.java @@ -0,0 +1,42 @@ +package smarttraffic.smartparking.dataModels; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.dataModels + */ + +public class Point { + + private double latitud; + private double longitud; + + public Point(double latitud, double longitud) { + this.latitud = latitud; + this.longitud = longitud; + } + + @Override + public String toString() { + return "Point{" + + "latitud=" + latitud + + ", longitud=" + longitud + + '}'; + } + + public double getLatitud() { + return latitud; + } + + public void setLatitud(double latitud) { + this.latitud = latitud; + } + + public double getLongitud() { + return longitud; + } + + public void setLongitud(double longitud) { + this.longitud = longitud; + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/ProfileRegistry.java b/app/src/main/java/smarttraffic/smartparking/dataModels/ProfileRegistry.java new file mode 100644 index 0000000..fc4b90f --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/ProfileRegistry.java @@ -0,0 +1,49 @@ +package smarttraffic.smartparking.dataModels; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.dataModels + */ + +public class ProfileRegistry { + + private String username; + private String password; + private SmartParkingProfile smartparkingprofile; + + @Override + public String toString() { + return "ProfileRegistry{" + + "username='" + username + '\'' + + ", password='" + password + '\'' + + ", smartParkingProfile=" + smartparkingprofile + + '}'; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public SmartParkingProfile getSmartParkingProfile() { + return smartparkingprofile; + } + + public void setSmartParkingProfile(SmartParkingProfile smartParkingProfile) { + this.smartparkingprofile = smartParkingProfile; + } + +} + diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/ProfileUser.java b/app/src/main/java/smarttraffic/smartparking/dataModels/ProfileUser.java new file mode 100644 index 0000000..63c63cb --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/ProfileUser.java @@ -0,0 +1,50 @@ +package smarttraffic.smartparking.dataModels; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.dataModels + */ + +public class ProfileUser { + + private String url; + private String username; + private SmartParkingProfile smartparkingprofile; + + public ProfileUser() { + } + + @Override + public String toString() { + return "ProfileUser{" + + "url='" + url + '\'' + + ", username='" + username + '\'' + + ", smartParkingProfile=" + smartparkingprofile + + '}'; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public SmartParkingProfile getSmartParkingProfile() { + return smartparkingprofile; + } + + public void setSmartParkingProfile(SmartParkingProfile smartParkingProfile) { + this.smartparkingprofile = smartParkingProfile; + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/SmartParkingProfile.java b/app/src/main/java/smarttraffic/smartparking/dataModels/SmartParkingProfile.java new file mode 100644 index 0000000..2afbef7 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/SmartParkingProfile.java @@ -0,0 +1,41 @@ +package smarttraffic.smartparking.dataModels; + +/** + * Created by Joaquin Olivera on july 19. + * + * @author joaquin + */ + +public class SmartParkingProfile { + + private String birth_date; + private String sex; + + public SmartParkingProfile() { + } + + @Override + public String toString() { + return "SmartParkingProfile{" + + "birth_date='" + birth_date + '\'' + + ", sex='" + sex + '\'' + + '}'; + } + + public String getBirth_date() { + return birth_date; + } + + public void setBirth_date(String birth_date) { + this.birth_date = birth_date; + } + + public String getSex() { + return sex; + } + + public void setSex(String sex) { + this.sex = sex; + } + +} diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/Spots/PolygonGeometry.java b/app/src/main/java/smarttraffic/smartparking/dataModels/Spots/PolygonGeometry.java new file mode 100644 index 0000000..22403d2 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/Spots/PolygonGeometry.java @@ -0,0 +1,46 @@ +package smarttraffic.smartparking.dataModels.Spots; + +import java.util.ArrayList; +import java.util.List; + +import smarttraffic.smartparking.dataModels.Point; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.dataModels + */ + +public class PolygonGeometry { + + private String type; + private List>> coordinates; + + public List>> getCoordinates() { + return coordinates; + } + + public void setCoordinates(List>> coordinates) { + this.coordinates = coordinates; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public List getPolygonPoints(){ + List result = new ArrayList<>(); + List> cordenadas = getCoordinates().get(0); + if(cordenadas != null){ + for(List point : cordenadas){ + Point newPoint = new Point(point.get(1), point.get(0)); + result.add(newPoint); + } + } + return result; + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/Spots/Spot.java b/app/src/main/java/smarttraffic/smartparking/dataModels/Spots/Spot.java new file mode 100644 index 0000000..e8bedb9 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/Spots/Spot.java @@ -0,0 +1,68 @@ +package smarttraffic.smartparking.dataModels.Spots; + +import com.google.android.gms.maps.model.LatLng; + +import java.util.ArrayList; +import java.util.List; + +import smarttraffic.smartparking.dataModels.Point; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.dataModels + */ + +public class Spot { + + private String type; + private SpotProperties properties; + private PolygonGeometry geometry; + + public Spot() { + } + + @Override + public String toString() { + return "Spot{" + + "type='" + type + '\'' + + ", properties=" + properties + + ", geometry=" + geometry + + '}'; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public SpotProperties getProperties() { + return properties; + } + + public void setProperties(SpotProperties properties) { + this.properties = properties; + } + + public PolygonGeometry getGeometry() { + return geometry; + } + + public void setGeometry(PolygonGeometry geometry) { + this.geometry = geometry; + } + + public List toLatLngList(){ + List listOfSpots = getGeometry().getPolygonPoints(); + List resultList = new ArrayList(); + if(listOfSpots != null){ + for(Point point : listOfSpots){ + resultList.add(new LatLng(point.getLatitud(),point.getLongitud())); + } + } + return resultList; + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/Spots/SpotList.java b/app/src/main/java/smarttraffic/smartparking/dataModels/Spots/SpotList.java new file mode 100644 index 0000000..9323796 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/Spots/SpotList.java @@ -0,0 +1,42 @@ +package smarttraffic.smartparking.dataModels.Spots; + +import java.util.List; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.dataModels + */ + +public class SpotList { + + private String type; + private List features; + + public SpotList() { + } + + @Override + public String toString() { + return "SpotList{" + + "type='" + type + '\'' + + ", features=" + features + + '}'; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public List getFeatures() { + return features; + } + + public void setFeatures(List features) { + this.features = features; + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/Spots/SpotProperties.java b/app/src/main/java/smarttraffic/smartparking/dataModels/Spots/SpotProperties.java new file mode 100644 index 0000000..7660f10 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/Spots/SpotProperties.java @@ -0,0 +1,60 @@ +package smarttraffic.smartparking.dataModels.Spots; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.dataModels + */ + +public class SpotProperties { + + private String url; + private String state; + private String lot; + + public SpotProperties() { + } + + @Override + public String toString() { + return "SpotProperties{" + + "url='" + url + '\'' + + ", state='" + state + '\'' + + ", lot='" + lot + '\'' + + '}'; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public String getLot() { + return lot; + } + + public void setLot(String lot) { + this.lot = lot; + } + + public int getIdFromUrl() { + String[] parts = this.url.split("/"); + return Integer.parseInt(parts[parts.length - 1]); + } + + public int getLotId() { + String[] parts = this.lot.split("/"); + return Integer.parseInt(parts[parts.length - 1]); + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/dataModels/UserToken.java b/app/src/main/java/smarttraffic/smartparking/dataModels/UserToken.java new file mode 100644 index 0000000..a8893fd --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/dataModels/UserToken.java @@ -0,0 +1,45 @@ +package smarttraffic.smartparking.dataModels; + +/** + * Created by Joaquin on 09/2019. + *

+ * smarttraffic.smartparking.dataModels + */ + +public class UserToken { + + private String token; + private String url; + + public UserToken() { + } + + @Override + public String toString() { + return "UserToken{" + + "token='" + token + '\'' + + ", url='" + url + '\'' + + '}'; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public int getIdFromUrl() { + String[] parts = this.url.split("/"); + return Integer.parseInt(parts[parts.length - 1]); + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/receivers/GeofenceBroadcastReceiver.java b/app/src/main/java/smarttraffic/smartparking/receivers/GeofenceBroadcastReceiver.java new file mode 100644 index 0000000..f1e7909 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/receivers/GeofenceBroadcastReceiver.java @@ -0,0 +1,15 @@ +package smarttraffic.smartparking.receivers; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import smarttraffic.smartparking.services.GeofenceTransitionsJobIntentService; + +public class GeofenceBroadcastReceiver extends BroadcastReceiver { + @Override + public void onReceive(Context context, Intent intent) { + // Enqueues a JobIntentService passing the context and intent as parameters + GeofenceTransitionsJobIntentService.enqueueWork(context, intent); + } + } diff --git a/app/src/main/java/smarttraffic/smartparking/receivers/LoginReceiver.java b/app/src/main/java/smarttraffic/smartparking/receivers/LoginReceiver.java new file mode 100644 index 0000000..5a06507 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/receivers/LoginReceiver.java @@ -0,0 +1,94 @@ +package smarttraffic.smartparking.receivers; + +import android.annotation.SuppressLint; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.view.Gravity; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import butterknife.BindView; +import smarttraffic.smartparking.R; +import smarttraffic.smartparking.activities.HomeActivity; +import smarttraffic.smartparking.services.LoginService; + +/** + * Created by Joaquin Olivera on july 19. + * + * @author joaquin + */ + +public class LoginReceiver extends BroadcastReceiver { + + private static final String LOG_TAG = "LoginReceiver"; + + private String sex; + private Integer age; + private Integer identifier; + + @Override + public void onReceive(Context context, Intent intent) { + if(intent.getAction().equals(LoginService.LOGIN_ACTION)) { + Intent i = new Intent(context, HomeActivity.class); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(i); + } + else if(intent.getAction().equals(LoginService.BAD_LOGIN_ACTION)) { + setErrorMessage(intent.getStringExtra(LoginService.PROBLEM)); + showToast(getErrorMessage(),context); + } + else if(intent.getAction().equals(LoginService.SERVER_PROBLEM)) { + setErrorMessage(intent.getStringExtra(LoginService.PROBLEM)); + showToast(getErrorMessage(),context); + } + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + private String errorMessage; + + public String getSexResponse() { + return sex; + } + + public void setSexResponse(String sexResponse) { + this.sex = sexResponse; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + public Integer getIdentifier() { + return identifier; + } + + public void setIdentifier(Integer identifier) { + this.identifier = identifier; + } + + // Show images in Toast prompt. + @SuppressLint("ResourceAsColor") + private void showToast(String message, Context context) { + Toast toast = Toast.makeText(context, message, Toast.LENGTH_LONG); + toast.setGravity(Gravity.CENTER, 0, 0); + LinearLayout toastContentView = (LinearLayout) toast.getView(); + ImageView imageView = new ImageView(context); + imageView.setImageResource(R.mipmap.smartparking_logo_round); + toastContentView.addView(imageView, 0); + toast.show(); + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/receivers/RegistrationReceiver.java b/app/src/main/java/smarttraffic/smartparking/receivers/RegistrationReceiver.java new file mode 100644 index 0000000..f629176 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/receivers/RegistrationReceiver.java @@ -0,0 +1,60 @@ +package smarttraffic.smartparking.receivers; + +import android.annotation.SuppressLint; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.view.Gravity; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.Toast; + +import smarttraffic.smartparking.R; +import smarttraffic.smartparking.activities.LoginActivity; +import smarttraffic.smartparking.services.RegistrationService; + +/** + * Created by Joaquin Olivera on july 19. + * + * @author joaquin + */ + +public class RegistrationReceiver extends BroadcastReceiver { + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + private String errorMessage; + private static final String LOG_TAG = "RegistrationReceiver"; + + @Override + public void onReceive(Context context, Intent intent) { + + if(intent.getAction().equals(RegistrationService.REGISTRATION_OK)) { + showToast(RegistrationService.REGISTRATION_OK, context); + Intent i = new Intent(context, LoginActivity.class); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(i); + } + else if(intent.getAction().equals(RegistrationService.BAD_REGISTRATION)) { + setErrorMessage(intent.getStringExtra(RegistrationService.PROBLEM)); + showToast(getErrorMessage(),context); + } + } + // Show images in Toast prompt. + @SuppressLint("ResourceAsColor") + private void showToast(String message, Context context) { + Toast toast = Toast.makeText(context, message, Toast.LENGTH_LONG); + toast.setGravity(Gravity.CENTER, 0, 0); + LinearLayout toastContentView = (LinearLayout) toast.getView(); + ImageView imageView = new ImageView(context); + imageView.setImageResource(R.mipmap.smartparking_logo_round); + toastContentView.addView(imageView, 0); + toast.show(); + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/services/DetectedActivitiesService.java b/app/src/main/java/smarttraffic/smartparking/services/DetectedActivitiesService.java new file mode 100644 index 0000000..c5276f2 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/services/DetectedActivitiesService.java @@ -0,0 +1,61 @@ +package smarttraffic.smartparking.services; + +import android.app.IntentService; +import android.content.Intent; +import android.preference.PreferenceManager; +import android.support.v4.content.LocalBroadcastManager; +import android.util.Log; +import android.widget.Toast; + +import com.google.android.gms.location.ActivityRecognitionResult; +import com.google.android.gms.location.DetectedActivity; + +import java.util.ArrayList; + +import smarttraffic.smartparking.Constants; +import smarttraffic.smartparking.Utils; +import smarttraffic.smartparking.activities.HomeActivity; + +public class DetectedActivitiesService extends IntentService { + + private static final String LOG_TAG = "DetectedActivities"; + + public DetectedActivitiesService() { + super("DetectedActivitiesService"); + } + + @Override + public void onCreate() { + super.onCreate(); + } + + @Override + protected void onHandleIntent(Intent intent) { + ActivityRecognitionResult result = ActivityRecognitionResult.extractResult(intent); + + // Get the list of the probable activities associated with the current state of the + // device. Each activity is associated with a confidence level, which is an int between + // 0 and 100. + + ArrayList detectedActivities = (ArrayList) result.getProbableActivities(); + + PreferenceManager.getDefaultSharedPreferences(this) + .edit() + .putString(Constants.KEY_DETECTED_ACTIVITIES, + Utils.detectedActivitiesToJson(detectedActivities)) + .apply(); + + // Log each activity. + Log.i(LOG_TAG, Utils.getActivityString( + getApplicationContext(), + result.getMostProbableActivity().getType()) + " " + result.getMostProbableActivity().getConfidence() + "%"); + broadcastActivityTransition(result); + } + + private void broadcastActivityTransition(ActivityRecognitionResult result) { + Intent intent = new Intent(Constants.BROADCAST_TRANSITION_ACTIVITY_INTENT); + intent.putExtra(Constants.ACTIVITY_TYPE_TRANSITION, result.getMostProbableActivity().getType()); + intent.putExtra(Constants.ACTIVITY_CONFIDENCE_TRANSITION, result.getMostProbableActivity().getConfidence()); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/services/GeofenceTransitionsJobIntentService.java b/app/src/main/java/smarttraffic/smartparking/services/GeofenceTransitionsJobIntentService.java new file mode 100644 index 0000000..bf467f7 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/services/GeofenceTransitionsJobIntentService.java @@ -0,0 +1,217 @@ +package smarttraffic.smartparking.services; + +import android.annotation.SuppressLint; +import android.app.ActivityManager; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.TaskStackBuilder; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.location.Location; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.support.v4.app.JobIntentService; +import android.support.v4.app.NotificationCompat; +import android.support.v4.content.LocalBroadcastManager; +import android.support.v7.app.AlertDialog; +import android.text.TextUtils; +import android.util.Log; + +import com.google.android.gms.location.ActivityRecognitionResult; +import com.google.android.gms.location.Geofence; +import com.google.android.gms.location.GeofencingEvent; + +import java.util.ArrayList; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +import smarttraffic.smartparking.Constants; +import smarttraffic.smartparking.GeofenceErrorMessages; +import smarttraffic.smartparking.R; +import smarttraffic.smartparking.activities.HomeActivity; + + +public class GeofenceTransitionsJobIntentService extends JobIntentService { + + private static final int JOB_ID = 573; + + private static final String LOG_TAG = "GeofenceJobService"; + + private static final String CHANNEL_ID = "channel_01"; + + public static final String TRANSITION = "TRANSITION"; + public static final String GEOFENCE_TRIGGED = "GEOFENCE_TRIGGED"; + private static final String HAS_TRANSITION = "HAS_TRANSITION"; + + + /** + * Convenience method for enqueuing work in to this service. + */ + public static void enqueueWork(Context context, Intent intent) { + enqueueWork(context, GeofenceTransitionsJobIntentService.class, JOB_ID, intent); + } + + /** + * Handles incoming intents. + * @param intent sent by Location Services. This Intent is provided to Location + * Services (inside a PendingIntent) when addGeofences() is called. + */ + @SuppressLint("StringFormatInvalid") + @Override + protected void onHandleWork(Intent intent) { + GeofencingEvent geofencingEvent = GeofencingEvent.fromIntent(intent); + if (geofencingEvent.hasError()) { + String errorMessage = GeofenceErrorMessages.getErrorString(this, + geofencingEvent.getErrorCode()); + Log.e(LOG_TAG, errorMessage); + return; + } + // Get the transition type. + int geofenceTransition = geofencingEvent.getGeofenceTransition(); + // Test that the reported transition was of interest. + if (geofenceTransition == Geofence.GEOFENCE_TRANSITION_ENTER || + geofenceTransition == Geofence.GEOFENCE_TRANSITION_EXIT || + geofenceTransition == Geofence.GEOFENCE_TRANSITION_DWELL) { + // Get the geofences that were triggered. A single event can trigger multiple geofences. + List triggeringGeofences = geofencingEvent.getTriggeringGeofences(); + // Get the transition details as a String. + String geofenceTransitionDetails = getGeofenceTransitionDetails(geofenceTransition, + triggeringGeofences); + // Send notification and log the transition details. + broadcastGeofenceTransition(triggeringGeofences, geofenceTransition); + sendNotification(geofenceTransitionDetails, triggeringGeofences, geofenceTransition); + Log.i(LOG_TAG, geofenceTransitionDetails); + } else { + // Log the error. + Log.e(LOG_TAG, getString(R.string.geofence_transition_invalid_type, geofenceTransition)); + } + } + + + /** + * Gets transition details and returns them as a formatted string. + * + * @param geofenceTransition The ID of the geofence transition. + * @param triggeringGeofences The geofence(s) triggered. + * @return The transition details formatted as String. + */ + private String getGeofenceTransitionDetails( + int geofenceTransition, + List triggeringGeofences) { + + String geofenceTransitionString = getTransitionString(geofenceTransition); + + // Get the Ids of each geofence that was triggered. + ArrayList triggeringGeofencesIdsList = new ArrayList<>(); + for (Geofence geofence : triggeringGeofences) { + triggeringGeofencesIdsList.add(geofence.getRequestId()); + } + String triggeringGeofencesIdsString = TextUtils.join(", ", triggeringGeofencesIdsList); + + return geofenceTransitionString + ": " + triggeringGeofencesIdsString; + } + + /** + * Posts a notification in the notification bar when a transition is detected. + * If the user clicks the notification, control goes to the MainActivity. + */ + private void sendNotification(String notificationDetails, List geofenceList, int transition) { + ArrayList fencesTriggersIdList = new ArrayList<>(); + // Get an instance of the Notification manager + NotificationManager mNotificationManager = + (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); + + createNotificationChannel(); + + // Create an explicit intent for an Activity in your app + Intent notificationIntent = new Intent(getApplicationContext(), HomeActivity.class); + for(Geofence geofence : geofenceList){ + fencesTriggersIdList.add(geofence.getRequestId()); + } + notificationIntent.putExtra(HAS_TRANSITION, true); + notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); + + NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID) + .setSmallIcon(R.drawable.notifications_smart_parking) + .setLargeIcon(BitmapFactory.decodeResource(getResources(), + R.drawable.notify_smart_parking)) + .setTimeoutAfter(Constants.getMinutesInMilliseconds() * 5) + .setColor(Color.GREEN) + .setContentTitle(notificationDetails) + .setContentText(getString(R.string.geofence_transition_notification_text)) + .setPriority(NotificationCompat.PRIORITY_HIGH) + .setAutoCancel(true); + + if(transition == Geofence.GEOFENCE_TRANSITION_ENTER){ + PendingIntent pendingIntent = PendingIntent.getActivity(this, + 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); + builder.addAction(R.drawable.notifications_smart_parking, "Ir a la aplicación", + pendingIntent); + } + // Set the Channel ID for Android O. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + builder.setChannelId(CHANNEL_ID); // Channel ID + } + + // Issue the notification + mNotificationManager.notify(0, builder.build()); + } + + /** + * Maps geofence transition types to their human-readable equivalents. + * + * @param transitionType A transition type constant defined in Geofence + * @return A String indicating the type of transition + */ + private String getTransitionString(int transitionType) { + switch (transitionType) { + case Geofence.GEOFENCE_TRANSITION_ENTER: + return getString(R.string.geofence_transition_entered); + case Geofence.GEOFENCE_TRANSITION_EXIT: + return getString(R.string.geofence_transition_exited); + case Geofence.GEOFENCE_TRANSITION_DWELL: + return getString(R.string.geofence_transition_dwell); + default: + return getString(R.string.unknown_geofence_transition); + } + } + + private void createNotificationChannel() { + // Create the NotificationChannel, but only on API 26+ because + // the NotificationChannel class is new and not in the support library + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + CharSequence name = getString(R.string.channel_name); + String description = getString(R.string.channel_description); + int importance = NotificationManager.IMPORTANCE_HIGH; + NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance); + channel.setDescription(description); + // Register the channel with the system; you can't change the importance + // or other notification behaviors after this + NotificationManager notificationManager = getSystemService(NotificationManager.class); + notificationManager.createNotificationChannel(channel); + } + } + + + private void broadcastGeofenceTransition(List triggeringGeofences, + int geofenceTransition) { + ArrayList fencesTriggered = new ArrayList<>(); + if(triggeringGeofences != null){ + for(Geofence geofence : triggeringGeofences){ + fencesTriggered.add(geofence.getRequestId()); + } + } + Intent intent = new Intent(Constants.getBroadcastGeofenceTriggerIntent()); + intent.putStringArrayListExtra(GEOFENCE_TRIGGED, fencesTriggered); + intent.putExtra(TRANSITION, geofenceTransition); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + +} diff --git a/app/src/main/java/smarttraffic/smartparking/services/LoginService.java b/app/src/main/java/smarttraffic/smartparking/services/LoginService.java new file mode 100644 index 0000000..37365e7 --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/services/LoginService.java @@ -0,0 +1,118 @@ +package smarttraffic.smartparking.services; + +import android.app.IntentService; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import okhttp3.OkHttpClient; + +import okhttp3.ResponseBody; +import retrofit2.Call; +import retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; +import smarttraffic.smartparking.Constants; +import smarttraffic.smartparking.SmartParkingAPI; +import smarttraffic.smartparking.dataModels.Credentials; +import smarttraffic.smartparking.dataModels.UserToken; +import smarttraffic.smartparking.receivers.LoginReceiver; +import smarttraffic.smartparking.Interceptors.AddSmartParkingTokenInterceptor; + +/** + * Created by Joaquin Olivera on july 19. + * + * @author joaquin + */ + +public class LoginService extends IntentService { + + public static final String PROBLEM = "Ha fallado el proceso de ingreso!"; + public static final String CANNOT_LOGIN = "No se logro hacer inicio. Revisar credenciales!"; + public static final String CANNOT_CONNECT_SERVER = "No se pudo conectar con el servidor, favor revisar conexion!"; + public static final String ULI = "User Login Information"; + public static final String IULI = "IDENTIFICADOR USUARIO LOGGED IN"; + + /** + * Creates an IntentService. Invoked by your subclass's constructor. + * + */ + + public LoginService() { + super("LoginService"); + } + + public static final String LOGIN_ACTION = "Login exitoso!"; + public static final String BAD_LOGIN_ACTION = "Credenciales incorrectas"; + public static final String SERVER_PROBLEM = "Existe un error con la comunicacion con el servidor!"; + + @Override + protected void onHandleIntent(Intent intent) { + Credentials userCredentials = new Credentials(); + userCredentials.setUsername(intent.getStringExtra("username")); + userCredentials.setPassword(intent.getStringExtra("password")); + Gson gson = new GsonBuilder() + .setLenient() + .create(); + + final OkHttpClient okHttpClient = new OkHttpClient.Builder() + .connectTimeout(5, TimeUnit.SECONDS) + .writeTimeout(20, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .addInterceptor(new AddSmartParkingTokenInterceptor()) + .build(); + + SharedPreferences sharedPreferences = getApplicationContext().getSharedPreferences( + Constants.CLIENTE_DATA, Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPreferences.edit(); + + Retrofit retrofit = new Retrofit.Builder() + .client(okHttpClient) + .baseUrl(Constants.BASE_URL) + .addConverterFactory(GsonConverterFactory.create(gson)) + .build(); + + SmartParkingAPI smartParkingAPI = retrofit.create(SmartParkingAPI.class); + Call call = smartParkingAPI.getUserToken(userCredentials); + Intent loginIntent = new Intent("loginIntent"); + loginIntent.setClass(this, LoginReceiver.class); + + try{ + Response result = call.execute(); + if (result.code() == 200){ + loginIntent.setAction(LOGIN_ACTION); + editor.putString(Constants.USER_TOKEN, result.body().getToken()).apply(); + editor.putString(Constants.USER_PASSWORD, + intent.getStringExtra("password")).apply(); + editor.putInt(Constants.USER_ID, result.body().getIdFromUrl()).apply(); + editor.putString(Constants.USER_URL, result.body().getUrl()).apply(); + editor.commit(); + }else if (result.code() == 400){ + ResponseBody error = result.errorBody(); + loginIntent.putExtra(PROBLEM, "No se puede iniciar sesión " + + "con las credenciales proporcionadas"); + loginIntent.setAction(BAD_LOGIN_ACTION); + } + else { + loginIntent.putExtra(PROBLEM, result.errorBody().string()); + loginIntent.setAction(SERVER_PROBLEM); + } + } catch (IOException e) { + loginIntent.putExtra(PROBLEM, CANNOT_CONNECT_SERVER); + loginIntent.setAction(BAD_LOGIN_ACTION); + e.printStackTrace(); + } + sendBroadcast(loginIntent); + } + + private int getIdFromUrl(String url) { + String[] parts = url.split("/"); + return Integer.parseInt(parts[parts.length - 1]); + } +} diff --git a/app/src/main/java/smarttraffic/smartparking/services/RegistrationService.java b/app/src/main/java/smarttraffic/smartparking/services/RegistrationService.java new file mode 100644 index 0000000..d669d6c --- /dev/null +++ b/app/src/main/java/smarttraffic/smartparking/services/RegistrationService.java @@ -0,0 +1,99 @@ +package smarttraffic.smartparking.services; + +import android.app.IntentService; +import android.content.Intent; +import android.os.Bundle; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import okhttp3.Headers; +import okhttp3.OkHttpClient; +import retrofit2.Call; +import retrofit2.Response; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; +import smarttraffic.smartparking.Constants; +import smarttraffic.smartparking.SmartParkingAPI; +import smarttraffic.smartparking.dataModels.ProfileRegistry; +import smarttraffic.smartparking.dataModels.ProfileUser; +import smarttraffic.smartparking.dataModels.SmartParkingProfile; +import smarttraffic.smartparking.receivers.RegistrationReceiver; +import smarttraffic.smartparking.Interceptors.AddSmartParkingTokenInterceptor; + +/** + * Created by Joaquin Olivera on july 19. + * + * @author joaquin + */ + +public class RegistrationService extends IntentService { + + public static final String PROBLEM = "Found some Problem in Login"; + private static final String CANNOT_CONNECT_SERVER = "No se pudo conectar con el servidor," + + " favor revisar conexion!"; + + public static final String REGISTRATION_OK = "Registro correcto"; + public static final String BAD_REGISTRATION = "Registro no realizado"; + + public RegistrationService() { + super("RegistrationService"); + } + + @Override + protected void onHandleIntent(Intent intent) { + ProfileRegistry profileRegistry = new ProfileRegistry(); + profileRegistry.setSmartParkingProfile(new SmartParkingProfile()); + Bundle extras = intent.getExtras(); + setRegistrationExtras(extras, profileRegistry); + + Gson gson = new GsonBuilder() + .setLenient() + .create(); + + final OkHttpClient okHttpClient = new OkHttpClient.Builder() + .connectTimeout(5, TimeUnit.SECONDS) + .writeTimeout(20, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + //add the token header "Authorization" + .addInterceptor(new AddSmartParkingTokenInterceptor()) + .build(); + + Retrofit retrofit = new Retrofit.Builder() + .client(okHttpClient) + .baseUrl(Constants.BASE_URL) + .addConverterFactory(GsonConverterFactory.create(gson)) + .build(); + + SmartParkingAPI smartParkingAPI = retrofit.create(SmartParkingAPI.class); + Call call = smartParkingAPI.signUpUser(profileRegistry); + Intent registrationIntent = new Intent("registrationIntent"); + registrationIntent.setClass(this, RegistrationReceiver.class); + + try { + Response result = call.execute(); + Headers headers = result.headers(); + if(result.code() == 201){ + registrationIntent.setAction(REGISTRATION_OK); + }else{ + registrationIntent.putExtra("exists", "Profile already exists"); + registrationIntent.setAction(BAD_REGISTRATION); + } + } catch (IOException e) { + registrationIntent.putExtra(PROBLEM, CANNOT_CONNECT_SERVER); + registrationIntent.setAction(BAD_REGISTRATION); + e.printStackTrace(); + } + sendBroadcast(registrationIntent); + } + + private void setRegistrationExtras(Bundle extras, ProfileRegistry profileRegistry){ + profileRegistry.setUsername(extras.getString("username")); + profileRegistry.setPassword(extras.getString("password")); + profileRegistry.getSmartParkingProfile().setBirth_date(extras.getString("birth_date")); + profileRegistry.getSmartParkingProfile().setSex(extras.getString("sex")); + } +} diff --git a/app/src/main/res/drawable-anydpi-v24/notifications_smart_parking.xml b/app/src/main/res/drawable-anydpi-v24/notifications_smart_parking.xml new file mode 100644 index 0000000..8394d3f --- /dev/null +++ b/app/src/main/res/drawable-anydpi-v24/notifications_smart_parking.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/app/src/main/res/drawable-anydpi-v24/notify_smart_parking.xml b/app/src/main/res/drawable-anydpi-v24/notify_smart_parking.xml new file mode 100644 index 0000000..fb3b315 --- /dev/null +++ b/app/src/main/res/drawable-anydpi-v24/notify_smart_parking.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/app/src/main/res/drawable-anydpi/about.xml b/app/src/main/res/drawable-anydpi/about.xml new file mode 100644 index 0000000..3b40a01 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/about.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/app/src/main/res/drawable-anydpi/to_location.xml b/app/src/main/res/drawable-anydpi/to_location.xml new file mode 100644 index 0000000..a6fee61 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/to_location.xml @@ -0,0 +1,13 @@ + + + + + diff --git a/app/src/main/res/drawable-hdpi/about.png b/app/src/main/res/drawable-hdpi/about.png new file mode 100644 index 0000000..83d4646 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/about.png differ diff --git a/app/src/main/res/drawable-hdpi/about_menu.png b/app/src/main/res/drawable-hdpi/about_menu.png new file mode 100644 index 0000000..98fbc39 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/about_menu.png differ diff --git a/app/src/main/res/drawable-hdpi/changepass_menu.png b/app/src/main/res/drawable-hdpi/changepass_menu.png new file mode 100644 index 0000000..dba681e Binary files /dev/null and b/app/src/main/res/drawable-hdpi/changepass_menu.png differ diff --git a/app/src/main/res/drawable-hdpi/datepicker.png b/app/src/main/res/drawable-hdpi/datepicker.png new file mode 100644 index 0000000..13c29a4 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/datepicker.png differ diff --git a/app/src/main/res/drawable-hdpi/dontshowtext.png b/app/src/main/res/drawable-hdpi/dontshowtext.png new file mode 100644 index 0000000..00efbf5 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/dontshowtext.png differ diff --git a/app/src/main/res/drawable-hdpi/hamenuitem.png b/app/src/main/res/drawable-hdpi/hamenuitem.png new file mode 100644 index 0000000..72a5dcb Binary files /dev/null and b/app/src/main/res/drawable-hdpi/hamenuitem.png differ diff --git a/app/src/main/res/drawable-hdpi/homemenu.png b/app/src/main/res/drawable-hdpi/homemenu.png new file mode 100644 index 0000000..afb4496 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/homemenu.png differ diff --git a/app/src/main/res/drawable-hdpi/logout_menu.png b/app/src/main/res/drawable-hdpi/logout_menu.png new file mode 100644 index 0000000..d6ce68f Binary files /dev/null and b/app/src/main/res/drawable-hdpi/logout_menu.png differ diff --git a/app/src/main/res/drawable-hdpi/marker_icon.png b/app/src/main/res/drawable-hdpi/marker_icon.png new file mode 100644 index 0000000..505bcc9 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/marker_icon.png differ diff --git a/app/src/main/res/drawable-hdpi/notifications_smart_parking.png b/app/src/main/res/drawable-hdpi/notifications_smart_parking.png new file mode 100644 index 0000000..11e5a6f Binary files /dev/null and b/app/src/main/res/drawable-hdpi/notifications_smart_parking.png differ diff --git a/app/src/main/res/drawable-hdpi/notify_smart_parking.png b/app/src/main/res/drawable-hdpi/notify_smart_parking.png new file mode 100644 index 0000000..3947a49 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/notify_smart_parking.png differ diff --git a/app/src/main/res/drawable-hdpi/settings_menu.png b/app/src/main/res/drawable-hdpi/settings_menu.png new file mode 100644 index 0000000..f24bb80 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/settings_menu.png differ diff --git a/app/src/main/res/drawable-hdpi/showtext.png b/app/src/main/res/drawable-hdpi/showtext.png new file mode 100644 index 0000000..6e8d3bc Binary files /dev/null and b/app/src/main/res/drawable-hdpi/showtext.png differ diff --git a/app/src/main/res/drawable-hdpi/to_location.png b/app/src/main/res/drawable-hdpi/to_location.png new file mode 100644 index 0000000..08806c3 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/to_location.png differ diff --git a/app/src/main/res/drawable-mdpi/about.png b/app/src/main/res/drawable-mdpi/about.png new file mode 100644 index 0000000..079c1d1 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/about.png differ diff --git a/app/src/main/res/drawable-mdpi/about_menu.png b/app/src/main/res/drawable-mdpi/about_menu.png new file mode 100644 index 0000000..a334e20 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/about_menu.png differ diff --git a/app/src/main/res/drawable-mdpi/changepass_menu.png b/app/src/main/res/drawable-mdpi/changepass_menu.png new file mode 100644 index 0000000..8162d39 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/changepass_menu.png differ diff --git a/app/src/main/res/drawable-mdpi/datepicker.png b/app/src/main/res/drawable-mdpi/datepicker.png new file mode 100644 index 0000000..acf7972 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/datepicker.png differ diff --git a/app/src/main/res/drawable-mdpi/dontshowtext.png b/app/src/main/res/drawable-mdpi/dontshowtext.png new file mode 100644 index 0000000..5ae4947 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/dontshowtext.png differ diff --git a/app/src/main/res/drawable-mdpi/hamenuitem.png b/app/src/main/res/drawable-mdpi/hamenuitem.png new file mode 100644 index 0000000..201dfd4 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/hamenuitem.png differ diff --git a/app/src/main/res/drawable-mdpi/homemenu.png b/app/src/main/res/drawable-mdpi/homemenu.png new file mode 100644 index 0000000..4990752 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/homemenu.png differ diff --git a/app/src/main/res/drawable-mdpi/logout_menu.png b/app/src/main/res/drawable-mdpi/logout_menu.png new file mode 100644 index 0000000..75ed534 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/logout_menu.png differ diff --git a/app/src/main/res/drawable-mdpi/marker_icon.png b/app/src/main/res/drawable-mdpi/marker_icon.png new file mode 100644 index 0000000..ce65ee4 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/marker_icon.png differ diff --git a/app/src/main/res/drawable-mdpi/notifications_smart_parking.png b/app/src/main/res/drawable-mdpi/notifications_smart_parking.png new file mode 100644 index 0000000..17a747a Binary files /dev/null and b/app/src/main/res/drawable-mdpi/notifications_smart_parking.png differ diff --git a/app/src/main/res/drawable-mdpi/notify_smart_parking.png b/app/src/main/res/drawable-mdpi/notify_smart_parking.png new file mode 100644 index 0000000..f2a2626 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/notify_smart_parking.png differ diff --git a/app/src/main/res/drawable-mdpi/settings_menu.png b/app/src/main/res/drawable-mdpi/settings_menu.png new file mode 100644 index 0000000..67e38f7 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/settings_menu.png differ diff --git a/app/src/main/res/drawable-mdpi/showtext.png b/app/src/main/res/drawable-mdpi/showtext.png new file mode 100644 index 0000000..80dcdf6 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/showtext.png differ diff --git a/app/src/main/res/drawable-mdpi/to_location.png b/app/src/main/res/drawable-mdpi/to_location.png new file mode 100644 index 0000000..be741d6 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/to_location.png differ diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..1f6bb29 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable-xhdpi/about.png b/app/src/main/res/drawable-xhdpi/about.png new file mode 100644 index 0000000..1833880 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/about.png differ diff --git a/app/src/main/res/drawable-xhdpi/about_menu.png b/app/src/main/res/drawable-xhdpi/about_menu.png new file mode 100644 index 0000000..36003f2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/about_menu.png differ diff --git a/app/src/main/res/drawable-xhdpi/changepass_menu.png b/app/src/main/res/drawable-xhdpi/changepass_menu.png new file mode 100644 index 0000000..358aafb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/changepass_menu.png differ diff --git a/app/src/main/res/drawable-xhdpi/datepicker.png b/app/src/main/res/drawable-xhdpi/datepicker.png new file mode 100644 index 0000000..7db54b7 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/datepicker.png differ diff --git a/app/src/main/res/drawable-xhdpi/dontshowtext.png b/app/src/main/res/drawable-xhdpi/dontshowtext.png new file mode 100644 index 0000000..d1c4fcb Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/dontshowtext.png differ diff --git a/app/src/main/res/drawable-xhdpi/hamenuitem.png b/app/src/main/res/drawable-xhdpi/hamenuitem.png new file mode 100644 index 0000000..5921bde Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/hamenuitem.png differ diff --git a/app/src/main/res/drawable-xhdpi/homemenu.png b/app/src/main/res/drawable-xhdpi/homemenu.png new file mode 100644 index 0000000..77ac564 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/homemenu.png differ diff --git a/app/src/main/res/drawable-xhdpi/logout_menu.png b/app/src/main/res/drawable-xhdpi/logout_menu.png new file mode 100644 index 0000000..f11c8b0 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/logout_menu.png differ diff --git a/app/src/main/res/drawable-xhdpi/marker_icon.png b/app/src/main/res/drawable-xhdpi/marker_icon.png new file mode 100644 index 0000000..2423931 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/marker_icon.png differ diff --git a/app/src/main/res/drawable-xhdpi/notifications_smart_parking.png b/app/src/main/res/drawable-xhdpi/notifications_smart_parking.png new file mode 100644 index 0000000..8c3d0e1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/notifications_smart_parking.png differ diff --git a/app/src/main/res/drawable-xhdpi/notify_smart_parking.png b/app/src/main/res/drawable-xhdpi/notify_smart_parking.png new file mode 100644 index 0000000..4d5a45b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/notify_smart_parking.png differ diff --git a/app/src/main/res/drawable-xhdpi/settings_menu.png b/app/src/main/res/drawable-xhdpi/settings_menu.png new file mode 100644 index 0000000..56de03c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/settings_menu.png differ diff --git a/app/src/main/res/drawable-xhdpi/showtext.png b/app/src/main/res/drawable-xhdpi/showtext.png new file mode 100644 index 0000000..6e93d1d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/showtext.png differ diff --git a/app/src/main/res/drawable-xhdpi/to_location.png b/app/src/main/res/drawable-xhdpi/to_location.png new file mode 100644 index 0000000..b0d51f3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/to_location.png differ diff --git a/app/src/main/res/drawable-xxhdpi/about.png b/app/src/main/res/drawable-xxhdpi/about.png new file mode 100644 index 0000000..c48b5ce Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/about.png differ diff --git a/app/src/main/res/drawable-xxhdpi/about_menu.png b/app/src/main/res/drawable-xxhdpi/about_menu.png new file mode 100644 index 0000000..dd885f2 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/about_menu.png differ diff --git a/app/src/main/res/drawable-xxhdpi/changepass_menu.png b/app/src/main/res/drawable-xxhdpi/changepass_menu.png new file mode 100644 index 0000000..4a41ad1 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/changepass_menu.png differ diff --git a/app/src/main/res/drawable-xxhdpi/datepicker.png b/app/src/main/res/drawable-xxhdpi/datepicker.png new file mode 100644 index 0000000..f11282a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/datepicker.png differ diff --git a/app/src/main/res/drawable-xxhdpi/dontshowtext.png b/app/src/main/res/drawable-xxhdpi/dontshowtext.png new file mode 100644 index 0000000..c9889c4 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/dontshowtext.png differ diff --git a/app/src/main/res/drawable-xxhdpi/hamenuitem.png b/app/src/main/res/drawable-xxhdpi/hamenuitem.png new file mode 100644 index 0000000..7b872cd Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/hamenuitem.png differ diff --git a/app/src/main/res/drawable-xxhdpi/homemenu.png b/app/src/main/res/drawable-xxhdpi/homemenu.png new file mode 100644 index 0000000..7196157 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/homemenu.png differ diff --git a/app/src/main/res/drawable-xxhdpi/logout_menu.png b/app/src/main/res/drawable-xxhdpi/logout_menu.png new file mode 100644 index 0000000..aca1f16 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/logout_menu.png differ diff --git a/app/src/main/res/drawable-xxhdpi/marker_icon.png b/app/src/main/res/drawable-xxhdpi/marker_icon.png new file mode 100644 index 0000000..4f307d5 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/marker_icon.png differ diff --git a/app/src/main/res/drawable-xxhdpi/notifications_smart_parking.png b/app/src/main/res/drawable-xxhdpi/notifications_smart_parking.png new file mode 100644 index 0000000..820ab51 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/notifications_smart_parking.png differ diff --git a/app/src/main/res/drawable-xxhdpi/notify_smart_parking.png b/app/src/main/res/drawable-xxhdpi/notify_smart_parking.png new file mode 100644 index 0000000..ae910d1 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/notify_smart_parking.png differ diff --git a/app/src/main/res/drawable-xxhdpi/settings_menu.png b/app/src/main/res/drawable-xxhdpi/settings_menu.png new file mode 100644 index 0000000..54528af Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/settings_menu.png differ diff --git a/app/src/main/res/drawable-xxhdpi/showtext.png b/app/src/main/res/drawable-xxhdpi/showtext.png new file mode 100644 index 0000000..50caf0a Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/showtext.png differ diff --git a/app/src/main/res/drawable-xxhdpi/to_location.png b/app/src/main/res/drawable-xxhdpi/to_location.png new file mode 100644 index 0000000..eb1187c Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/to_location.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/about_menu.png b/app/src/main/res/drawable-xxxhdpi/about_menu.png new file mode 100644 index 0000000..abf528f Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/about_menu.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/changepass_menu.png b/app/src/main/res/drawable-xxxhdpi/changepass_menu.png new file mode 100644 index 0000000..6b70127 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/changepass_menu.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/datepicker.png b/app/src/main/res/drawable-xxxhdpi/datepicker.png new file mode 100644 index 0000000..82d0556 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/datepicker.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/dontshowtext.png b/app/src/main/res/drawable-xxxhdpi/dontshowtext.png new file mode 100644 index 0000000..0bf4ca2 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/dontshowtext.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/hamenuitem.png b/app/src/main/res/drawable-xxxhdpi/hamenuitem.png new file mode 100644 index 0000000..00f217b Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/hamenuitem.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/homemenu.png b/app/src/main/res/drawable-xxxhdpi/homemenu.png new file mode 100644 index 0000000..335ee6b Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/homemenu.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/logout_menu.png b/app/src/main/res/drawable-xxxhdpi/logout_menu.png new file mode 100644 index 0000000..a1efc55 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/logout_menu.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/marker_icon.png b/app/src/main/res/drawable-xxxhdpi/marker_icon.png new file mode 100644 index 0000000..6dc8dad Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/marker_icon.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/notifications_smart_parking.png b/app/src/main/res/drawable-xxxhdpi/notifications_smart_parking.png new file mode 100644 index 0000000..ed3affb Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/notifications_smart_parking.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/settings_menu.png b/app/src/main/res/drawable-xxxhdpi/settings_menu.png new file mode 100644 index 0000000..e1115a6 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/settings_menu.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/showtext.png b/app/src/main/res/drawable-xxxhdpi/showtext.png new file mode 100644 index 0000000..9363a5f Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/showtext.png differ diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..0d025f9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/roundbutton.xml b/app/src/main/res/drawable/roundbutton.xml new file mode 100644 index 0000000..fa17730 --- /dev/null +++ b/app/src/main/res/drawable/roundbutton.xml @@ -0,0 +1,9 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/about_layout.xml b/app/src/main/res/layout/about_layout.xml new file mode 100644 index 0000000..4c91fa4 --- /dev/null +++ b/app/src/main/res/layout/about_layout.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/change_password_layout.xml b/app/src/main/res/layout/change_password_layout.xml new file mode 100644 index 0000000..a78ffe7 --- /dev/null +++ b/app/src/main/res/layout/change_password_layout.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + +