diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a265233 --- /dev/null +++ b/.gitignore @@ -0,0 +1,20 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +/.idea/caches/build_file_checksums.ser +.idea/ +logs +gen-external-apklibs +out + 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/build.gradle b/app/build.gradle new file mode 100644 index 0000000..6fc80b8 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,88 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 28 + buildToolsVersion "29.0.3" + + defaultConfig { + applicationId "com.ichangemycity.ichangemycommunity" + minSdkVersion 21 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility = 1.8 + targetCompatibility = 1.8 + } + +} + +dependencies { + + def camerax_version = "1.0.0-rc01" + + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'androidx.appcompat:appcompat:1.0.0' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'com.squareup.retrofit2:retrofit:2.2.0' + implementation 'com.squareup.retrofit2:converter-gson:2.2.0' + implementation 'com.squareup.okhttp3:okhttp:3.6.0' + implementation 'com.squareup.okhttp3:logging-interceptor:3.6.0' + implementation 'com.google.code.gson:gson:2.4' + implementation 'com.squareup.picasso:picasso:2.71828' + implementation 'com.jakewharton:butterknife:8.5.1' + implementation 'de.hdodenhof:circleimageview:3.0.0' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'com.google.android.material:material:1.0.0' + implementation 'androidx.recyclerview:recyclerview:1.0.0' + implementation 'com.google.android.material:material:1.0.0' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test.ext:junit:1.1.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + + // Google Services + implementation 'com.google.android.gms:play-services-maps:17.0.0' + + // Google Location + implementation 'com.google.android.gms:play-services-location:17.0.0' + + // Google map utils for clustering + implementation 'com.google.maps.android:android-maps-utils:1.3.3' + + // Google Directions + implementation 'com.google.maps:google-maps-services:0.14.0' + + // Google Places + implementation 'com.google.android.libraries.places:places:2.2.0' + + // Cluster Markers + implementation 'com.google.maps.android:android-maps-utils:2.1.0' + + // CameraX core library using camera2 implementation + implementation "androidx.camera:camera-camera2:$camerax_version" + + // CameraX Lifecycle Library + implementation "androidx.camera:camera-lifecycle:$camerax_version" + + // CameraX View class + implementation "androidx.camera:camera-view:1.0.0-alpha20" + implementation "androidx.camera:camera-core:${camerax_version}" + + implementation "com.android.support:support-v4:28.0.0" + implementation "com.android.support:support-v13:28.0.0" + implementation "com.android.support:cardview-v7:28.0.0" + implementation "com.android.support:appcompat-v7:28.0.0" + + + implementation 'com.android.support:recyclerview-v7:28.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/com/ichangemycity/ichangemycommunity/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/ichangemycity/ichangemycommunity/ExampleInstrumentedTest.java new file mode 100644 index 0000000..90f7a3e --- /dev/null +++ b/app/src/androidTest/java/com/ichangemycity/ichangemycommunity/ExampleInstrumentedTest.java @@ -0,0 +1,28 @@ +package com.ichangemycity.ichangemycommunity; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Assert; +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.getInstrumentation().getTargetContext(); + + Assert.assertEquals("com.ichangemycity.ichangemycommunity", appContext.getPackageName()); + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..e4c039f --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/AppConfig.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/AppConfig.java new file mode 100644 index 0000000..17988fb --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/AppConfig.java @@ -0,0 +1,63 @@ +package com.ichangemycity.ichangemycommunity; + +import android.os.Environment; + +import java.io.File; + +public class AppConfig { + private static final Host HOST_DEFAULT = Host.STAGING1; + private static final String DEFAULT_LOG_TAG = "IChangeMyCommunity"; + private static final String SHARED_PREF_NAME = "IChangeMyCommunityPref"; + private static final String BASE_FOLDER_NAME = "IChangeMyCommunity"; + public static final String DATABASE_NAME = "IChangeMyCommunityDB"; + + public enum Host{ + STAGING1("https://jsonplaceholder.typicode.com"), + STAGING("http://ankuran-hack.ap-south-1.elasticbeanstalk.com"), + PRODUCTION("http://ankuran-hack.ap-south-1.elasticbeanstalk.com"); + + private final String url; + + private Host(final String url) + { + this.url=url; + } + + @Override + public String toString() { + return url; + } + } + + + + public static String getHostDefault() { + return HOST_DEFAULT.toString(); + } + + public static boolean isDevelopment() { + if(getHostDefault().equals(Host.PRODUCTION.toString())) + return false; + return true; + } + + public static boolean isLogEnabled() { + return isDevelopment(); + } + + public static String getDefaultLogTag() { + return DEFAULT_LOG_TAG; + } + + public static String getSharedPrefName() { + return SHARED_PREF_NAME; + } + + public static String getBaseFolderPath(){ + return Environment.getExternalStorageDirectory() + File.separator + BASE_FOLDER_NAME + File.separator; + } + + public static String getDatabaseName() { + return DATABASE_NAME; + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/AppConstant.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/AppConstant.java new file mode 100644 index 0000000..d665a8a --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/AppConstant.java @@ -0,0 +1,58 @@ +package com.ichangemycity.ichangemycommunity; + +import android.os.Environment; + +import java.io.File; + +public class AppConstant { + + private static final Object MAIN_FOLDER = "IChangeMyCity" ; + public static final Object APP_NAME = "IChangeMyCommunity" ; + + public static final String BASE_FOLDER = Environment.getExternalStorageDirectory() + File.separator + MAIN_FOLDER + File.separator; + public static int SPLASH_SCREEN_TIME_OUT=2000; + public static final int SMS_PERMISSION_CODE = 1002; + public static final String ACTION_SMS_RECEIVED="android.provider.Telephony.SMS_RECEIVED"; + public static final String URL_TERMS_N_CONDITION_WEBVIEW="https://developer.android.com/guide/webapps/webview"; + + public static final String DEFAULT_PIN = "0000"; + + + //KEY FOR SHARED PREFERENCE + public static final String PREF_KEY_MOBILE = "UserMobile"; + public static final String PREF_KEY_USER_DETAILS = "UserDetails"; + public static final String PREF_KEY_DEVICE_ID = "UserDeviceId"; + + //Key for request object + public static final String REQUEST_KEY_MOBILE = "phoneNumber"; + public static final String REQUEST_KEY_OTP = "otp"; + + //Keys for network call + public static final int NETWORK_CALL_INITIATE_OTP = 1; + public static final int NETWORK_CALL_VALIDATE_OTP = 2; + + //Image request code + + public static final int PICK_IMAGE =10000 ; + public static final int PICK_LICENCE =10001 ; + public static final int PICK_INSURANCE =10002 ; + public static final int PICK_RC =10003 ; + + + public enum ImageType{ + PROFILE_PIC("PP"), + SURVEY_PIC("DL"), + ; + private final String type; + + private ImageType(final String type) + { + this.type=type; + } + + @Override + public String toString() { + return type; + } + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/AppMain.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/AppMain.java new file mode 100644 index 0000000..cdfe1d0 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/AppMain.java @@ -0,0 +1,43 @@ +package com.ichangemycity.ichangemycommunity; + +import android.app.Application; +import android.content.Context; +import android.content.SharedPreferences; + +import com.ichangemycity.ichangemycommunity.network.NetworkClient; +import com.ichangemycity.ichangemycommunity.network.NetworkClientBuilder; + +public class AppMain extends Application { + private static Context mContext; + private static NetworkClient sNetworkClient; + private static AppMain sApplicationInstance = null; + + public static AppMain getInstance() { + return sApplicationInstance; + } + + @Override + public void onCreate() { + super.onCreate(); + mContext = getApplicationContext(); + sApplicationInstance = this; + } + + + + public static SharedPreferences getSharedPreferences() { + return mContext.getSharedPreferences(AppConfig.getSharedPrefName(), MODE_PRIVATE); + } + + public static Context getAppMainContext() { + return mContext; + } + + public static NetworkClient getDefaultNetWorkClient() { + if (sNetworkClient == null) { + NetworkClientBuilder networkClientBuilder = new NetworkClientBuilder(mContext); + sNetworkClient = networkClientBuilder.getDefaultNetworkClient(); + } + return sNetworkClient; + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/MainActivity.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/MainActivity.java new file mode 100644 index 0000000..84b5cc2 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/MainActivity.java @@ -0,0 +1,14 @@ +package com.ichangemycity.ichangemycommunity; + +import android.os.Bundle; + +import androidx.appcompat.app.AppCompatActivity; + +public class MainActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/model/ClusterMarker.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/model/ClusterMarker.java new file mode 100644 index 0000000..5101471 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/model/ClusterMarker.java @@ -0,0 +1,73 @@ +package com.ichangemycity.ichangemycommunity.model; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.google.android.gms.maps.model.LatLng; +import com.google.maps.android.clustering.ClusterItem; + +public class ClusterMarker implements ClusterItem { + + private LatLng position; + private String title; + private String snippet; + private int image; + private Survey survey; + + public ClusterMarker() { + } + + public ClusterMarker(LatLng position, String title, String snippet, int image, Survey survey) { + this.position = position; + this.title = title; + this.snippet = snippet; + this.image = image; + this.survey = survey; + } + + @NonNull + @Override + public LatLng getPosition() { + return position; + } + + public void setPosition(LatLng position) { + this.position = position; + } + + @Nullable + @Override + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + @Nullable + @Override + public String getSnippet() { + return snippet; + } + + public void setSnippet(String snippet) { + this.snippet = snippet; + } + + public int getImage() { + return image; + } + + public void setImage(int image) { + this.image = image; + } + + public Survey getSurvey() { + return survey; + } + + public void setSurvey(Survey survey) { + this.survey = survey; + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/model/LuminosityRowItem.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/model/LuminosityRowItem.java new file mode 100644 index 0000000..436cda5 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/model/LuminosityRowItem.java @@ -0,0 +1,30 @@ +package com.ichangemycity.ichangemycommunity.model; + +import android.graphics.Bitmap; + +public class LuminosityRowItem { + + private Bitmap image; + private float lumens; + + public LuminosityRowItem(Bitmap image, float lumens) { + this.image = image; + this.lumens = lumens; + } + + public Bitmap getImage() { + return image; + } + + public float getLumens() { + return lumens; + } + + public void setImage(Bitmap image) { + this.image = image; + } + + public void setLumens(float lumens) { + this.lumens = lumens; + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/model/MapSurveyCollection.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/model/MapSurveyCollection.java new file mode 100644 index 0000000..0834629 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/model/MapSurveyCollection.java @@ -0,0 +1,36 @@ +package com.ichangemycity.ichangemycommunity.model; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class MapSurveyCollection { + + public Map> getCategoryMap() { + Map> map = new HashMap<>(); + map.put("Walkability", getSubcategories("Walkability")); + map.put("Visibility", getSubcategories("Visibility")); + map.put("Drivability", getSubcategories("Drivability")); + return map; + } + + private List getSubcategories(String key) { + List subCategories = new ArrayList<>(); + subCategories.add("Obstacles"); + switch (key) { + case "Walkability": + subCategories.add("Broken footpath"); + subCategories.add("Encroachment"); + break; + case "Visibility": + subCategories.add("Luminosity"); + break; + case "Drivability": + subCategories.add("Pot holes"); + subCategories.add("Speed breakers"); + break; + } + return subCategories; + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/model/PolylineData.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/model/PolylineData.java new file mode 100644 index 0000000..529531f --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/model/PolylineData.java @@ -0,0 +1,39 @@ +package com.ichangemycity.ichangemycommunity.model; + +import com.google.android.gms.maps.model.Polyline; +import com.google.maps.model.DirectionsLeg; + +public class PolylineData { + + private Polyline polyline; + private DirectionsLeg leg; + + public PolylineData(Polyline polyline, DirectionsLeg leg) { + this.polyline = polyline; + this.leg = leg; + } + + public Polyline getPolyline() { + return polyline; + } + + public void setPolyline(Polyline polyline) { + this.polyline = polyline; + } + + public DirectionsLeg getLeg() { + return leg; + } + + public void setLeg(DirectionsLeg leg) { + this.leg = leg; + } + + @Override + public String toString() { + return "PolylineData{" + + "polyline=" + polyline + + ", leg=" + leg + + '}'; + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/model/Survey.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/model/Survey.java new file mode 100644 index 0000000..5f70cdf --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/model/Survey.java @@ -0,0 +1,106 @@ +package com.ichangemycity.ichangemycommunity.model; + +import com.google.android.gms.maps.model.LatLng; +import com.ichangemycity.ichangemycommunity.utils.map.SurveyDropDownEnum; + +import java.io.Serializable; + +public class Survey implements Serializable { + + private String id; + private Integer image; + private String city; + private String location; + private LatLng position; + private SurveyDropDownEnum category; + private String subCategory; + private String qualityScore; + private String distance; + + public Survey() { + } + + public Survey(String id, Integer image, String city, String location, LatLng position, SurveyDropDownEnum category, String subCategory, String qualityScore, String distance) { + this.id = id; + this.image = image; + this.city = city; + this.location = location; + this.position = position; + this.category = category; + this.subCategory = subCategory; + this.qualityScore = qualityScore; + this.distance = distance; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public Integer getImage() { + return image; + } + + public void setImage(Integer image) { + this.image = image; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public LatLng getPosition() { + return position; + } + + public void setPosition(LatLng position) { + this.position = position; + } + + public SurveyDropDownEnum getCategory() { + return category; + } + + public void setCategory(SurveyDropDownEnum category) { + this.category = category; + } + + public String getSubCategory() { + return subCategory; + } + + public void setSubCategory(String subCategory) { + this.subCategory = subCategory; + } + + public String getQualityScore() { + return qualityScore; + } + + public void setQualityScore(String qualityScore) { + this.qualityScore = qualityScore; + } + + public String getDistance() { + return distance; + } + + public void setDistance(String distance) { + this.distance = distance; + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/model/User.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/model/User.java new file mode 100644 index 0000000..2e68049 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/model/User.java @@ -0,0 +1,115 @@ +package com.ichangemycity.ichangemycommunity.model; + +import java.io.Serializable; + +public class User implements Serializable { + + private String id; + private boolean isVerified; + private String name; + private String email; + private String phone; + private Integer image; + private double rating; + private String liveLocation; + private String timeStamp; + + public User(String id, boolean isVerified, String name, String email, String phone, Integer image, double rating, String liveLocation, String timeStamp) { + this.id = id; + this.isVerified = isVerified; + this.name = name; + this.email = email; + this.phone = phone; + this.image = image; + this.rating = rating; + this.liveLocation = liveLocation; + this.timeStamp = timeStamp; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public boolean isVerified() { + return isVerified; + } + + public void setVerified(boolean verified) { + isVerified = verified; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public Integer getImage() { + return image; + } + + public void setImage(Integer image) { + this.image = image; + } + + public double getRating() { + return rating; + } + + public void setRating(double rating) { + this.rating = rating; + } + + public String getTimeStamp() { + return timeStamp; + } + + public void setTimeStamp(String timeStamp) { + this.timeStamp = timeStamp; + } + + public String getLiveLocation() { + return liveLocation; + } + + public void setLiveLocation(String liveLocation) { + this.liveLocation = liveLocation; + } + + @Override + public String toString() { + return "User{" + + "id='" + id + '\'' + + ", isVerified=" + isVerified + + ", name='" + name + '\'' + + ", email='" + email + '\'' + + ", phone='" + phone + '\'' + + ", image=" + image + + ", rating=" + rating + + ", liveLocation='" + liveLocation + '\'' + + ", timeStamp='" + timeStamp + '\'' + + '}'; + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/network/NetworkClient.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/network/NetworkClient.java new file mode 100644 index 0000000..c8f2abe --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/network/NetworkClient.java @@ -0,0 +1,40 @@ +package com.ichangemycity.ichangemycommunity.network; + + +import com.google.gson.JsonObject; + +import retrofit2.Call; +import retrofit2.http.Body; +import retrofit2.http.GET; +import retrofit2.http.POST; +import retrofit2.http.PUT; +import retrofit2.http.Path; + +public interface NetworkClient { + String SEGMENT_ICHANGEMYCOMMUNITY_APP = "/ichangemycommunity"; + String SEGMENT_TODOS = "/todos"; + String SEGMENT_POSTS = "/posts"; + String SEGMENT_SURVEY= "/survey"; + String SEGMENT_CREATE_PROFILE="/createProfile"; + + String SEGMENT_INITIATE_OTP="/initiatePhoneVerification"; + String SEGMENT_VALIDATE_OTP="/completePhoneVerification"; + + + @GET(SEGMENT_ICHANGEMYCOMMUNITY_APP +SEGMENT_TODOS+"/"+"{todoId}") + Call todos(@Path("todoId") String todoId); + + + @POST(SEGMENT_ICHANGEMYCOMMUNITY_APP +SEGMENT_POSTS) + Call posts(@Body JsonObject jsonObject); + + + @POST(SEGMENT_ICHANGEMYCOMMUNITY_APP +SEGMENT_SURVEY+SEGMENT_INITIATE_OTP) + Call initiateOTP(@Body JsonObject requestObject); + + @PUT(SEGMENT_ICHANGEMYCOMMUNITY_APP +SEGMENT_SURVEY+SEGMENT_VALIDATE_OTP) + Call validateOTP(@Body JsonObject requestObject); + + + +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/network/NetworkClientBuilder.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/network/NetworkClientBuilder.java new file mode 100644 index 0000000..dac8173 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/network/NetworkClientBuilder.java @@ -0,0 +1,149 @@ +package com.ichangemycity.ichangemycommunity.network; + +import android.content.Context; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.ichangemycity.ichangemycommunity.AppConfig; + +import java.security.cert.CertificateException; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import okhttp3.CipherSuite; +import okhttp3.ConnectionSpec; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.TlsVersion; +import okhttp3.logging.HttpLoggingInterceptor; +import retrofit2.Converter; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; + +public class NetworkClientBuilder { + private Context mContext; + + public NetworkClientBuilder(Context context) { + mContext = context; + } + + private OkHttpClient getOkHttpClient(boolean isNativeClient) { + + if (isNativeClient) + return new OkHttpClient.Builder() + .sslSocketFactory(getSSLSocketFactory()) + .hostnameVerifier(getHostNameVerifier()) + .addInterceptor(getLoggingInterceptor()) + .connectTimeout(10, TimeUnit.SECONDS) + .readTimeout(10, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .build(); + else + return new OkHttpClient.Builder() + .sslSocketFactory(getSSLSocketFactory()) + .hostnameVerifier(getHostNameVerifier()) + .addInterceptor(getLoggingInterceptor()) + .connectTimeout(10, TimeUnit.SECONDS) + .readTimeout(10, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .build(); + + } + + private List getConnectionSpecs() { + ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS) + .tlsVersions(TlsVersion.TLS_1_2, TlsVersion.TLS_1_1, TlsVersion.TLS_1_0) + .cipherSuites( + CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, + CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA) + .build(); + return Collections.singletonList(spec); + } + + private HostnameVerifier getHostNameVerifier() { + return new HostnameVerifier() { + @Override + public boolean verify(String s, SSLSession sslSession) { + return true; + } + }; + } + + private SSLSocketFactory getSSLSocketFactory() { + // Create a trust manager that does not validate certificate chains + SSLSocketFactory sslSocketFactory = null; + try { + final TrustManager[] trustAllCerts = new TrustManager[]{ + new X509TrustManager() { + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return new java.security.cert.X509Certificate[]{}; + } + } + }; + + // Install the all-trusting trust manager + final SSLContext sslContext = SSLContext.getInstance("SSL"); + sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); + // Create an ssl socket factory with our all-trusting manager + sslSocketFactory = sslContext.getSocketFactory(); + + } catch (Exception e) { + e.printStackTrace(); + } + + return sslSocketFactory; + } + + + private Interceptor getLoggingInterceptor() { + HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); + loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); + return loggingInterceptor; + + } + + + private Converter.Factory buildGsonConverterFactory() { + GsonBuilder gsonBuilder = new GsonBuilder(); +// gsonBuilder.registerTypeAdapter(Date.class, new DateFormatter()); +// gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES); + Gson myGson = gsonBuilder.create(); + return GsonConverterFactory.create(myGson); + } + + public NetworkClient getDefaultNetworkClient() { + return getNetworkClient(AppConfig.getHostDefault()); + } + + public NetworkClient getCustomNetworkClient(String baseUrl) { + return getNetworkClient(baseUrl); + } + + private NetworkClient getNetworkClient(String baseUrl) { + return new Retrofit.Builder() + .client(getOkHttpClient(true)) + .baseUrl(baseUrl) + .addConverterFactory(buildGsonConverterFactory()) + .build() + .create(NetworkClient.class); + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/services/AppFirebaseMessagingService.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/services/AppFirebaseMessagingService.java new file mode 100644 index 0000000..5157930 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/services/AppFirebaseMessagingService.java @@ -0,0 +1,116 @@ +//package com.ichangemycity.ichangemycommunity.services; +// +//import android.app.Notification; +//import android.app.NotificationChannel; +//import android.app.NotificationManager; +//import android.app.PendingIntent; +//import android.content.Context; +//import android.content.Intent; +//import android.graphics.BitmapFactory; +//import android.graphics.Color; +//import android.media.RingtoneManager; +//import android.net.Uri; +//import android.os.Bundle; +//import android.util.Log; +// +//import androidx.annotation.NonNull; +//import androidx.core.app.NotificationCompat; +// +//import com.google.firebase.messaging.FirebaseMessagingService; +//import com.google.firebase.messaging.RemoteMessage; +//import com.ichangemycity.ichangemycommunity.R; +//import com.ichangemycity.ichangemycommunity.ui.activities.SurveyHomeActivity; +//import com.ichangemycity.ichangemycommunity.utils.AppUtils; +//import com.ichangemycity.ichangemycommunity.utils.LogUtils; +//import com.ichangemycity.ichangemycommunity.utils.PushNotificationsUtil; +// +//import java.util.HashMap; +//import java.util.Map; +// +//import static androidx.core.content.ContextCompat.getSystemService; +// +//public class AppFirebaseMessagingService extends FirebaseMessagingService { +// public static final String TAG = AppFirebaseMessagingService.class.getSimpleName(); +// private static int count = 0; +// private PushNotificationsUtil pushNotificationsUtil; +// +// public AppFirebaseMessagingService() { +// super(); +// } +// +// @Override +// public void onMessageReceived(@NonNull RemoteMessage remoteMessage) { +// Map> data = new HashMap<>(); +// Intent intent = remoteMessage.toIntent(); +// Bundle bundle = intent.getExtras(); +// Log.d(TAG, "onMessageReceived: " + bundle); +// sendNotification(bundle); +// } +// +// @Override +// public void onDeletedMessages() { +// super.onDeletedMessages(); +// LogUtils.debug(TAG, "onDeletedMessages::"); +// } +// +// @Override +// public void onMessageSent(@NonNull String s) { +// super.onMessageSent(s); +// LogUtils.debug(TAG, "onMessageSent::" + s); +// } +// +// @Override +// public void onSendError(@NonNull String s, @NonNull Exception e) { +// super.onSendError(s, e); +// LogUtils.debug(TAG, "onSendError::" + s); +// LogUtils.debug(TAG, "onSendError::" + e.getMessage()); +// } +// +// @Override +// public void onNewToken(@NonNull String s) { +// super.onNewToken(s); +// LogUtils.debug(TAG, "onNewToken::" + s); +// AppUtils.saveFCMToken(s); +// //TODO call updateProfile +// } +// +// private void sendNotification(Bundle bundle) { +// Log.d(TAG, "sendNotification: " + bundle); +// String title = String.valueOf(bundle.get("title")); +// String body = String.valueOf(bundle.get("body")); +// pushNotificationsUtil = new PushNotificationsUtil(this); +// pushNotificationsUtil.configureNotificationActions(bundle); +// Intent intent = new Intent(this, SurveyHomeActivity.class); +// intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); +// PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT); +// +// Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); +// NotificationManager mNotifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); +// //For Android Version Orio and greater than orio. +// if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { +// NotificationChannel mChannel = new NotificationChannel("ichangemycommunity", "ichangemycommunity", NotificationManager.IMPORTANCE_HIGH); +// mChannel.setDescription(body); +// mChannel.enableLights(true); +// mChannel.setLightColor(Color.RED); +// mChannel.setSound(defaultSoundUri, Notification.AUDIO_ATTRIBUTES_DEFAULT); +// mChannel.enableVibration(true); +// mChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400}); +// mNotifyManager.createNotificationChannel(mChannel); +// } +// //For Android Version lower than oreo. +// NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, "ichangemycommunity"); +// mBuilder.setContentTitle(title) +// .setContentText(body) +// .setSmallIcon(R.drawable.app_logo) +// .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.app_logo)) +// .setAutoCancel(true) +// .setSound(defaultSoundUri) +// .setColor(Color.parseColor("#FFD600")) +// .setContentIntent(pendingIntent) +// .setChannelId("ichangemycommunity") +// .setPriority(NotificationCompat.PRIORITY_HIGH); +// +// mNotifyManager.notify(count, mBuilder.build()); +// count++; +// } +//} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/services/ImageUploadService.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/services/ImageUploadService.java new file mode 100644 index 0000000..88ffb23 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/services/ImageUploadService.java @@ -0,0 +1,73 @@ +package com.ichangemycity.ichangemycommunity.services; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; + +import androidx.annotation.Nullable; +import com.ichangemycity.ichangemycommunity.AppConstant; +import com.ichangemycity.ichangemycommunity.utils.LogUtils; + +import java.io.File; + +public class ImageUploadService extends Service { + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } + + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { +// performS3ImageSync(); + return Service.START_NOT_STICKY; + } + +// private void performS3ImageSync() { +// LogUtils.debug("Syncing images on s3"); +// AWSCredentials credentials = new AWSCredentials() { +// @Override +// public String getAWSAccessKeyId() { +// return AppConstant.AWS_ACCESS_KEY; +// } +// +// @Override +// public String getAWSSecretKey() { +// return AppConstant.AWS_SECRET_KEY; +// } +// +// +// }; +// TransferManager transferManager = new TransferManager(credentials); +// File dir = new File(AppConstant.BASE_FOLDER); +// File[] directory = dir.listFiles(); +// if (directory != null) { +// for (File file : directory) { +// String key = file.getName(); +// LogUtils.debug("Syncing images on s3 key:" + key); +// awsUpload(transferManager, AppConstant.AWS_IMAGES_BUCKET_NAME, key, file); +// file.delete(); +// } +// } +// +// transferManager.shutdownNow(); +// LogUtils.debug("Images Sync campaign finished"); +// } +// +// +// private void awsUpload(TransferManager transferManager, String bucketName, String key, File file) { +// Upload myUpload = transferManager.upload(bucketName, key, file); +// if (myUpload.isDone() == false) { +// LogUtils.debug("Transfer: " + myUpload.getDescription()); +// LogUtils.debug(" - State: " + myUpload.getState()); +// LogUtils.debug(" - Progress: " +// + myUpload.getProgress().getBytesTransferred()); +// } +// try { +// myUpload.waitForCompletion(); +// } catch (InterruptedException e) { +// e.printStackTrace(); +// } +// } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/services/LocationService.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/services/LocationService.java new file mode 100644 index 0000000..f2039f8 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/services/LocationService.java @@ -0,0 +1,149 @@ +package com.ichangemycity.ichangemycommunity.services; + +import android.Manifest; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.BitmapFactory; +import android.graphics.Color; +import android.location.Location; +import android.media.RingtoneManager; +import android.net.Uri; +import android.os.Build; +import android.os.IBinder; +import android.os.Looper; +import android.util.Log; + +import androidx.annotation.Nullable; +import androidx.core.app.ActivityCompat; +import androidx.core.app.NotificationCompat; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + +import com.google.android.gms.location.FusedLocationProviderClient; +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.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.ui.activities.SurveyHomeActivity; +import com.ichangemycity.ichangemycommunity.utils.IChangeMyCommunityConstants; +import com.ichangemycity.ichangemycommunity.utils.map.MapInputContainerEnum; +import com.ichangemycity.ichangemycommunity.utils.map.UserClient; + +public class LocationService extends Service { + + private static final String TAG = "LocationService"; + private LocationCallback locationCallback; + private FusedLocationProviderClient mFusedLocationClient; + private MapInputContainerEnum mapInputContainerEnum; + private UserClient userClient; + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public void onCreate() { + super.onCreate(); + + userClient = (UserClient) getApplicationContext(); + mFusedLocationClient = LocationServices.getFusedLocationProviderClient(getApplicationContext()); + + if (Build.VERSION.SDK_INT >= 26) { + String CHANNEL_ID = "ichangemycommunity"; + NotificationChannel channel = new NotificationChannel(CHANNEL_ID, + "ichangemycommunity", + NotificationManager.IMPORTANCE_DEFAULT); + + ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel); + + Intent intent = new Intent(this, SurveyHomeActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); + PendingIntent pendingIntent = PendingIntent.getActivity(this, 1234, intent, PendingIntent.FLAG_ONE_SHOT); + + Uri defaultSoundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); + Notification notification = new NotificationCompat.Builder(getApplicationContext(), CHANNEL_ID) + .setContentTitle(getResources().getString(R.string.location)) + .setContentText(getResources().getString(R.string.locationDetail)) + .setSmallIcon(R.drawable.app_logo) + .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.app_logo)) + .setAutoCancel(true) + .setSound(defaultSoundUri) + .setColor(Color.parseColor("#FFD600")) + .setContentIntent(pendingIntent) + .setChannelId("ichangemycommunity") + .setPriority(NotificationCompat.PRIORITY_LOW) + .build(); + + startForeground(1, notification); + } + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Log.d(TAG, "onStartCommand: called."); + getLocation(); + return Service.START_NOT_STICKY; + } + + private void getLocation() { + // ---------------------------------- LocationRequest ------------------------------------ + // Create the location request to start receiving updates + LocationRequest mLocationRequestHighAccuracy = new LocationRequest(); + mLocationRequestHighAccuracy.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); + mLocationRequestHighAccuracy.setInterval(IChangeMyCommunityConstants.UPDATE_INTERVAL); + mLocationRequestHighAccuracy.setFastestInterval(IChangeMyCommunityConstants.FASTEST_INTERVAL); + + + // new Google API SDK v11 uses getFusedLocationProviderClient(this) + if (ActivityCompat.checkSelfPermission(this, + Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + Log.d(TAG, "getLocation: stopping the location service."); + stopSelf(); + return; + } + Log.d(TAG, "getLocation: getting location information."); + locationCallback(); + mFusedLocationClient.requestLocationUpdates(mLocationRequestHighAccuracy, locationCallback, + Looper.myLooper()); // Looper.myLooper tells this to repeat forever until thread is destroyed + } + + private void locationCallback() { + locationCallback = new LocationCallback() { + @Override + public void onLocationResult(LocationResult locationResult) { + Location location = locationResult.getLastLocation(); + double lat = location.getLatitude(); + double lng = location.getLongitude(); + mapInputContainerEnum = userClient.getMapInputContainerEnum(); + userClient.saveUserLocation(lat, lng); + if (userClient.isInitialLocationBroadcast() && mapInputContainerEnum.compareTo(MapInputContainerEnum.LoaderFragment) == 0) { + Log.d(TAG, "send onLocationResult: got location result: Lat: " + lat + ", Lng: " + lng); + sendMessage(); + } else { + Log.d(TAG, "stop onLocationResult: got location result: Lat: " + lat + ", Lng: " + lng); + stopSelf(); + } + } + }; + } + + private void sendMessage() { + Log.d("sender", "Broadcasting message"); + Intent broadcastIntent = new Intent(IChangeMyCommunityConstants.INITIAL_LOCATION_BROADCAST); + LocalBroadcastManager.getInstance(this).sendBroadcast(broadcastIntent); + } + + @Override + public void onDestroy() { + super.onDestroy(); + stopSelf(); + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/activities/BaseActivity.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/activities/BaseActivity.java new file mode 100644 index 0000000..56ffd49 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/activities/BaseActivity.java @@ -0,0 +1,186 @@ +package com.ichangemycity.ichangemycommunity.ui.activities; + +import android.app.Activity; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.MenuItem; +import android.view.View; +import android.view.inputmethod.InputMethodManager; +import android.widget.Toast; + +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentTransaction; + +import com.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.utils.LogUtils; + +import butterknife.ButterKnife; + + +public abstract class BaseActivity extends AppCompatActivity { + + protected String TAG; + private ProgressDialog mProgressDialog; + protected Toolbar mToolbar; + + + protected abstract int getContentViewId(); + + protected abstract void onCreateActivity(Bundle bundle); + + public BaseActivity() { + this.TAG = getClass().getSimpleName(); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + LogUtils.debug(this.TAG, "* onCreateActivity"); + setContentView(getContentViewId()); + ButterKnife.bind((Activity) this); + //TODO enable this for toolbar support +// this.mToolbar = (Toolbar) ButterKnife.findById((Activity) this, (int) R.id.toolbar); +// if (this.mToolbar != null) { +// setSupportActionBar(this.mToolbar); +// } + onCreateActivity(savedInstanceState); + } + + @Override + protected void onResume() { + super.onResume(); + LogUtils.debug(this.TAG, "* onResumeActivity"); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + LogUtils.debug(this.TAG, "* onDestroyActivity"); + } + + @Override + protected void onPause() { + super.onPause(); + LogUtils.debug(this.TAG, "* onPause"); + hideSoftKeyboard(); + } + + public void showToast(String text) { + if (text != null) { + Toast.makeText(this, text, Toast.LENGTH_LONG).show(); + LogUtils.debug(this.TAG, "toast: " + text); + } + } + + public void showToast(int res) { + showToast(getString(res)); + } + + protected void hideSoftKeyboard() { + if (getCurrentFocus() != null) { + ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + int id = item.getItemId(); +// if (!(this instanceof MainActivity) && id == android.R.id.home) { +// onBackPressed(); +// } + return super.onOptionsItemSelected(item); + } + + + @Override + protected void onStart() { + super.onStart(); + } + + + @Override + protected void onStop() { + super.onStop(); + } + + protected void showProgressDialog(String s) { + if (this.mProgressDialog == null) { + this.mProgressDialog = new ProgressDialog(this); + this.mProgressDialog.setCancelable(false); + this.mProgressDialog.setIndeterminate(true); + this.mProgressDialog.setCanceledOnTouchOutside(false); + } + this.mProgressDialog.setMessage(s); + this.mProgressDialog.show(); + } + + protected void showFragment(Fragment fragment, int containerViewId, boolean isFirstFragmentInContainer) { + + if (isFirstFragmentInContainer) { + FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); + fragmentTransaction.add(containerViewId, fragment, null); + fragmentTransaction.commitAllowingStateLoss(); + } else { + String fragmentTag = fragment.getClass().getSimpleName(); + FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); + fragmentTransaction.replace(containerViewId, fragment, fragmentTag); + fragmentTransaction.addToBackStack(fragmentTag); + fragmentTransaction.commitAllowingStateLoss(); + } + } + + + protected void showProgressDialog(int res) { + showProgressDialog(getString(res)); + } + + protected Boolean getProgressDialogState() { + boolean z = this.mProgressDialog != null && this.mProgressDialog.isShowing(); + return Boolean.valueOf(z); + } + + protected void closeProgressDialog() { + if (this.mProgressDialog != null && this.mProgressDialog.isShowing()) { + this.mProgressDialog.dismiss(); + } + } + + + protected void hideKeyboard() { + View view = this.getCurrentFocus(); + if (view != null) { + InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + } + } + + public void showInfoDialog(String title, String msg, DialogInterface.OnClickListener listener) { + new AlertDialog.Builder(this) + .setTitle(title) + .setMessage(msg) + .setPositiveButton("Ok", listener).show(); + } + + public void showProgressDialog() { + mProgressDialog = ProgressDialog.show(this, "Please wait ...", "Loading...", true); + mProgressDialog.setCancelable(false); + } + + public void hideProgressDialog() { + if (mProgressDialog != null) + mProgressDialog.dismiss(); + } + + + public void toogleView(View toShow, View toHide) { + toShow.setVisibility(View.VISIBLE); + toHide.setVisibility(View.GONE); + + } + +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/activities/CameraActivity.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/activities/CameraActivity.java new file mode 100644 index 0000000..0a14f65 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/activities/CameraActivity.java @@ -0,0 +1,113 @@ +package com.ichangemycity.ichangemycommunity.ui.activities; + +import android.content.Intent; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.Button; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; +import androidx.appcompat.app.AppCompatActivity; +import androidx.camera.core.CameraSelector; +import androidx.camera.core.ImageCapture; +import androidx.camera.core.ImageCaptureException; +import androidx.camera.core.Preview; +import androidx.camera.lifecycle.ProcessCameraProvider; +import androidx.camera.view.PreviewView; +import androidx.core.content.ContextCompat; +import androidx.lifecycle.LifecycleOwner; + +import com.google.common.util.concurrent.ListenableFuture; +import com.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.utils.camera.CameraUtils; + +import java.io.File; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; + +public class CameraActivity extends AppCompatActivity { + + private CameraUtils cameraUtils; + private Button mCaptureBtn; + private static final String FILENAME = "yyyy-MM-dd-HH-mm-ss-SSS"; + private static final String PHOTO_EXTENSION = ".jpg"; + Preview preview; + ImageCapture imageCapture; + + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.camera_activity); + + cameraUtils = new CameraUtils(); + cameraUtils.verifyStoragePermissions(this); + mCaptureBtn = findViewById(R.id.camera_capture_button); + + PreviewView previewView = findViewById(R.id.viewFinder); + startCamera(previewView); + + mCaptureBtn.setOnClickListener(new View.OnClickListener() { + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + @Override + public void onClick(View v) { + captureImage(); + } + }); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private void captureImage() { + + File photoFile = cameraUtils.createFile(cameraUtils.getOutputDirectory(this), FILENAME, PHOTO_EXTENSION); + + ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(photoFile).build(); + + imageCapture.takePicture(outputFileOptions, Executors.newSingleThreadExecutor(), + new ImageCapture.OnImageSavedCallback() { + @Override + public void onImageSaved(ImageCapture.OutputFileResults outputFileResults) { + Uri savedUri = Uri.fromFile(photoFile); + } + + @Override + public void onError(ImageCaptureException error) { + Log.d("TAG", error.toString()); + + } + }); + } + + private void startCamera(PreviewView previewView) { + ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(this); + cameraProviderFuture.addListener(() -> { + try { + ProcessCameraProvider cameraProvider = cameraProviderFuture.get(); + bindPreviewAndImageCapture(cameraProvider, previewView); + } catch (ExecutionException | InterruptedException e) { + // No errors need to be handled for this Future. + // This should never be reached. + } + }, ContextCompat.getMainExecutor(this)); + } + + public void bindPreviewAndImageCapture(@NonNull ProcessCameraProvider cameraProvider, PreviewView previewView) { + + preview = new Preview.Builder().build(); + imageCapture = new ImageCapture.Builder().setTargetRotation(previewView.getDisplay().getRotation()).build(); + + + CameraSelector cameraSelector = new CameraSelector.Builder() + .requireLensFacing(CameraSelector.LENS_FACING_BACK) + .build(); + + preview.setSurfaceProvider(previewView.getSurfaceProvider()); + + cameraProvider.unbindAll(); + cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, preview, imageCapture); + } + +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/activities/MainActivity.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/activities/MainActivity.java new file mode 100644 index 0000000..aa9470c --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/activities/MainActivity.java @@ -0,0 +1,90 @@ +package com.ichangemycity.ichangemycommunity.ui.activities; + +import android.os.Bundle; +import android.view.View; +import android.widget.Button; + +import androidx.appcompat.app.AppCompatActivity; + +import com.google.gson.JsonObject; +import com.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.utils.LogUtils; + +public class MainActivity extends AppCompatActivity implements View.OnClickListener { + Button mGetApiClick, mPostApiClick; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + mGetApiClick = findViewById(R.id.getApiCLick); + mGetApiClick.setOnClickListener(this); + + mPostApiClick = findViewById(R.id.postApiClick); + mPostApiClick.setOnClickListener(this); + } + + private void dummyGetCall(String todoId) { + LogUtils.debug("dummyGetCall", "fetchIssueDetails"); +// +// AppMain.getDefaultNetWorkClient().todos(todoId).enqueue(new Callback() { +// @Override +// public void onResponse(Call call, Response response) { +//// if(response.code() == HTTP_CODE_SUCCESS){ +//// setIncidentValues(response.body()); +//// } +// +// LogUtils.debug("Response"); +// LogUtils.debug(String.valueOf(response.code())); +// LogUtils.debug(new Gson().toJson(response.body())); +// } +// +// @Override +// public void onFailure(Call call, Throwable t) { +// //TODO: Show retrofit error dialog +// LogUtils.debug("Network call onFailure get callv", new Gson().toJson(call)); +// } +// }); + + } + + + private void dummyPostCall() { + JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("title", "foo"); + jsonObject.addProperty("body", "bar"); + jsonObject.addProperty("userId", 1); + +// AppMain.getDefaultNetWorkClient().posts(jsonObject).enqueue(new Callback() { +// @Override +// public void onResponse(Call call, Response response) { +//// if(response.code() == HTTP_CODE_SUCCESS){ +//// setIncidentValues(response.body()); +//// } +// LogUtils.debug("Network call OnResponse post call", new Gson().toJson(response)); +// } +// +// @Override +// public void onFailure(Call call, Throwable t) { +// //TODO: Show retrofit error dialog +// LogUtils.debug("Network call onFailure post call", new Gson().toJson(call)); +// } +// }); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.getApiCLick: + dummyGetCall("1"); + break; + + case R.id.postApiClick: + dummyPostCall(); + break; + + + } + } +} + diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/activities/SplashActivity.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/activities/SplashActivity.java new file mode 100644 index 0000000..fe1f948 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/activities/SplashActivity.java @@ -0,0 +1,33 @@ +package com.ichangemycity.ichangemycommunity.ui.activities; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; + +import androidx.appcompat.app.AppCompatActivity; + +import com.ichangemycity.ichangemycommunity.AppConstant; +import com.ichangemycity.ichangemycommunity.R; + + +public class SplashActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_splash); + init(); + } + + + private void init() { + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + Intent navIntent = new Intent(SplashActivity.this, SurveyHomeActivity.class); + startActivity(navIntent); + finish(); + } + }, AppConstant.SPLASH_SCREEN_TIME_OUT); + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/activities/SurveyHomeActivity.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/activities/SurveyHomeActivity.java new file mode 100644 index 0000000..5bb3cf6 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/activities/SurveyHomeActivity.java @@ -0,0 +1,430 @@ +package com.ichangemycity.ichangemycommunity.ui.activities; + +import android.Manifest; +import android.app.ActivityManager; +import android.app.Dialog; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.location.Location; +import android.location.LocationManager; +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; +import android.view.MenuItem; +import android.widget.FrameLayout; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.core.view.GravityCompat; +import androidx.drawerlayout.widget.DrawerLayout; +import androidx.fragment.app.Fragment; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; + +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GoogleApiAvailability; +import com.google.android.gms.location.FusedLocationProviderClient; +import com.google.android.gms.location.LocationServices; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.android.material.navigation.NavigationView; +import com.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.services.LocationService; +import com.ichangemycity.ichangemycommunity.ui.fragments.MapViewFragment; +import com.ichangemycity.ichangemycommunity.ui.fragments.SurveyCategoryFragment; +import com.ichangemycity.ichangemycommunity.ui.fragments.SurveyFormFragment; +import com.ichangemycity.ichangemycommunity.ui.fragments.SurveyHomeFragment; +import com.ichangemycity.ichangemycommunity.ui.fragments.WalkabilityFragment; +import com.ichangemycity.ichangemycommunity.ui.listeners.ReplaceInputContainerListener; +import com.ichangemycity.ichangemycommunity.ui.listeners.SelectSurveyFilterListener; +import com.ichangemycity.ichangemycommunity.ui.listeners.SubmitSurveyListener; +import com.ichangemycity.ichangemycommunity.utils.FragmentUtils; +import com.ichangemycity.ichangemycommunity.utils.map.MapInputContainerEnum; +import com.ichangemycity.ichangemycommunity.utils.map.MapUtils; +import com.ichangemycity.ichangemycommunity.utils.map.UserClient; + +import static com.ichangemycity.ichangemycommunity.utils.IChangeMyCommunityConstants.ERROR_DIALOG_REQUEST; +import static com.ichangemycity.ichangemycommunity.utils.IChangeMyCommunityConstants.INITIAL_LOCATION_BROADCAST; +import static com.ichangemycity.ichangemycommunity.utils.IChangeMyCommunityConstants.MAP_LAYOUT_STATE_CONTRACTED; +import static com.ichangemycity.ichangemycommunity.utils.IChangeMyCommunityConstants.MAP_LAYOUT_STATE_EXPANDED; +import static com.ichangemycity.ichangemycommunity.utils.IChangeMyCommunityConstants.PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION; +import static com.ichangemycity.ichangemycommunity.utils.IChangeMyCommunityConstants.PERMISSIONS_REQUEST_ENABLE_GPS; +import static com.ichangemycity.ichangemycommunity.utils.IChangeMyCommunityConstants.UPDATE_INTERVAL; + +public class SurveyHomeActivity extends AppCompatActivity + implements NavigationView.OnNavigationItemSelectedListener, + MapViewFragment.MapViewSizeListener, + ReplaceInputContainerListener, + SelectSurveyFilterListener, + SubmitSurveyListener { + + private static final String TAG = SurveyHomeActivity.class.getSimpleName(); + + private MapUtils mapUtils = new MapUtils(); + private FusedLocationProviderClient mFusedLocationClient; + private UserClient userClient; + private FragmentUtils fragmentUtils = new FragmentUtils(); + private MapInputContainerEnum mapInputContainerEnum; + private Handler mHandler = new Handler(); + private Runnable mRunnable; + + private int mMapLayoutState = 0; + private boolean mLocationPermissionGranted = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_navigation_screen); +// Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); +// setSupportActionBar(toolbar); + +// DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); +// ActionBarDrawerToggle toggle = new ActionBarDrawerToggle( +// this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close); +// drawer.addDrawerListener(toggle); +// toggle.syncState(); + + NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); + navigationView.setNavigationItemSelectedListener(this); + + mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this); + userClient = (UserClient) getApplicationContext(); + startDriverRunnable(); + } + + @Override + protected void onPause() { + super.onPause(); + // Unregister since the activity is paused. + LocalBroadcastManager.getInstance(this).unregisterReceiver( + mMessageReceiver); + } + + @Override + protected void onResume() { + super.onResume(); + LocalBroadcastManager.getInstance(this).registerReceiver( + mMessageReceiver, new IntentFilter(INITIAL_LOCATION_BROADCAST)); + } + + private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (userClient.isInitialLocationBroadcast() && userClient.getMapInputContainerEnum().compareTo(MapInputContainerEnum.LoaderFragment) == 0) { + Log.d("receiver", "Got message"); + userClient.setInitialLocationBroadcast(false); + userClient.setMapInputContainerEnum(MapInputContainerEnum.SurveyFormFragment); + onReplaceInputContainer(); + } + } + }; + + @Override + public void onBackPressed() { + DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); + Fragment f = getSupportFragmentManager().findFragmentById(R.id.input_view_container); + Fragment f1 = getSupportFragmentManager().findFragmentById(R.id.surveyHomeContainer); + if (drawer.isDrawerOpen(GravityCompat.START)) { + drawer.closeDrawer(GravityCompat.START); + } else if (f1 instanceof SurveyCategoryFragment || + f1 instanceof WalkabilityFragment) { + Log.i("BACK PRESSED", "BACK PRESSED"); + } else if (f instanceof SurveyFormFragment) {//the fragment on which you want to handle your back press + Log.i("BACK PRESSED", "BACK PRESSED"); + } else { + super.onBackPressed(); + } + } + +// @Override +// public boolean onCreateOptionsMenu(Menu menu) { +// // Inflate the menu; this adds items to the action bar if it is present. +// getMenuInflater().inflate(R.menu.navigation_screen, menu); +// return true; +// } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // Handle action bar item clicks here. The action bar will + // automatically handle clicks on the Home/Up button, so long + // as you specify a parent activity in AndroidManifest.xml. + int id = item.getItemId(); + +// //noinspection SimplifiableIfStatement +// if (id == R.id.action_settings) { +// return true; +// } + + return super.onOptionsItemSelected(item); + } + + @SuppressWarnings("StatementWithEmptyBody") + @Override + public boolean onNavigationItemSelected(MenuItem item) { + // Handle navigation view item clicks here. + int id = item.getItemId(); + + if (id == R.id.nav_camera) { + // Handle the camera action + Intent i = new Intent(SurveyHomeActivity.this, + SurveyHomeActivity.class); + startActivity(i); + } else if (id == R.id.nav_gallery) { + + } else if (id == R.id.nav_manage) { + + } else if (id == R.id.nav_share) { + + } else if (id == R.id.nav_send) { + + } + + DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); + drawer.closeDrawer(GravityCompat.START); + return true; + } + + /* + Step 0: Check Map Service + a. Determine if google services can be used on the device + b. Determine if GPS is enabled on the device, send to settings screen to enable GPS + c. If GPS is not enabled, explicitly asking for location permissions + */ + private boolean checkMapServices() { + if (isServicesOK()) { + if (isMapsEnabled()) { + return true; + } + } + return false; + } + + // Used to determine if google services can be used by device + public boolean isServicesOK() { + Log.d(TAG, "isServicesOK: checking google services version"); + + int available = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this); + + if (available == ConnectionResult.SUCCESS) { + //everything is fine and the user can make map requests + Log.d(TAG, "isServicesOK: Google Play Services is working"); + return true; + } else if (GoogleApiAvailability.getInstance().isUserResolvableError(available)) { + //an error occured but we can resolve it + Log.d(TAG, "isServicesOK: an error occured but we can fix it"); + Dialog dialog = GoogleApiAvailability.getInstance().getErrorDialog(this, available, ERROR_DIALOG_REQUEST); + dialog.show(); + } else { + Toast.makeText(this, "You can't make map requests", Toast.LENGTH_SHORT).show(); + Log.d(TAG, "You can't make map requests"); + } + return false; + } + + // Used to determine if maps is enabled on the device + public boolean isMapsEnabled() { + final LocationManager manager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); + if (!manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) { + buildAlertMessageNoGps(); + return false; + } + return true; + } + + // This will open Settings on the device to enable GPS + private void buildAlertMessageNoGps() { + final AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setMessage("This application requires GPS to work properly, do you want to enable it?") + .setCancelable(false) + .setPositiveButton("Yes", new DialogInterface.OnClickListener() { + public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) { + Intent enableGpsIntent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS); + startActivityForResult(enableGpsIntent, PERMISSIONS_REQUEST_ENABLE_GPS); + } + }); + final AlertDialog alert = builder.create(); + alert.show(); + } + + // startActivityForResult is triggered to enable GPS + // If GPS is enabled, we continue with request + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + Log.d(TAG, "onActivityResult: called."); + switch (requestCode) { + case PERMISSIONS_REQUEST_ENABLE_GPS: + if (mLocationPermissionGranted) { + getLastKnownLocation(); + } else { + getLocationPermission(); + } + break; + } + } + + private void getLocationPermission() { + /* + * Request location permission, so that we can get the location of the + * device. The result of the permission request is handled by a callback, + * onRequestPermissionsResult. + */ + if (ContextCompat.checkSelfPermission(this, + android.Manifest.permission.ACCESS_FINE_LOCATION) + == PackageManager.PERMISSION_GRANTED) { + mLocationPermissionGranted = true; + getLastKnownLocation(); + } else { + ActivityCompat.requestPermissions(this, + new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, + PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION); + } + } + + + // Run after location permissions are selected + @Override + public void onRequestPermissionsResult(int requestCode, + @NonNull String permissions[], + @NonNull int[] grantResults) { + mLocationPermissionGranted = false; + switch (requestCode) { + case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: + // If request is cancelled, the result arrays are empty. + if (grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + mLocationPermissionGranted = true; + getLastKnownLocation(); + } + break; + } + } + + private void getLastKnownLocation() { + Log.d(TAG, "getLastKnownLocation: called."); + mapInputContainerEnum = userClient.getMapInputContainerEnum(); + if (userClient.isInitialLocationBroadcast() && mapInputContainerEnum.compareTo(MapInputContainerEnum.LoaderFragment) == 0) { + startLocationService(); + } else { + if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + // TODO: Consider calling + // ActivityCompat#requestPermissions + // here to request the missing permissions, and then overriding + // public void onRequestPermissionsResult(int requestCode, String[] permissions, + // int[] grantResults) + // to handle the case where the user grants the permission. See the documentation + // for ActivityCompat#requestPermissions for more details. + return; + } + mFusedLocationClient.getLastLocation().addOnCompleteListener( + new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if (task.isSuccessful()) { + Location location = task.getResult(); + if (location != null) { + userClient.saveUserLocation(location.getLatitude(), location.getLongitude()); + } + } + } + } + ); + } + } + + private void startLocationService() { + if (!isLocationServiceRunning()) { + Intent serviceIntent = new Intent(getApplicationContext(), LocationService.class); + getApplicationContext().startService(serviceIntent); + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { + this.startForegroundService(serviceIntent); + } + } + } + + private boolean isLocationServiceRunning() { + ActivityManager manager = (ActivityManager) this.getSystemService(this.ACTIVITY_SERVICE); + for (ActivityManager.RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) { + if ("LocationService".equals(service.service.getClassName())) { + Log.d(TAG, "isLocationServiceRunning: location service is already running."); + return true; + } + } + Log.d(TAG, "isLocationServiceRunning: location service is not running."); + return false; + } + + @Override + public void onReplaceInputContainer() { + SurveyHomeFragment driverHomeFragment = new SurveyHomeFragment(); + fragmentUtils.replaceFragment(R.id.survey_home_fragment, TAG, getSupportFragmentManager(), driverHomeFragment); + } + + private void startDriverRunnable() { + mHandler.postDelayed(mRunnable = new Runnable() { + @Override + public void run() { + userClient.setMapInputContainerEnum(MapInputContainerEnum.LoaderFragment); + onReplaceInputContainer(); + if (checkMapServices()) { + if (mLocationPermissionGranted) { + getLastKnownLocation(); + } else { + getLocationPermission(); + } + } + mHandler.removeCallbacks(mRunnable); + } + }, UPDATE_INTERVAL); + } + + @Override + public void onDestroy() { + super.onDestroy(); + mHandler.removeCallbacks(mRunnable); + Intent serviceIntent = new Intent(this, LocationService.class); + Log.d(TAG, "stopping LocationService"); + this.stopService(serviceIntent); + } + + @Override + public void onMapViewSizeChange() { + int mapSize = 70; + FrameLayout mMapViewContainer = findViewById(R.id.map_view_container); + FrameLayout mInputViewContainer = findViewById(R.id.input_view_container); + if (mMapLayoutState == MAP_LAYOUT_STATE_CONTRACTED) { + mMapLayoutState = MAP_LAYOUT_STATE_EXPANDED; + mapUtils.expandMapAnimation(mMapViewContainer, mapSize, 100, + mInputViewContainer, 100 - mapSize, 0); + } else if (mMapLayoutState == MAP_LAYOUT_STATE_EXPANDED) { + mMapLayoutState = MAP_LAYOUT_STATE_CONTRACTED; + mapUtils.contractMapAnimation(mMapViewContainer, 100, mapSize, + mInputViewContainer, 0, 100 - mapSize); + } + } + + @Override + public void onSelectFilter(String filter) { + MapViewFragment mapViewFragment = new MapViewFragment(); + Bundle args = new Bundle(); + args.putString("SurveyDropDown", filter); + mapViewFragment.setArguments(args); + fragmentUtils.replaceFragment(R.id.map_view_container, TAG, getSupportFragmentManager(), mapViewFragment); + } + + @Override + public void onSubmitSurvey() { + MapViewFragment mapViewFragment = new MapViewFragment(); + Bundle args = new Bundle(); + args.putBoolean("submitsurvey", true); + mapViewFragment.setArguments(args); + fragmentUtils.replaceFragment(R.id.map_view_container, TAG, getSupportFragmentManager(), mapViewFragment); + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/adapters/LuminosityAdapter.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/adapters/LuminosityAdapter.java new file mode 100644 index 0000000..e482281 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/adapters/LuminosityAdapter.java @@ -0,0 +1,62 @@ +package com.ichangemycity.ichangemycommunity.ui.adapters; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.model.LuminosityRowItem; + +public class LuminosityAdapter extends RecyclerView.Adapter { + + private LuminosityRowItem luminosityData[]; + + public static class ViewHolder extends RecyclerView.ViewHolder { + private final TextView thumbnailText; + private final ImageView thumbnail; + + public ViewHolder(View view) { + super(view); + thumbnail = view.findViewById(R.id.thumbnail); + thumbnailText = view.findViewById(R.id.thumbnail_text); + } + + public TextView getThumbnailText() { + return thumbnailText; + } + + public ImageView getThumbnail() { + return thumbnail; + } + } + + public LuminosityAdapter(LuminosityRowItem luminosityData[]) { + this.luminosityData = luminosityData; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.recycler_view_item, parent, false); + + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + holder.thumbnail.setImageBitmap(luminosityData[position].getImage()); + holder.thumbnailText.setText(luminosityData[position].getLumens() + " Lumens"); + } + + @Override + public int getItemCount() { + return luminosityData.length; + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/CameraFragment.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/CameraFragment.java new file mode 100644 index 0000000..beafe9c --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/CameraFragment.java @@ -0,0 +1,146 @@ +package com.ichangemycity.ichangemycommunity.ui.fragments; + +import android.content.Context; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.RequiresApi; +import androidx.camera.core.CameraSelector; +import androidx.camera.core.ImageCapture; +import androidx.camera.core.ImageCaptureException; +import androidx.camera.core.Preview; +import androidx.camera.lifecycle.ProcessCameraProvider; +import androidx.camera.view.PreviewView; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.LifecycleOwner; + +import com.google.common.util.concurrent.ListenableFuture; +import com.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.ui.listeners.ReplaceInputContainerListener; +import com.ichangemycity.ichangemycommunity.utils.camera.CameraUtils; +import com.ichangemycity.ichangemycommunity.utils.map.MapInputContainerEnum; +import com.ichangemycity.ichangemycommunity.utils.map.SurveyDropDownEnum; +import com.ichangemycity.ichangemycommunity.utils.map.UserClient; + +import java.io.File; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; + +public class CameraFragment extends Fragment { + + private static final String TAG = CameraFragment.class.getSimpleName(); + private UserClient userClient; + private ReplaceInputContainerListener replaceInputContainerListener; + private CameraUtils cameraUtils; + private Button mCaptureBtn; + private static final String FILENAME = "yyyy-MM-dd-HH-mm-ss-SSS"; + private static final String PHOTO_EXTENSION = ".jpg"; + Preview preview; + ImageCapture imageCapture; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + userClient = (UserClient) getContext().getApplicationContext(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.camera_activity, null, false); + cameraUtils = new CameraUtils(); + cameraUtils.verifyStoragePermissions(requireActivity()); + mCaptureBtn = view.findViewById(R.id.camera_capture_button); + + PreviewView previewView = view.findViewById(R.id.viewFinder); + startCamera(previewView); + + mCaptureBtn.setOnClickListener(new View.OnClickListener() { + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + @Override + public void onClick(View v) { + captureImage(); + } + }); + return view; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + replaceInputContainerListener = (ReplaceInputContainerListener) context; + } + + @Override + public void onDetach() { + super.onDetach(); + replaceInputContainerListener = null; + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private void captureImage() { + + File photoFile = cameraUtils.getOutputDirectory(requireContext()); //cameraUtils.createFile(cameraUtils.getOutputDirectory(requireContext()), FILENAME, PHOTO_EXTENSION); + + ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(photoFile).build(); + + imageCapture.takePicture(outputFileOptions, Executors.newSingleThreadExecutor(), + new ImageCapture.OnImageSavedCallback() { + + @Override + public void onImageSaved(ImageCapture.OutputFileResults outputFileResults) { + Uri savedUri = Uri.fromFile(photoFile); + } + + @Override + public void onError(ImageCaptureException error) { + Log.d("TAG", error.toString()); + + } + }); + } + + private void startCamera(PreviewView previewView) { + ListenableFuture cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext()); + cameraProviderFuture.addListener(() -> { + try { + ProcessCameraProvider cameraProvider = cameraProviderFuture.get(); + bindPreviewAndImageCapture(cameraProvider, previewView); + } catch (ExecutionException | InterruptedException e) { + // No errors need to be handled for this Future. + // This should never be reached. + } + }, ContextCompat.getMainExecutor(requireContext())); + } + + public void bindPreviewAndImageCapture(@NonNull ProcessCameraProvider cameraProvider, PreviewView previewView) { + + preview = new Preview.Builder().build(); + imageCapture = new ImageCapture.Builder().setTargetRotation(previewView.getDisplay().getRotation()).build(); + + + CameraSelector cameraSelector = new CameraSelector.Builder() + .requireLensFacing(CameraSelector.LENS_FACING_BACK) + .build(); + + preview.setSurfaceProvider(previewView.getSurfaceProvider()); + + cameraProvider.unbindAll(); + cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, preview, imageCapture); + } + +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/DrivabilityFragment.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/DrivabilityFragment.java new file mode 100644 index 0000000..0cc0d55 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/DrivabilityFragment.java @@ -0,0 +1,105 @@ +package com.ichangemycity.ichangemycommunity.ui.fragments; +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.SeekBar; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.Fragment; +import com.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.ui.listeners.ReplaceInputContainerListener; +import com.ichangemycity.ichangemycommunity.utils.map.MapInputContainerEnum; +import com.ichangemycity.ichangemycommunity.utils.map.UserClient; + +public class DrivabilityFragment extends Fragment implements View.OnClickListener { + private static final String TAG = DrivabilityFragment.class.getSimpleName(); + private UserClient userClient; + private ReplaceInputContainerListener replaceInputContainerListener; + private RadioGroup mRadioGroup; + private String subcategorySelection = null; + private Button mSubmitBtn; + private TextView mQualityScore; + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + userClient = (UserClient) getContext().getApplicationContext(); + } + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_drivability, null, false); + mRadioGroup = view.findViewById(R.id.radio_group); + mRadioGroup.setOnCheckedChangeListener((group, checkedId) -> { + RadioButton rb = view.findViewById(checkedId); + subcategorySelection = rb.getText().toString(); + }); + mSubmitBtn = view.findViewById(R.id.submit); + mSubmitBtn.setOnClickListener(this::onClick); + mQualityScore = view.findViewById(R.id.quality_score); + SeekBar seekBar = view.findViewById(R.id.seekBar); + seekBar.setOnSeekBarChangeListener(seekBarChangeListener); + return view; + } + SeekBar.OnSeekBarChangeListener seekBarChangeListener = new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + mQualityScore.setText("Quality Score: " + progress + "%"); + } + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // called when the user first touches the SeekBar + } + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // called after the user finishes moving the SeekBar + } + }; + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + } + @Override + public void onAttach(Context context) { + super.onAttach(context); + replaceInputContainerListener = (ReplaceInputContainerListener) context; + } + @Override + public void onDetach() { + super.onDetach(); + replaceInputContainerListener = null; + } + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.submit: + userClient.submitSurvey(subcategorySelection, null, null, (String) mQualityScore.getText()); + showAlert(); + break; + } + } + private void showAlert() { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + LayoutInflater factory = LayoutInflater.from(getContext()); + View view = factory.inflate(R.layout.layout_submit_survey_confirmation, null); + Button mOkBtn = view.findViewById(R.id.ok); + builder.setView(view) + .setCancelable(true); + AlertDialog alert = builder.create(); + mOkBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + alert.dismiss(); + userClient.setMapInputContainerEnum(MapInputContainerEnum.SurveyFormFragment); + replaceInputContainerListener.onReplaceInputContainer(); + } + }); + alert.show(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/LoaderFragment.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/LoaderFragment.java new file mode 100644 index 0000000..05fd8ab --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/LoaderFragment.java @@ -0,0 +1,47 @@ +package com.ichangemycity.ichangemycommunity.ui.fragments; + +import android.graphics.drawable.AnimationDrawable; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import androidx.fragment.app.Fragment; + +import com.ichangemycity.ichangemycommunity.R; + +public class LoaderFragment extends Fragment { + + private static final String TAG = LoaderFragment.class.getSimpleName(); + + private ImageView loader; + private AnimationDrawable animation; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_loader, container, false); + loader = view.findViewById(R.id.loader); + loader.setBackgroundResource(R.drawable.loader_animation); + animation = (AnimationDrawable) loader.getBackground(); + return view; + } + + @Override + public void onResume() { + super.onResume(); + animation.start(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + animation.stop(); + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/LuminosityFragment.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/LuminosityFragment.java new file mode 100644 index 0000000..090c61c --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/LuminosityFragment.java @@ -0,0 +1,133 @@ +package com.ichangemycity.ichangemycommunity.ui.fragments; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.ui.listeners.ReplaceInputContainerListener; +import com.ichangemycity.ichangemycommunity.utils.camera.CameraUtils; +import com.ichangemycity.ichangemycommunity.utils.map.MapInputContainerEnum; +import com.ichangemycity.ichangemycommunity.utils.map.UserClient; + +public class LuminosityFragment extends Fragment implements View.OnClickListener { + private static final String TAG = LuminosityFragment.class.getSimpleName(); + private UserClient userClient; + private ReplaceInputContainerListener replaceInputContainerListener; + + private Button mOpenCameraBtn; + private Button mBackHomeBtn; + private CameraUtils cameraUtils; + static final int REQUEST_CODE_PERMISSIONS = 10; + private static final int CAMERA_REQUEST = 1888; + private ImageView imageView; + private static final int MY_CAMERA_PERMISSION_CODE = 100; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + userClient = (UserClient) getContext().getApplicationContext(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_luminosity, null, false); + + mOpenCameraBtn = view.findViewById(R.id.open_camera_button); + mOpenCameraBtn.setOnClickListener(this::onClick); + mBackHomeBtn = view.findViewById(R.id.back_home_button); + mBackHomeBtn.setOnClickListener(this::onClick); + + return view; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + replaceInputContainerListener = (ReplaceInputContainerListener) context; + } + + @Override + public void onDetach() { + super.onDetach(); + replaceInputContainerListener = null; + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.open_camera_button: + cameraUtils = new CameraUtils(); + if (cameraUtils.isCameraPermissionGranted(requireActivity())) { + Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); + startActivityForResult(cameraIntent, CAMERA_REQUEST); + } else { + cameraUtils.requestCameraPermission(requireActivity()); + } + break; + + case R.id.back_home_button: + // TODO: action on home button + break; + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == MY_CAMERA_PERMISSION_CODE) { + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + Toast.makeText(requireActivity(), "camera permission granted", Toast.LENGTH_LONG).show(); + Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); + startActivityForResult(cameraIntent, CAMERA_REQUEST); + } else { + Toast.makeText(requireActivity(), "camera permission denied", Toast.LENGTH_LONG).show(); + } + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) { + Bitmap photo = (Bitmap) data.getExtras().get("data"); + Bundle bundle = new Bundle(); + bundle.putParcelable("thumbnail", photo); + userClient.setMapInputContainerEnum(MapInputContainerEnum.LuminosityProgressFragment); + userClient.setBundle(bundle); + replaceInputContainerListener.onReplaceInputContainer(); + //imageView.setImageBitmap(photo); + } + } + /*@Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == REQUEST_CODE_PERMISSIONS) { + if (cameraUtils.isCameraPermissionGranted(requireActivity())) { + Intent i = new Intent(getActivity(), CameraActivity.class); + startActivity(i); + } else { + Toast.makeText(requireActivity(), "Permissions not granted by the user.", Toast.LENGTH_SHORT).show(); + } + } + }*/ + +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/LuminosityProgressFragment.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/LuminosityProgressFragment.java new file mode 100644 index 0000000..a2e2e84 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/LuminosityProgressFragment.java @@ -0,0 +1,168 @@ +package com.ichangemycity.ichangemycommunity.ui.fragments; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.hardware.Sensor; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; +import android.hardware.SensorManager; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.ui.listeners.ReplaceInputContainerListener; +import com.ichangemycity.ichangemycommunity.utils.camera.CameraUtils; +import com.ichangemycity.ichangemycommunity.utils.map.UserClient; + +import static android.content.Context.SENSOR_SERVICE; + +public class LuminosityProgressFragment extends Fragment implements View.OnClickListener, SensorEventListener { + private static final String TAG = LuminosityFragment.class.getSimpleName(); + private UserClient userClient; + private ReplaceInputContainerListener replaceInputContainerListener; + + private Button mTakeAnotherPhotoBtn; + private Button mSubmitBtn; + private ImageView thumbnail; + private TextView thumbnailText; + private CameraUtils cameraUtils; + static final int REQUEST_CODE_PERMISSIONS = 10; + private static final int CAMERA_REQUEST = 1888; + private ImageView imageView; + private static final int MY_CAMERA_PERMISSION_CODE = 100; + private SensorManager mSensorManager; + private Sensor mLuminosity; + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + userClient = (UserClient) getContext().getApplicationContext(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_captured_image, null, false); + + mSensorManager = (SensorManager) getActivity().getSystemService(SENSOR_SERVICE); + mLuminosity = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); + + thumbnail = view.findViewById(R.id.thumbnail); + thumbnailText = view.findViewById(R.id.thumbnail_text); + thumbnail.setImageBitmap(getArguments().getParcelable("thumbnail")); + mTakeAnotherPhotoBtn = view.findViewById(R.id.take_another_photo_button); + mTakeAnotherPhotoBtn.setOnClickListener(this::onClick); + mSubmitBtn = view.findViewById(R.id.submit_luminosity); + mSubmitBtn.setOnClickListener(this::onClick); + + return view; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + replaceInputContainerListener = (ReplaceInputContainerListener) context; + } + + @Override + public void onDetach() { + super.onDetach(); + replaceInputContainerListener = null; + } + + @Override + public void onResume() { + super.onResume(); + mSensorManager.registerListener(this, mLuminosity, SensorManager.SENSOR_DELAY_FASTEST); + } + + @Override + public void onPause() { + super.onPause(); + mSensorManager.unregisterListener(this); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.take_another_photo_button: + + /** + cameraUtils = new CameraUtils(); + if (cameraUtils.isCameraPermissionGranted(requireActivity())) { + Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); + startActivityForResult(cameraIntent, CAMERA_REQUEST); + } else { + cameraUtils.requestCameraPermission(requireActivity()); + } + break; **/ + + case R.id.submit_luminosity: + // TODO: action on home button + break; + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) + { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == MY_CAMERA_PERMISSION_CODE) + { + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) + { + Toast.makeText(requireActivity(), "camera permission granted", Toast.LENGTH_LONG).show(); + Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); + startActivityForResult(cameraIntent, CAMERA_REQUEST); + } + else + { + Toast.makeText(requireActivity(), "camera permission denied", Toast.LENGTH_LONG).show(); + } + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) + { + if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) + { + Bitmap photo = (Bitmap) data.getExtras().get("data"); + thumbnail.setImageBitmap(photo); + } + } + + @Override + public void onSensorChanged(SensorEvent sensorEvent) { + + if (sensorEvent.sensor.getType() == Sensor.TYPE_LIGHT) { + float currentReading = sensorEvent.values[0]; + thumbnailText.setText(currentReading + " Lumens"); + mSensorManager.unregisterListener(this); + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int i) { + + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/MapViewFragment.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/MapViewFragment.java new file mode 100644 index 0000000..96e6c66 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/MapViewFragment.java @@ -0,0 +1,273 @@ +package com.ichangemycity.ichangemycommunity.ui.fragments; + +import android.content.Context; +import android.os.Bundle; +import android.os.Handler; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.fragment.app.Fragment; + +import com.google.android.gms.maps.CameraUpdateFactory; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.MapView; +import com.google.android.gms.maps.OnMapReadyCallback; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.Marker; +import com.google.maps.GeoApiContext; +import com.google.maps.android.clustering.ClusterManager; +import com.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.model.ClusterMarker; +import com.ichangemycity.ichangemycommunity.model.Survey; +import com.ichangemycity.ichangemycommunity.utils.IChangeMyCommunityConstants; +import com.ichangemycity.ichangemycommunity.utils.map.ClusterManagerRenderer; +import com.ichangemycity.ichangemycommunity.utils.map.UserClient; + +import java.util.ArrayList; +import java.util.List; + +import static com.ichangemycity.ichangemycommunity.utils.IChangeMyCommunityConstants.MAPVIEW_BUNDLE_KEY; + +public class MapViewFragment extends Fragment implements OnMapReadyCallback, + View.OnClickListener { + + private static final String TAG = MapViewFragment.class.getSimpleName(); + + private MapView mMapView; + private GoogleMap mGoogleMap; + private MapViewSizeListener mMapViewSizeListener; + private UserClient userClient; + private Handler mHandler = new Handler(); + private Runnable mRunnable; + private GeoApiContext mGeoApiContext = null; + private LatLng userLocation; + private ClusterManager mClusterManager; + private ClusterManagerRenderer mClusterManagerRenderer; + private ArrayList mClusterMarkers = new ArrayList<>(); + private List mSurveyList = new ArrayList<>(); + private Context mContext; + private ClusterMarker mSelectedClusterMarker; + + public interface MapViewSizeListener { + void onMapViewSizeChange(); + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + userClient = (UserClient) getContext().getApplicationContext(); + mContext = getActivity().getApplicationContext(); + if (mSurveyList.size() == 0) { + Bundle bundle = getArguments(); + if (bundle != null) { + if (bundle.containsKey("submitsurvey")) { + Log.d(TAG, "submitsurvey not null"); + } + if (bundle.containsKey("SurveyDropDown")) { + String key = (String) getArguments().get("SurveyDropDown"); + if (key != null) { + mSurveyList = userClient.filterSurveyList(key); + } else { + mSurveyList = userClient.getSurveyList(); + } + Log.d(TAG, "getArguments() not null"); + } + } + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_map_view, container, false); + mMapView = view.findViewById(R.id.map); + view.findViewById(R.id.btn_full_screen_map).setOnClickListener(this); + view.findViewById(R.id.btn_reset_map).setOnClickListener(this); + initGoogleMap(savedInstanceState); + return view; + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + mMapViewSizeListener = (MapViewSizeListener) context; + } + + @Override + public void onDetach() { + super.onDetach(); + mMapViewSizeListener = null; + } + + private void initGoogleMap(Bundle savedInstanceState) { + // *** IMPORTANT *** + // MapView requires that the Bundle you pass contain _ONLY_ MapView SDK + // objects or sub-Bundles. + Bundle mapViewBundle = null; + if (savedInstanceState != null) { + mapViewBundle = savedInstanceState.getBundle(MAPVIEW_BUNDLE_KEY); + } + mMapView.onCreate(mapViewBundle); + mMapView.getMapAsync(this); + if (mGeoApiContext == null) { + mGeoApiContext = new GeoApiContext.Builder().apiKey(getString(R.string.google_maps_key)).build(); + } + userLocation = userClient.getUserLatLng(); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + Bundle mapViewBundle = outState.getBundle(MAPVIEW_BUNDLE_KEY); + if (mapViewBundle == null) { + mapViewBundle = new Bundle(); + outState.putBundle(MAPVIEW_BUNDLE_KEY, mapViewBundle); + } + mMapView.onSaveInstanceState(mapViewBundle); + } + + @Override + public void onResume() { + super.onResume(); + mMapView.onResume(); + } + + @Override + public void onStart() { + super.onStart(); + mMapView.onStart(); + } + + @Override + public void onStop() { + super.onStop(); + mMapView.onStop(); + } + + @Override + public void onMapReady(GoogleMap map) { + mGoogleMap = map; + mGoogleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); + mGoogleMap.getUiSettings().setZoomControlsEnabled(true); + mGoogleMap.getUiSettings().setRotateGesturesEnabled(true); + mGoogleMap.getUiSettings().setScrollGesturesEnabled(true); + mGoogleMap.getUiSettings().setTiltGesturesEnabled(true); + mGoogleMap.getUiSettings().setZoomGesturesEnabled(true); + Log.d(TAG, "onMapReady"); + setCameraView(); + addSurveyMapMarkers(); + } + + private void addSurveyMapMarkers() { + if (mGoogleMap != null) { + if (mClusterManager == null) { + mClusterManager = new ClusterManager(mContext, mGoogleMap); + } + if (mClusterManagerRenderer == null) { + mClusterManagerRenderer = new ClusterManagerRenderer( + getActivity(), + mGoogleMap, + mClusterManager + ); + mClusterManager.setRenderer(mClusterManagerRenderer); + } + + mClusterManager.setOnClusterItemClickListener(new ClusterManager.OnClusterItemClickListener() { + @Override + public boolean onClusterItemClick(ClusterMarker item) { + Log.d("cluster item", "clicked"); + mSelectedClusterMarker = item; + return false; + } + }); + + mClusterManager.getMarkerCollection() + .setInfoWindowAdapter(new CustomInfoViewAdapter(LayoutInflater.from(getContext()))); + mGoogleMap.setInfoWindowAdapter(mClusterManager.getMarkerManager()); + mGoogleMap.setOnMarkerClickListener(mClusterManager); + + for (Survey survey : mSurveyList) { +// Log.d(TAG, "addMapMarkers: survey: " + survey.getPosition().toString()); + try { + ClusterMarker newClusterMarker = new ClusterMarker( + new LatLng(survey.getPosition().latitude, survey.getPosition().longitude), + "title", + "", + R.drawable.ic_survey, + survey + ); + mClusterManager.addItem(newClusterMarker); + mClusterMarkers.add(newClusterMarker); + + } catch (NullPointerException e) { + Log.e(TAG, "addMapMarkers: NullPointerException: " + e.getMessage()); + } + } + + mClusterManager.cluster(); + } + } + + private void setCameraView() { + mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom( + userLocation, IChangeMyCommunityConstants.DEFAULT_ZOOM)); + } + + @Override + public void onPause() { + mMapView.onPause(); + super.onPause(); + } + + @Override + public void onDestroy() { + mMapView.onDestroy(); + super.onDestroy(); + } + + @Override + public void onLowMemory() { + super.onLowMemory(); + mMapView.onLowMemory(); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.btn_full_screen_map: { + mMapViewSizeListener.onMapViewSizeChange(); + break; + } + } + } + + public class CustomInfoViewAdapter implements GoogleMap.InfoWindowAdapter { + + private final LayoutInflater mInflater; + + public CustomInfoViewAdapter(LayoutInflater inflater) { + this.mInflater = inflater; + } + + @Override + public View getInfoWindow(Marker marker) { + final View popup = mInflater.inflate(R.layout.info_window, null); + return null; + } + + @Override + public View getInfoContents(Marker marker) { + final View popup = mInflater.inflate(R.layout.info_window, null); + + Survey survey = mSelectedClusterMarker.getSurvey(); + ((TextView) popup.findViewById(R.id.txtCategory)).setText(survey.getCategory().toString()); + ((TextView) popup.findViewById(R.id.txtSubCategory)).setText(survey.getSubCategory()); + ((TextView) popup.findViewById(R.id.txtQualityScore)).setText(survey.getQualityScore()); + ((TextView) popup.findViewById(R.id.txtLocation)).setText(survey.getLocation()); + return popup; + } + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/SurveyCategoryFragment.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/SurveyCategoryFragment.java new file mode 100644 index 0000000..606c3a8 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/SurveyCategoryFragment.java @@ -0,0 +1,74 @@ +package com.ichangemycity.ichangemycommunity.ui.fragments; +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import com.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.ui.listeners.ReplaceInputContainerListener; +import com.ichangemycity.ichangemycommunity.utils.map.MapInputContainerEnum; +import com.ichangemycity.ichangemycommunity.utils.map.SurveyDropDownEnum; +import com.ichangemycity.ichangemycommunity.utils.map.UserClient; +public class SurveyCategoryFragment extends Fragment implements View.OnClickListener { + private static final String TAG = SurveyCategoryFragment.class.getSimpleName(); + private UserClient userClient; + private ReplaceInputContainerListener replaceInputContainerListener; + private Button walkabilityButton; + private Button visibilityButton; + private Button drivabilityButton; + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + userClient = (UserClient) getContext().getApplicationContext(); + } + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_survey_category, null, false); + walkabilityButton = view.findViewById(R.id.walkability); + visibilityButton = view.findViewById(R.id.visibility); + drivabilityButton = view.findViewById(R.id.drivability); + walkabilityButton.setOnClickListener(this::onClick); + visibilityButton.setOnClickListener(this::onClick); + drivabilityButton.setOnClickListener(this::onClick); + return view; + } + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + } + @Override + public void onAttach(Context context) { + super.onAttach(context); + replaceInputContainerListener = (ReplaceInputContainerListener) context; + } + @Override + public void onDetach() { + super.onDetach(); + replaceInputContainerListener = null; + } + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.walkability: + userClient.setSurveyCategory(SurveyDropDownEnum.Walkability); + userClient.setMapInputContainerEnum(MapInputContainerEnum.WalkabilityFragment); + replaceInputContainerListener.onReplaceInputContainer(); + break; + case R.id.drivability: + userClient.setSurveyCategory(SurveyDropDownEnum.Drivability); + userClient.setMapInputContainerEnum(MapInputContainerEnum.DrivabilityFragment); + replaceInputContainerListener.onReplaceInputContainer(); + break; + case R.id.visibility: + userClient.setSurveyCategory(SurveyDropDownEnum.Luminosity); + userClient.setMapInputContainerEnum(MapInputContainerEnum.LuminosityFragment); + replaceInputContainerListener.onReplaceInputContainer(); + break; + } + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/SurveyFormFragment.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/SurveyFormFragment.java new file mode 100644 index 0000000..8672311 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/SurveyFormFragment.java @@ -0,0 +1,102 @@ +package com.ichangemycity.ichangemycommunity.ui.fragments; + +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.Spinner; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.ui.listeners.ReplaceInputContainerListener; +import com.ichangemycity.ichangemycommunity.ui.listeners.SelectSurveyFilterListener; +import com.ichangemycity.ichangemycommunity.utils.map.MapInputContainerEnum; +import com.ichangemycity.ichangemycommunity.utils.map.UserClient; + +import java.util.ArrayList; + +public class SurveyFormFragment extends Fragment implements View.OnClickListener { + + private static final String TAG = SurveyFormFragment.class.getSimpleName(); + + private UserClient userClient; + private ReplaceInputContainerListener replaceInputContainerListener; + private SelectSurveyFilterListener selectSurveyFilterListener; + private Button mTakeSurveyBtn; + private Spinner mSpinner; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + userClient = (UserClient) getContext().getApplicationContext(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_survey_form, null, true); + mTakeSurveyBtn = view.findViewById(R.id.takeSurvey); + mSpinner = view.findViewById(R.id.spinner); + mTakeSurveyBtn.setOnClickListener(this::onClick); + ArrayAdapter adapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1, new ArrayList(userClient.getSurveyDropDownList())); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + mSpinner.setAdapter(adapter); + mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView adapterView, View view, + int position, long id) { + Object item = adapterView.getItemAtPosition(position); + selectSurveyFilterListener.onSelectFilter(item.toString()); + } + + @Override + public void onNothingSelected(AdapterView adapterView) { + // do something here? + } + }); + return view; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + replaceInputContainerListener = (ReplaceInputContainerListener) context; + selectSurveyFilterListener = (SelectSurveyFilterListener) context; + } + + @Override + public void onDetach() { + super.onDetach(); + replaceInputContainerListener = null; + selectSurveyFilterListener = null; + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.takeSurvey: + userClient.createSurvey(); + userClient.setMapInputContainerEnum(MapInputContainerEnum.SurveyCategoryFragment); + replaceInputContainerListener.onReplaceInputContainer(); + break; + } + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/SurveyHomeFragment.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/SurveyHomeFragment.java new file mode 100644 index 0000000..d95586e --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/SurveyHomeFragment.java @@ -0,0 +1,83 @@ +package com.ichangemycity.ichangemycommunity.ui.fragments; + +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.fragment.app.Fragment; + +import com.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.utils.FragmentUtils; +import com.ichangemycity.ichangemycommunity.utils.map.MapInputContainerEnum; +import com.ichangemycity.ichangemycommunity.utils.map.UserClient; + +import java.io.IOException; + +public class SurveyHomeFragment extends Fragment { + + private static final String TAG = SurveyHomeFragment.class.getSimpleName(); + + private FragmentUtils fragmentUtils = new FragmentUtils(); + private MapInputContainerEnum mapInputContainerEnum; + private UserClient userClient; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + userClient = (UserClient) getContext().getApplicationContext(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View view = inflater.inflate(R.layout.fragment_survey_home, container, false); + renderInputViewContainer(); + return view; + } + + private void renderInputViewContainer() { + mapInputContainerEnum = userClient.getMapInputContainerEnum(); + Bundle bundle = userClient.getBundle(); + + switch (mapInputContainerEnum) { + case LoaderFragment: + fragmentUtils.replaceFragment(R.id.surveyHomeContainer, TAG, getFragmentManager(), new LoaderFragment()); + break; + case SurveyCategoryFragment: + fragmentUtils.replaceFragment(R.id.surveyHomeContainer, TAG, getFragmentManager(), new SurveyCategoryFragment()); + break; + case WalkabilityFragment: + fragmentUtils.replaceFragment(R.id.surveyHomeContainer, TAG, getFragmentManager(), new WalkabilityFragment()); + break; + case VisibilityFragment: + fragmentUtils.replaceFragment(R.id.surveyHomeContainer, TAG, getFragmentManager(), new VisibilityFragment()); + break; + case LuminosityFragment: + fragmentUtils.replaceFragment(R.id.surveyHomeContainer, TAG, getFragmentManager(), new LuminosityFragment()); + break; + case DrivabilityFragment: + fragmentUtils.replaceFragment(R.id.surveyHomeContainer, TAG, getFragmentManager(), new DrivabilityFragment()); + break; + case SurveyFormFragment: + fragmentUtils.replaceFragment(R.id.map_view_container, TAG, getFragmentManager(), new MapViewFragment()); + fragmentUtils.replaceFragment(R.id.input_view_container, TAG, getFragmentManager(), new SurveyFormFragment()); + break; + case CameraFragment: + fragmentUtils.replaceFragment(R.id.surveyHomeContainer, TAG, getFragmentManager(), new CameraFragment()); + break; + case LuminosityProgressFragment: + fragmentUtils.replaceFragment(R.id.surveyHomeContainer, TAG, getFragmentManager(), bundle, new LuminosityProgressFragment()); + break; + case Unknown: + try { + throw new IOException(); + } catch (IOException e) { + Log.d(TAG, "IOException: " + e.getMessage()); + } + break; + } + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/VisibilityFragment.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/VisibilityFragment.java new file mode 100644 index 0000000..50118b6 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/VisibilityFragment.java @@ -0,0 +1,107 @@ +package com.ichangemycity.ichangemycommunity.ui.fragments; +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.SeekBar; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.Fragment; +import com.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.ui.listeners.ReplaceInputContainerListener; +import com.ichangemycity.ichangemycommunity.utils.map.MapInputContainerEnum; +import com.ichangemycity.ichangemycommunity.utils.map.UserClient; + +public class VisibilityFragment extends Fragment implements View.OnClickListener { + private static final String TAG = VisibilityFragment.class.getSimpleName(); + private UserClient userClient; + private ReplaceInputContainerListener replaceInputContainerListener; + private RadioGroup mRadioGroup; + private String subcategorySelection = null; + private Button mSubmitBtn; + private TextView mQualityScore; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + userClient = (UserClient) getContext().getApplicationContext(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_visibility, null, false); + mRadioGroup = view.findViewById(R.id.radio_group); + mRadioGroup.setOnCheckedChangeListener((group, checkedId) -> { + RadioButton rb = view.findViewById(checkedId); + subcategorySelection = rb.getText().toString(); + }); + mSubmitBtn = view.findViewById(R.id.submit); + mSubmitBtn.setOnClickListener(this::onClick); + mQualityScore = view.findViewById(R.id.quality_score); + SeekBar seekBar = view.findViewById(R.id.seekBar); + seekBar.setOnSeekBarChangeListener(seekBarChangeListener); + return view; + } + SeekBar.OnSeekBarChangeListener seekBarChangeListener = new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + mQualityScore.setText("Quality Score: " + progress + "%"); + } + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // called when the user first touches the SeekBar + } + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // called after the user finishes moving the SeekBar + } + }; + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + } + @Override + public void onAttach(Context context) { + super.onAttach(context); + replaceInputContainerListener = (ReplaceInputContainerListener) context; + } + @Override + public void onDetach() { + super.onDetach(); + replaceInputContainerListener = null; + } + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.submit: + userClient.submitSurvey(subcategorySelection, null, null, (String) mQualityScore.getText()); + showAlert(); + break; + } + } + private void showAlert() { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + LayoutInflater factory = LayoutInflater.from(getContext()); + View view = factory.inflate(R.layout.layout_submit_survey_confirmation, null); + Button mOkBtn = view.findViewById(R.id.ok); + builder.setView(view) + .setCancelable(true); + AlertDialog alert = builder.create(); + mOkBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + alert.dismiss(); + userClient.setMapInputContainerEnum(MapInputContainerEnum.SurveyFormFragment); + replaceInputContainerListener.onReplaceInputContainer(); + } + }); + alert.show(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/WalkabilityFragment.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/WalkabilityFragment.java new file mode 100644 index 0000000..5894be2 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/fragments/WalkabilityFragment.java @@ -0,0 +1,107 @@ +package com.ichangemycity.ichangemycommunity.ui.fragments; +import android.content.Context; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.SeekBar; +import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.fragment.app.Fragment; +import com.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.ui.listeners.ReplaceInputContainerListener; +import com.ichangemycity.ichangemycommunity.utils.map.MapInputContainerEnum; +import com.ichangemycity.ichangemycommunity.utils.map.UserClient; + +public class WalkabilityFragment extends Fragment implements View.OnClickListener { + private static final String TAG = WalkabilityFragment.class.getSimpleName(); + private UserClient userClient; + private ReplaceInputContainerListener replaceInputContainerListener; + private RadioGroup mRadioGroup; + private String subcategorySelection = null; + private Button mSubmitBtn; + private TextView mQualityScore; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + userClient = (UserClient) getContext().getApplicationContext(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_walkability, null, false); + mRadioGroup = view.findViewById(R.id.radio_group); + mRadioGroup.setOnCheckedChangeListener((group, checkedId) -> { + RadioButton rb = view.findViewById(checkedId); + subcategorySelection = rb.getText().toString(); + }); + mSubmitBtn = view.findViewById(R.id.submit); + mSubmitBtn.setOnClickListener(this::onClick); + mQualityScore = view.findViewById(R.id.quality_score); + SeekBar seekBar = view.findViewById(R.id.seekBar); + seekBar.setOnSeekBarChangeListener(seekBarChangeListener); + return view; + } + SeekBar.OnSeekBarChangeListener seekBarChangeListener = new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + mQualityScore.setText("Quality Score: " + progress + "%"); + } + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + // called when the user first touches the SeekBar + } + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + // called after the user finishes moving the SeekBar + } + }; + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + } + @Override + public void onAttach(Context context) { + super.onAttach(context); + replaceInputContainerListener = (ReplaceInputContainerListener) context; + } + @Override + public void onDetach() { + super.onDetach(); + replaceInputContainerListener = null; + } + @Override + public void onClick(View v) { + switch (v.getId()) { + case R.id.submit: + userClient.submitSurvey(subcategorySelection, null, null, (String) mQualityScore.getText()); + showAlert(); + break; + } + } + private void showAlert() { + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + LayoutInflater factory = LayoutInflater.from(getContext()); + View view = factory.inflate(R.layout.layout_submit_survey_confirmation, null); + Button mOkBtn = view.findViewById(R.id.ok); + builder.setView(view) + .setCancelable(true); + AlertDialog alert = builder.create(); + mOkBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + alert.dismiss(); + userClient.setMapInputContainerEnum(MapInputContainerEnum.SurveyFormFragment); + replaceInputContainerListener.onReplaceInputContainer(); + } + }); + alert.show(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/listeners/ReplaceInputContainerListener.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/listeners/ReplaceInputContainerListener.java new file mode 100644 index 0000000..3a9080c --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/listeners/ReplaceInputContainerListener.java @@ -0,0 +1,6 @@ +package com.ichangemycity.ichangemycommunity.ui.listeners; + +public interface ReplaceInputContainerListener { + + void onReplaceInputContainer(); +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/listeners/SelectSurveyFilterListener.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/listeners/SelectSurveyFilterListener.java new file mode 100644 index 0000000..9be12c4 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/listeners/SelectSurveyFilterListener.java @@ -0,0 +1,6 @@ +package com.ichangemycity.ichangemycommunity.ui.listeners; + +public interface SelectSurveyFilterListener { + + void onSelectFilter(String filter); +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/listeners/SubmitSurveyListener.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/listeners/SubmitSurveyListener.java new file mode 100644 index 0000000..be94b7b --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/ui/listeners/SubmitSurveyListener.java @@ -0,0 +1,6 @@ +package com.ichangemycity.ichangemycommunity.ui.listeners; + +public interface SubmitSurveyListener { + + void onSubmitSurvey(); +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/AppUtils.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/AppUtils.java new file mode 100644 index 0000000..843db8b --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/AppUtils.java @@ -0,0 +1,76 @@ +package com.ichangemycity.ichangemycommunity.utils; + +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; + +import com.google.gson.Gson; +import com.ichangemycity.ichangemycommunity.AppConstant; +import com.ichangemycity.ichangemycommunity.AppMain; +import com.ichangemycity.ichangemycommunity.model.User; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.List; + + + +public class AppUtils { + + public static boolean isValidList(List list) { + if (list != null && list.size() > 0) + return true; + return false; + } + + public static boolean isConnectedToInternet() { + + ConnectivityManager connectivityManager = (ConnectivityManager) AppMain.getAppMainContext().getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo(); + + // Since NetworkInfo is null incase of no current network + boolean isNetworkConnected = false; + if (networkInfo != null) { + isNetworkConnected = networkInfo.isConnected(); + } + return isNetworkConnected; + } + + + public static String getCurrentDate(){ + Date currentTime = Calendar.getInstance().getTime(); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + String currentDate=dateFormat.format(currentTime); + return currentDate; + } + + public static String getReadableDate(String dateInString){ + + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + SimpleDateFormat formatterOut = new SimpleDateFormat("dd MMM yyyy"); + try { + + Date date = formatter.parse(dateInString); + String readableDate=formatterOut.format(date); + return readableDate; + + } catch (ParseException e) { + e.printStackTrace(); + } + //TODO change this + return "31 July 2020"; + } + + public static void saveDriverDetails(User user){ + String mobile = user.getPhone(); + SharedPreferenceUtils.putStringValue(AppConstant.PREF_KEY_MOBILE,mobile); + SharedPreferenceUtils.putStringValue(AppConstant.PREF_KEY_USER_DETAILS,new Gson().toJson(user)); + } + + public static void saveFCMToken(String token) { + SharedPreferenceUtils.putStringValue(AppConstant.PREF_KEY_DEVICE_ID,token); + } + +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/DateFormatter.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/DateFormatter.java new file mode 100644 index 0000000..6def1f1 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/DateFormatter.java @@ -0,0 +1,69 @@ +package com.ichangemycity.ichangemycommunity.utils; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +import java.lang.reflect.Type; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + +public class DateFormatter implements JsonDeserializer, + JsonSerializer { + + private final DateFormat[] formats; + /** */ + public static String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'"; //$NON-NLS-1$ + /** */ + public static String DATE_FORMAT_V2_1 = "yyyy/MM/dd HH:mm:ss Z"; //$NON-NLS-1$ + /** */ + public static String DATE_FORMAT_V2_2 = "yyyy-MM-dd'T'HH:mm:ss"; //$NON-NLS-1$ + + public static String DATE_FORMAT_V2_3 = "yyyy-MM-dd"; //$NON-NLS-1$ + + /** + * Create date formatter + */ + public DateFormatter() { + formats = new DateFormat[4]; + formats[0] = new SimpleDateFormat(DATE_FORMAT); + formats[1] = new SimpleDateFormat(DATE_FORMAT_V2_1); + formats[2] = new SimpleDateFormat(DATE_FORMAT_V2_2); + formats[3] = new SimpleDateFormat(DATE_FORMAT_V2_3); + final TimeZone timeZone = TimeZone.getTimeZone("UTC"); //$NON-NLS-1$ + for (DateFormat format : formats) + format.setTimeZone(timeZone); + } + + public Date deserialize(JsonElement json, Type typeOfT, + JsonDeserializationContext context) throws JsonParseException { + JsonParseException exception = null; + final String value = json.getAsString(); + for (DateFormat format : formats) + try { + synchronized (format) { + return format.parse(value); + } + } catch (ParseException e) { + exception = new JsonParseException(e); + } + throw exception; + } + + public JsonElement serialize(Date date, Type type, + JsonSerializationContext context) { + final DateFormat primary = formats[0]; + String formatted; + synchronized (primary) { + formatted = primary.format(date); + } + return new JsonPrimitive(formatted); + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/FileUtils.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/FileUtils.java new file mode 100644 index 0000000..e754db0 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/FileUtils.java @@ -0,0 +1,41 @@ +package com.ichangemycity.ichangemycommunity.utils; + +import android.content.Context; +import android.os.Environment; + +import com.ichangemycity.ichangemycommunity.AppConstant; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; + + +public class FileUtils { + + public static File createImageFile(Context context) throws IOException { + //TODO change storage directory and pass product id + String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); + String pictureFile = AppConstant.APP_NAME + "_" + timeStamp; + File storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES); + File image = File.createTempFile(pictureFile, ".jpg", storageDir); + return image; + } + + public static File getImageFile(String imageType, String fileExtension) throws IOException { + //TODO NO NEED OF TIMESTAMP -- THIS WILL PROVIDE OVERRIDE FUNCTIONALITY + // String timeStamp = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); + String mobile = SharedPreferenceUtils.getStringValue(AppConstant.PREF_KEY_MOBILE); + File baseFolder = new File(AppConstant.BASE_FOLDER); + if (!baseFolder.exists()) + baseFolder.mkdirs(); + String imageName = AppConstant.BASE_FOLDER + mobile + "_" + imageType + "." + fileExtension; + File image = new File(imageName); + return image; + } + + +// public static String constructS3ImageUrl(String fileName) { +// return "https://" + AppConstant.AWS_IMAGES_BUCKET_NAME + ".s3.amazonaws.com/" + fileName; +// } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/FragmentUtils.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/FragmentUtils.java new file mode 100644 index 0000000..28cb2b8 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/FragmentUtils.java @@ -0,0 +1,32 @@ +package com.ichangemycity.ichangemycommunity.utils; + +import android.os.Bundle; + +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; + +public class FragmentUtils { + + public void replaceFragment(int containerId, String source, FragmentManager fragmentManager, Fragment destination) { + + // Begin Fragment transaction. + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + + // Replace the layout holder with the required Fragment object. + fragmentTransaction.replace(containerId, destination, destination.getTag()); + + fragmentTransaction.addToBackStack(source); + + // Commit the Fragment replace action. + fragmentTransaction.commit(); + } + + public void replaceFragment(int containerId, String source, FragmentManager fragmentManager, Bundle extras, Fragment destination) { + + //pass some extras to the destination + destination.setArguments(extras); + + replaceFragment(containerId, source, fragmentManager, destination); + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/IChangeMyCommunityConstants.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/IChangeMyCommunityConstants.java new file mode 100644 index 0000000..5ea4088 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/IChangeMyCommunityConstants.java @@ -0,0 +1,17 @@ +package com.ichangemycity.ichangemycommunity.utils; + +public class IChangeMyCommunityConstants { + + public static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 9001; + public static final int PERMISSIONS_REQUEST_ENABLE_GPS = 9002; + public static final int ERROR_DIALOG_REQUEST = 9003; + public static final String MAPVIEW_BUNDLE_KEY = "MapViewBundleKey"; + public static final int MAP_LAYOUT_STATE_CONTRACTED = 0; + public static final int MAP_LAYOUT_STATE_EXPANDED = 1; + public static final int REQUEST_CALL = 1; + public static final long LOCATION_UPDATE_INTERVAL = 3000; + public static final long UPDATE_INTERVAL = 3000; + public static final long FASTEST_INTERVAL = 3000; + public static final int DEFAULT_ZOOM = 10; + public static final String INITIAL_LOCATION_BROADCAST = "initial_location_broadcast"; +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/LogUtils.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/LogUtils.java new file mode 100644 index 0000000..686b34b --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/LogUtils.java @@ -0,0 +1,57 @@ +package com.ichangemycity.ichangemycommunity.utils; + +import com.ichangemycity.ichangemycommunity.AppConfig; + +public class LogUtils { + + public static String makeLogTag(Class cls) + { + return cls.getSimpleName(); + } + + + public static void debug(String tag, String text) { + if (tag == null) { + tag = AppConfig.getDefaultLogTag(); + } + if (AppConfig.isLogEnabled()) + android.util.Log.d(tag, text); + } + + public static void error(String tag, String text) { + if (tag == null) { + tag = AppConfig.getDefaultLogTag(); + } + if (AppConfig.isLogEnabled()) + android.util.Log.e(tag, text); + } + + public static void info(String tag, String text) { + if (tag == null) { + tag = AppConfig.getDefaultLogTag(); + } + if (AppConfig.isLogEnabled()) + android.util.Log.i(tag, text); + } + + public static void debug(String text) { + if (AppConfig.isLogEnabled()) + android.util.Log.d(AppConfig.getDefaultLogTag(), text); + } + + public static void error(String text) { + if (AppConfig.isLogEnabled()) + android.util.Log.e(AppConfig.getDefaultLogTag(), text); + } + + public static void info(String text) { + if (AppConfig.isLogEnabled()) + android.util.Log.i(AppConfig.getDefaultLogTag(), text); + } + + public static void warning(String tag, String s) { + if (AppConfig.isLogEnabled()) + android.util.Log.w(tag, s); + } +} + diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/PushNotificationsUtil.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/PushNotificationsUtil.java new file mode 100644 index 0000000..cae64ac --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/PushNotificationsUtil.java @@ -0,0 +1,26 @@ +package com.ichangemycity.ichangemycommunity.utils; + +import android.content.Context; +import android.os.Bundle; +import android.util.Log; + +import com.ichangemycity.ichangemycommunity.utils.map.UserClient; + +public class PushNotificationsUtil { + + public static final String TAG = PushNotificationsUtil.class.getSimpleName(); + private UserClient userClient; + + public PushNotificationsUtil(Context context) { + userClient = (UserClient) context.getApplicationContext(); + } + + public void configureNotificationActions(Bundle bundle) { + Log.d(TAG, "configureNotificationActions: " + bundle); + String identifier = String.valueOf(bundle.get("identifier")); + + switch (identifier) { + default: + } + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/SharedPreferenceUtils.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/SharedPreferenceUtils.java new file mode 100644 index 0000000..3d561e3 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/SharedPreferenceUtils.java @@ -0,0 +1,119 @@ +package com.ichangemycity.ichangemycommunity.utils; + +import android.content.SharedPreferences; + +import com.ichangemycity.ichangemycommunity.AppMain; + +import static android.os.Build.VERSION.SDK_INT; +import static android.os.Build.VERSION_CODES.GINGERBREAD; + +public class SharedPreferenceUtils { + private static SharedPreferenceUtils mInstance; + static SharedPreferences mSharedPreferences; + private static String defaultValue = ""; + + + private static SharedPreferences getSharedPref() { + mSharedPreferences = AppMain.getSharedPreferences(); + return mSharedPreferences; + + } + + public static String getStringValue(String key) { + mSharedPreferences = getSharedPref(); + String value = mSharedPreferences.getString(key, defaultValue); + return value; + } + + public static String getStringValue(String key, String defValue) { + mSharedPreferences = getSharedPref(); + String value = mSharedPreferences.getString(key, defValue); + return value; + } + + public static void putStringValue(String key, String value) { + mSharedPreferences = getSharedPref(); + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putString(key, value); + save(editor); + } + + private static long getLongValue(String key, long defValue) { + + mSharedPreferences = getSharedPref(); + long value = mSharedPreferences.getLong(key, defValue); + return value; + } + + private static void putLongValue(String key, long value) { + mSharedPreferences = getSharedPref(); + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putLong(key, value); + save(editor); + } + + private static void putBooleanValue(String key, boolean value) { + mSharedPreferences = getSharedPref(); + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putBoolean(key, value); + save(editor); + } + + private static boolean getBooleanValue(String key) { + + mSharedPreferences = getSharedPref(); + boolean result = mSharedPreferences.getBoolean(key, false); + return result; + } + + private static boolean getBooleanValue(String key, boolean defValue) { + + mSharedPreferences = getSharedPref(); + boolean result = mSharedPreferences.getBoolean(key, defValue); + return result; + } + + private static int getIntValue(String key) { + + mSharedPreferences = getSharedPref(); + int result = mSharedPreferences.getInt(key, 0); + return result; + } + + private static void putIntValue(String key, int value) { + mSharedPreferences = getSharedPref(); + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.putInt(key, value); + save(editor); + } + + private static void removeKey(String key) { + mSharedPreferences = getSharedPref(); + SharedPreferences.Editor editor = mSharedPreferences.edit(); + editor.remove(key); + save(editor); + } + + private static boolean isEditorApplyAvailable() { + return SDK_INT >= GINGERBREAD; + } + + /** + * Save preferences in given editor + * + * @param editor + */ + private static void save(final SharedPreferences.Editor editor) { + /*commit() writes the data synchronously (blocking the thread its called from). + It then informs you about the success of the operation. + + apply() schedules the data to be written asynchronously. + It does not inform you about the success of the operation.*/ + + if (isEditorApplyAvailable()) + editor.apply(); + else + editor.commit(); + } + +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/camera/CameraUtils.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/camera/CameraUtils.java new file mode 100644 index 0000000..8e21846 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/camera/CameraUtils.java @@ -0,0 +1,83 @@ +package com.ichangemycity.ichangemycommunity.utils.camera; + +import android.Manifest; +import android.app.Activity; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Environment; +import android.util.Log; + +import androidx.annotation.RequiresApi; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import com.ichangemycity.ichangemycommunity.R; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Locale; + +public class CameraUtils { + + static final int REQUEST_CODE_PERMISSIONS = 10; + static final int REQUEST_EXTERNAL_STORAGE = 1; + static String[] PERMISSIONS_STORAGE = { + Manifest.permission.READ_EXTERNAL_STORAGE, + Manifest.permission.WRITE_EXTERNAL_STORAGE + }; + + static final double RATIO_4_3_VALUE = 4.0 / 3.0; + static final double RATIO_16_9_VALUE = 16.0 / 9.0; + static final String CAMERA_PERMISSIONS[] = {Manifest.permission.CAMERA}; + + public boolean isCameraPermissionGranted(Activity context) { + return ContextCompat.checkSelfPermission(context, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED; + } + + public void requestCameraPermission(Activity context) { + ActivityCompat.requestPermissions( + context, CAMERA_PERMISSIONS, REQUEST_CODE_PERMISSIONS); + } + + public void verifyStoragePermissions(Activity activity) { + int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); + + if (permission != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions( + activity, + PERMISSIONS_STORAGE, + REQUEST_EXTERNAL_STORAGE + ); + } + } + + public File createFile(File baseFolder, String format, String extension) { + return new File(baseFolder, new SimpleDateFormat(format, Locale.US).format(System.currentTimeMillis()) + extension); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + public File getOutputDirectory(Context context) { + + Context appContext = context.getApplicationContext(); + String fileName = String.valueOf(System.currentTimeMillis()) + ".jpg"; + File mediaStorageDir = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), appContext.getResources().getString(R.string.app_name)); + + // Create the storage directory if it does not exist + if (!mediaStorageDir.exists() && !mediaStorageDir.mkdirs()){ + Log.d("APP_TAG", "failed to create directory"); + } + + // Return the file target for the photo based on filename + File file = new File(mediaStorageDir.getPath() + File.separator + fileName); + + return file; + /*Context appContext = context.getApplicationContext(); + File[] mediaDir = context.getExternalMediaDirs(); + if (mediaDir != null) { + File file = new File(mediaDir[0], appContext.getResources().getString(R.string.app_name)); + return file; + } + return appContext.getFilesDir();*/ + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/ClusterManagerRenderer.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/ClusterManagerRenderer.java new file mode 100644 index 0000000..45aab08 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/ClusterManagerRenderer.java @@ -0,0 +1,51 @@ +package com.ichangemycity.ichangemycommunity.utils.map; + +import android.content.Context; +import android.graphics.Bitmap; +import android.util.Log; +import android.view.ViewGroup; +import android.widget.ImageView; + +import androidx.annotation.NonNull; + +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.model.BitmapDescriptorFactory; +import com.google.android.gms.maps.model.MarkerOptions; +import com.google.maps.android.clustering.Cluster; +import com.google.maps.android.clustering.ClusterManager; +import com.google.maps.android.clustering.view.DefaultClusterRenderer; +import com.google.maps.android.ui.IconGenerator; +import com.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.model.ClusterMarker; + +public class ClusterManagerRenderer extends DefaultClusterRenderer { + + private final IconGenerator iconGenerator; + private final ImageView imageView; + private int markerWidth; + private int markerHeight; + + public ClusterManagerRenderer(Context context, GoogleMap map, ClusterManager clusterManager) { + super(context, map, clusterManager); + + iconGenerator = new IconGenerator(context.getApplicationContext()); + imageView = new ImageView(context.getApplicationContext()); + markerWidth = (int) context.getResources().getDimension(R.dimen.custom_marker_image); + markerHeight = (int) context.getResources().getDimension(R.dimen.custom_marker_image); + imageView.setLayoutParams(new ViewGroup.LayoutParams(markerWidth, markerHeight)); + int padding = (int) context.getResources().getDimension(R.dimen.custom_marker_padding); + imageView.setPadding(padding, padding, padding, padding); + iconGenerator.setContentView(imageView); + } + + @Override + protected void onBeforeClusterItemRendered(@NonNull ClusterMarker item, @NonNull MarkerOptions markerOptions) { +// Bitmap icon = iconGenerator.makeIcon(); + markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_YELLOW)).snippet(item.getSnippet()); + } + + @Override + protected boolean shouldRenderAsCluster(@NonNull Cluster cluster) { + return false; + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/MapInputContainerEnum.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/MapInputContainerEnum.java new file mode 100644 index 0000000..f22a364 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/MapInputContainerEnum.java @@ -0,0 +1,17 @@ +package com.ichangemycity.ichangemycommunity.utils.map; + +import java.io.Serializable; + +public enum MapInputContainerEnum implements Serializable { + + LoaderFragment, + SurveyCategoryFragment, + WalkabilityFragment, + VisibilityFragment, + DrivabilityFragment, + SurveyFormFragment, + CameraFragment, + LuminosityFragment, + LuminosityProgressFragment, + Unknown; +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/MapUtils.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/MapUtils.java new file mode 100644 index 0000000..4cb8959 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/MapUtils.java @@ -0,0 +1,49 @@ +package com.ichangemycity.ichangemycommunity.utils.map; + +import android.animation.ObjectAnimator; +import android.widget.FrameLayout; + +public class MapUtils { + + private static final int interval = 800; + + public void expandMapAnimation(FrameLayout mMapViewContainer, int mMapOldSize, int mMapNewSize, + FrameLayout mInputViewContainer, int mTextOldSize, int mTextNewSize) { + ViewWeightAnimationWrapper mapAnimationWrapper = new ViewWeightAnimationWrapper(mMapViewContainer); + ObjectAnimator mapAnimation = ObjectAnimator.ofFloat(mapAnimationWrapper, + "weight", + mMapOldSize, + mMapNewSize); + mapAnimation.setDuration(interval); + + ViewWeightAnimationWrapper textAnimationWrapper = new ViewWeightAnimationWrapper(mInputViewContainer); + ObjectAnimator textAnimation = ObjectAnimator.ofFloat(textAnimationWrapper, + "weight", + mTextOldSize, + mTextNewSize); + textAnimation.setDuration(interval); + + textAnimation.start(); + mapAnimation.start(); + } + + public void contractMapAnimation(FrameLayout mMapViewContainer, int mMapOldSize, int mMapNewSize, + FrameLayout mInputViewContainer, int mTextOldSize, int mTextNewSize) { + ViewWeightAnimationWrapper mapAnimationWrapper = new ViewWeightAnimationWrapper(mMapViewContainer); + ObjectAnimator mapAnimation = ObjectAnimator.ofFloat(mapAnimationWrapper, + "weight", + mMapOldSize, + mMapNewSize); + mapAnimation.setDuration(interval); + + ViewWeightAnimationWrapper textAnimationWrapper = new ViewWeightAnimationWrapper(mInputViewContainer); + ObjectAnimator textAnimation = ObjectAnimator.ofFloat(textAnimationWrapper, + "weight", + mTextOldSize, + mTextNewSize); + textAnimation.setDuration(interval); + + textAnimation.start(); + mapAnimation.start(); + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/SurveyDropDownEnum.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/SurveyDropDownEnum.java new file mode 100644 index 0000000..206b62c --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/SurveyDropDownEnum.java @@ -0,0 +1,11 @@ +package com.ichangemycity.ichangemycommunity.utils.map; + +import java.io.Serializable; + +public enum SurveyDropDownEnum implements Serializable { + + Walkability, + Visibility, + Drivability, + Luminosity +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/UserClient.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/UserClient.java new file mode 100644 index 0000000..d00fb37 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/UserClient.java @@ -0,0 +1,199 @@ +package com.ichangemycity.ichangemycommunity.utils.map; + +import android.app.Application; +import android.os.Bundle; +import android.util.Log; + +import com.google.android.gms.maps.model.LatLng; +import com.ichangemycity.ichangemycommunity.R; +import com.ichangemycity.ichangemycommunity.model.Survey; +import com.ichangemycity.ichangemycommunity.model.User; + +import java.sql.Timestamp; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class UserClient extends Application { + + private static final String TAG = UserClient.class.getSimpleName(); + private LatLng userLatLng; + private boolean isInitialBroadcast = true; + private MapInputContainerEnum mapInputContainerEnum; + private Bundle bundle; + private Map> surveyMap = new HashMap<>(); + private List surveyDropDownList = new ArrayList<>(); + private Survey survey; + private User user; + + public MapInputContainerEnum getMapInputContainerEnum() { + return mapInputContainerEnum; + } + + public Bundle getBundle(){ + return bundle; + } + + // Retrieve user details from db, mocked driver details are fetched below + public User fetchUser() { + user = new User("Citizen", true, "Citizen", "citizen@gmail.com", "1234567890", R.drawable.ic_driver_pin, 4.5, null, getCurrentTimeStamp()); + fetchSurveyMap(); + fetchSurveyDropDownList(); + return user; + } + + private void fetchSurveyMap() { + List category1 = new ArrayList<>(); + category1.add(new Survey("001", 1, "Bangalore", "Kariyammana Agrahara, Bellandur", new LatLng(12.9360, 77.6808), SurveyDropDownEnum.Walkability, "Broken footpath", "60", "20m")); + category1.add(new Survey("002", 2, "Bangalore", "RMZ Eco Space, Bellandur", new LatLng(12.9275, 77.6810), SurveyDropDownEnum.Walkability, "Obstacles", "40", "35m")); + category1.add(new Survey("005", 5, "Bangalore", "BTM Layout 2nd Stage", new LatLng(12.9166, 77.6101), SurveyDropDownEnum.Walkability, "Encroachment", "30", "100m")); + category1.add(new Survey("007", 7, "Bangalore", "New Horizon Gurukul, Kadubeesanahalli", new LatLng(12.9340, 77.6977), SurveyDropDownEnum.Walkability, "Obstacles", "60", "42m")); + + List category2 = new ArrayList<>(); + category2.add(new Survey("003", 3, "Bangalore", "RGA Tech Park, Bellandur", new LatLng(12.9009, 77.7072), SurveyDropDownEnum.Visibility, "Luminosity", "50", "")); + category2.add(new Survey("004", 4, "Bangalore", "Carmelmaram Railway Station, Bellandur", new LatLng(12.9072, 77.7054), SurveyDropDownEnum.Visibility, "Obstacles", "50", "")); + + List category3 = new ArrayList<>(); + category3.add(new Survey("006", 6, "Bangalore", "Kadubeesanahalli", new LatLng(12.9394, 77.6952), SurveyDropDownEnum.Drivability, "Speed breakers", "60", "")); + category3.add(new Survey("008", 8, "Bangalore", "BTM Layout 2nd Stage", new LatLng(12.9083, 77.6051), SurveyDropDownEnum.Drivability, "Obstacles", "60", "")); + category3.add(new Survey("009", 9, "Bangalore", "Gear School, Bellandur", new LatLng(12.9183, 77.6976), SurveyDropDownEnum.Drivability, "Potholes", "60", "")); + + surveyMap.put(SurveyDropDownEnum.Walkability, category1); + surveyMap.put(SurveyDropDownEnum.Visibility, category2); + surveyMap.put(SurveyDropDownEnum.Drivability, category3); + } + + private void fetchSurveyDropDownList() { + surveyDropDownList.clear(); + surveyDropDownList.add(0, "View all surveys"); + surveyDropDownList.add(1, SurveyDropDownEnum.Walkability.toString()); + surveyDropDownList.add(2, SurveyDropDownEnum.Visibility.toString()); + surveyDropDownList.add(3, SurveyDropDownEnum.Drivability.toString()); + } + + public User getUserDetails() { + return user; + } + + public void setMapInputContainerEnum(MapInputContainerEnum mapInputContainerEnum) { + this.mapInputContainerEnum = mapInputContainerEnum; + } + + public void setBundle(Bundle bundle) { + this.bundle = bundle; + } + + public String getCurrentTimeStamp() { + Timestamp timestamp = new Timestamp(System.currentTimeMillis()); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss"); + return sdf.format(timestamp); + } + + // N/W call Save user location + public void saveUserLocation(double lat, double lng) { + fetchUser(); + userLatLng = new LatLng(lat, lng); + user.setLiveLocation(getLiveAddress(userLatLng)); + user.setTimeStamp(getCurrentTimeStamp()); + } + + private String getLiveAddress(LatLng latLng) { +// String address = ""; +// Geocoder geocoder = new Geocoder(getApplicationContext()); +// List
addresses = new ArrayList<>(); +// try { +// addresses = geocoder.getFromLocation(latLng.latitude, latLng.longitude, 1); +// } catch (IOException e) { +// Log.d(TAG, "Exception while getting address from LatLng"); +// } +// if (addresses.size() > 0) { +// address = addresses.get(0).toString(); +// Log.d(TAG, "address from LatLng: " + address); +// } + return getGeoCoder(latLng); + } + + private Map getGeoCoder2() { + Map map = new HashMap<>(); + map.put("Kariyammana Agrahara, Bellandur", new LatLng(12.9360, 77.6808)); + map.put("RMZ Eco Space, Bellandur", new LatLng(12.9275, 77.6810)); + map.put("RGA Tech Park, Bellandur", new LatLng(12.9009, 77.7072)); + map.put("Carmelmaram Railway Station, Bellandur", new LatLng(12.9072, 77.7054)); + map.put("BTM Layout 2nd Stage", new LatLng(12.9166, 77.6101)); + map.put("Kadubeesanahalli", new LatLng(12.9394, 77.6952)); + map.put("New Horizon Gurukul, Kadubeesanahalli", new LatLng(12.9340, 77.6977)); + map.put("BTM Layout 2nd Stage", new LatLng(12.9083, 77.6051)); + map.put("Gear School, Bellandur", new LatLng(12.9183, 77.6976)); + return map; + } + + private String getGeoCoder(LatLng latLng) { + Map map = new HashMap<>(); + map.put(new LatLng(12.9360, 77.6808), "Kariyammana Agrahara, Bellandur"); + map.put(new LatLng(12.9275, 77.6810), "RMZ Eco Space, Bellandur"); + map.put(new LatLng(12.9009, 77.7072), "RGA Tech Park, Bellandur"); + map.put(new LatLng(12.90733, 77.7058517), "Karmelmaram Railway Station, Bellandur"); + map.put(new LatLng(12.9166, 77.6101), "BTM Layout 2nd Stage"); + map.put(new LatLng(12.9394, 77.6952), "Kadubeesanahalli"); + map.put(new LatLng(12.9340, 77.6977), "New Horizon Gurukul, Kadubeesanahalli"); + map.put(new LatLng(12.9083, 77.6051), "BTM Layout 2nd Stage"); + map.put(new LatLng(12.9183, 77.6976), "Gear School, Bellandur"); + return map.get(latLng); + } + + public LatLng getUserLatLng() { + return userLatLng; + } + + public boolean isInitialLocationBroadcast() { + return isInitialBroadcast; + } + + /* Start Driver Trip Summary Screen */ + // N/W call to rate trip + public void rateTrip(String rating, String comments) { + // Do Nothing + } + + public void setInitialLocationBroadcast(boolean flag) { + isInitialBroadcast = flag; + } + + public List getSurveyDropDownList() { + Log.d("", "size: + surveyDropDownList.size()"); + return surveyDropDownList; + } + + public List getSurveyList() { + List surveyList = new ArrayList<>(); + surveyList.addAll(surveyMap.get(SurveyDropDownEnum.Walkability)); + surveyList.addAll(surveyMap.get(SurveyDropDownEnum.Visibility)); + surveyList.addAll(surveyMap.get(SurveyDropDownEnum.Drivability)); + return surveyList; + } + + public List filterSurveyList(String key) { + if (key.equals("View all surveys")) { + return getSurveyList(); + } + return surveyMap.get(SurveyDropDownEnum.valueOf(SurveyDropDownEnum.class, key)); + } + + public void createSurvey() { + survey = new Survey(); + } + + public void setSurveyCategory(SurveyDropDownEnum category) { + survey.setCategory(category); + } + + public void submitSurvey(String subCategory, String start, String end, String qualityScore) { + survey.setSubCategory(subCategory); + survey.setQualityScore(qualityScore); + survey.setDistance("35m"); + surveyMap.get(survey.getCategory()).add(survey); + Log.d("", "" + surveyMap.size()); + } +} diff --git a/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/ViewWeightAnimationWrapper.java b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/ViewWeightAnimationWrapper.java new file mode 100644 index 0000000..4ff69f0 --- /dev/null +++ b/app/src/main/java/com/ichangemycity/ichangemycommunity/utils/map/ViewWeightAnimationWrapper.java @@ -0,0 +1,27 @@ +package com.ichangemycity.ichangemycommunity.utils.map; + +import android.view.View; +import android.widget.LinearLayout; + +// Used to expand or contract Map View +public class ViewWeightAnimationWrapper { + private View view; + + public ViewWeightAnimationWrapper(View view) { + if (view.getLayoutParams() instanceof LinearLayout.LayoutParams) { + this.view = view; + } else { + throw new IllegalArgumentException("The view should have LinearLayout as parent"); + } + } + + public void setWeight(float weight) { + LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams(); + params.weight = weight; + view.getParent().requestLayout(); + } + + public float getWeight() { + return ((LinearLayout.LayoutParams) view.getLayoutParams()).weight; + } +} diff --git a/app/src/main/res/drawable-anydpi/bg_rounded_highlighted_edittext.xml b/app/src/main/res/drawable-anydpi/bg_rounded_highlighted_edittext.xml new file mode 100644 index 0000000..037d605 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/bg_rounded_highlighted_edittext.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-anydpi/blue_border_off.xml b/app/src/main/res/drawable-anydpi/blue_border_off.xml new file mode 100644 index 0000000..e6bc3df --- /dev/null +++ b/app/src/main/res/drawable-anydpi/blue_border_off.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-anydpi/blue_border_on.xml b/app/src/main/res/drawable-anydpi/blue_border_on.xml new file mode 100644 index 0000000..cd8f042 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/blue_border_on.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-anydpi/ic_full_screen.xml b/app/src/main/res/drawable-anydpi/ic_full_screen.xml new file mode 100644 index 0000000..96be652 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_full_screen.xml @@ -0,0 +1,14 @@ + + + + + diff --git a/app/src/main/res/drawable-anydpi/ic_locate.xml b/app/src/main/res/drawable-anydpi/ic_locate.xml new file mode 100644 index 0000000..96690ad --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_locate.xml @@ -0,0 +1,14 @@ + + + + + diff --git a/app/src/main/res/drawable-anydpi/ic_survey.xml b/app/src/main/res/drawable-anydpi/ic_survey.xml new file mode 100644 index 0000000..e977e20 --- /dev/null +++ b/app/src/main/res/drawable-anydpi/ic_survey.xml @@ -0,0 +1,16 @@ + + + + + diff --git a/app/src/main/res/drawable-anydpi/sw_thumb.xml b/app/src/main/res/drawable-anydpi/sw_thumb.xml new file mode 100644 index 0000000..a4e6cfa --- /dev/null +++ b/app/src/main/res/drawable-anydpi/sw_thumb.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-anydpi/sw_track.xml b/app/src/main/res/drawable-anydpi/sw_track.xml new file mode 100644 index 0000000..15f9d1b --- /dev/null +++ b/app/src/main/res/drawable-anydpi/sw_track.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/accept.png b/app/src/main/res/drawable-hdpi/accept.png new file mode 100644 index 0000000..547aaa0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/accept.png differ diff --git a/app/src/main/res/drawable-hdpi/alert.png b/app/src/main/res/drawable-hdpi/alert.png new file mode 100644 index 0000000..4222376 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/alert.png differ diff --git a/app/src/main/res/drawable-hdpi/app_logo.png b/app/src/main/res/drawable-hdpi/app_logo.png new file mode 100644 index 0000000..ad3d85d Binary files /dev/null and b/app/src/main/res/drawable-hdpi/app_logo.png differ diff --git a/app/src/main/res/drawable-hdpi/call.png b/app/src/main/res/drawable-hdpi/call.png new file mode 100644 index 0000000..bb6a3f1 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/call.png differ diff --git a/app/src/main/res/drawable-hdpi/check.png b/app/src/main/res/drawable-hdpi/check.png new file mode 100644 index 0000000..1d6a6c0 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/check.png differ diff --git a/app/src/main/res/drawable-hdpi/checked.png b/app/src/main/res/drawable-hdpi/checked.png new file mode 100644 index 0000000..468d65f Binary files /dev/null and b/app/src/main/res/drawable-hdpi/checked.png differ diff --git a/app/src/main/res/drawable-hdpi/date.png b/app/src/main/res/drawable-hdpi/date.png new file mode 100644 index 0000000..b44c975 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/date.png differ diff --git a/app/src/main/res/drawable-hdpi/distance.png b/app/src/main/res/drawable-hdpi/distance.png new file mode 100644 index 0000000..103252b Binary files /dev/null and b/app/src/main/res/drawable-hdpi/distance.png differ diff --git a/app/src/main/res/drawable-hdpi/doc_uploaded.png b/app/src/main/res/drawable-hdpi/doc_uploaded.png new file mode 100644 index 0000000..f52dfc8 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/doc_uploaded.png differ diff --git a/app/src/main/res/drawable-hdpi/duration.png b/app/src/main/res/drawable-hdpi/duration.png new file mode 100644 index 0000000..3a41ead Binary files /dev/null and b/app/src/main/res/drawable-hdpi/duration.png differ diff --git a/app/src/main/res/drawable-hdpi/earnings.png b/app/src/main/res/drawable-hdpi/earnings.png new file mode 100644 index 0000000..408e646 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/earnings.png differ diff --git a/app/src/main/res/drawable-hdpi/find.png b/app/src/main/res/drawable-hdpi/find.png new file mode 100644 index 0000000..235cea1 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/find.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_locate.png b/app/src/main/res/drawable-hdpi/ic_locate.png new file mode 100644 index 0000000..9497f19 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_locate.png differ diff --git a/app/src/main/res/drawable-hdpi/ic_survey.png b/app/src/main/res/drawable-hdpi/ic_survey.png new file mode 100644 index 0000000..658bacc Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_survey.png differ diff --git a/app/src/main/res/drawable-hdpi/menu.png b/app/src/main/res/drawable-hdpi/menu.png new file mode 100644 index 0000000..3bf1873 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/menu.png differ diff --git a/app/src/main/res/drawable-hdpi/navigate.png b/app/src/main/res/drawable-hdpi/navigate.png new file mode 100644 index 0000000..35d4df3 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/navigate.png differ diff --git a/app/src/main/res/drawable-hdpi/profile.png b/app/src/main/res/drawable-hdpi/profile.png new file mode 100644 index 0000000..4859a1f Binary files /dev/null and b/app/src/main/res/drawable-hdpi/profile.png differ diff --git a/app/src/main/res/drawable-hdpi/reject.png b/app/src/main/res/drawable-hdpi/reject.png new file mode 100644 index 0000000..ce79e4f Binary files /dev/null and b/app/src/main/res/drawable-hdpi/reject.png differ diff --git a/app/src/main/res/drawable-hdpi/request.png b/app/src/main/res/drawable-hdpi/request.png new file mode 100644 index 0000000..987fa76 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/request.png differ diff --git a/app/src/main/res/drawable-hdpi/rides.png b/app/src/main/res/drawable-hdpi/rides.png new file mode 100644 index 0000000..fc72697 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/rides.png differ diff --git a/app/src/main/res/drawable-hdpi/star.png b/app/src/main/res/drawable-hdpi/star.png new file mode 100644 index 0000000..d8eb021 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/star.png differ diff --git a/app/src/main/res/drawable-hdpi/star_.png b/app/src/main/res/drawable-hdpi/star_.png new file mode 100644 index 0000000..36e3f96 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/star_.png differ diff --git a/app/src/main/res/drawable-hdpi/start.png b/app/src/main/res/drawable-hdpi/start.png new file mode 100644 index 0000000..f639498 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/start.png differ diff --git a/app/src/main/res/drawable-hdpi/switch_off.png b/app/src/main/res/drawable-hdpi/switch_off.png new file mode 100644 index 0000000..72ff242 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/switch_off.png differ diff --git a/app/src/main/res/drawable-hdpi/switch_on.png b/app/src/main/res/drawable-hdpi/switch_on.png new file mode 100644 index 0000000..b952bfe Binary files /dev/null and b/app/src/main/res/drawable-hdpi/switch_on.png differ diff --git a/app/src/main/res/drawable-mdpi/accept.png b/app/src/main/res/drawable-mdpi/accept.png new file mode 100644 index 0000000..327d709 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/accept.png differ diff --git a/app/src/main/res/drawable-mdpi/alert.png b/app/src/main/res/drawable-mdpi/alert.png new file mode 100644 index 0000000..d39b9fa Binary files /dev/null and b/app/src/main/res/drawable-mdpi/alert.png differ diff --git a/app/src/main/res/drawable-mdpi/app_logo.png b/app/src/main/res/drawable-mdpi/app_logo.png new file mode 100644 index 0000000..c1ce87a Binary files /dev/null and b/app/src/main/res/drawable-mdpi/app_logo.png differ diff --git a/app/src/main/res/drawable-mdpi/call.png b/app/src/main/res/drawable-mdpi/call.png new file mode 100644 index 0000000..074aeac Binary files /dev/null and b/app/src/main/res/drawable-mdpi/call.png differ diff --git a/app/src/main/res/drawable-mdpi/check.png b/app/src/main/res/drawable-mdpi/check.png new file mode 100644 index 0000000..b785148 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/check.png differ diff --git a/app/src/main/res/drawable-mdpi/checked.png b/app/src/main/res/drawable-mdpi/checked.png new file mode 100644 index 0000000..48a1df2 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/checked.png differ diff --git a/app/src/main/res/drawable-mdpi/date.png b/app/src/main/res/drawable-mdpi/date.png new file mode 100644 index 0000000..1c7a3d0 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/date.png differ diff --git a/app/src/main/res/drawable-mdpi/distance.png b/app/src/main/res/drawable-mdpi/distance.png new file mode 100644 index 0000000..b9c22da Binary files /dev/null and b/app/src/main/res/drawable-mdpi/distance.png differ diff --git a/app/src/main/res/drawable-mdpi/doc_uploaded.png b/app/src/main/res/drawable-mdpi/doc_uploaded.png new file mode 100644 index 0000000..7c077a4 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/doc_uploaded.png differ diff --git a/app/src/main/res/drawable-mdpi/duration.png b/app/src/main/res/drawable-mdpi/duration.png new file mode 100644 index 0000000..eb1e4ae Binary files /dev/null and b/app/src/main/res/drawable-mdpi/duration.png differ diff --git a/app/src/main/res/drawable-mdpi/earnings.png b/app/src/main/res/drawable-mdpi/earnings.png new file mode 100644 index 0000000..e636903 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/earnings.png differ diff --git a/app/src/main/res/drawable-mdpi/find.png b/app/src/main/res/drawable-mdpi/find.png new file mode 100644 index 0000000..a09ccc9 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/find.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_locate.png b/app/src/main/res/drawable-mdpi/ic_locate.png new file mode 100644 index 0000000..94a28f1 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_locate.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_survey.png b/app/src/main/res/drawable-mdpi/ic_survey.png new file mode 100644 index 0000000..35fd813 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_survey.png differ diff --git a/app/src/main/res/drawable-mdpi/menu.png b/app/src/main/res/drawable-mdpi/menu.png new file mode 100644 index 0000000..caa015f Binary files /dev/null and b/app/src/main/res/drawable-mdpi/menu.png differ diff --git a/app/src/main/res/drawable-mdpi/navigate.png b/app/src/main/res/drawable-mdpi/navigate.png new file mode 100644 index 0000000..ccfb634 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/navigate.png differ diff --git a/app/src/main/res/drawable-mdpi/profile.png b/app/src/main/res/drawable-mdpi/profile.png new file mode 100644 index 0000000..a3eb6c9 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/profile.png differ diff --git a/app/src/main/res/drawable-mdpi/reject.png b/app/src/main/res/drawable-mdpi/reject.png new file mode 100644 index 0000000..c6ac5ec Binary files /dev/null and b/app/src/main/res/drawable-mdpi/reject.png differ diff --git a/app/src/main/res/drawable-mdpi/request.png b/app/src/main/res/drawable-mdpi/request.png new file mode 100644 index 0000000..d7a8ab5 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/request.png differ diff --git a/app/src/main/res/drawable-mdpi/rides.png b/app/src/main/res/drawable-mdpi/rides.png new file mode 100644 index 0000000..1fc0e9d Binary files /dev/null and b/app/src/main/res/drawable-mdpi/rides.png differ diff --git a/app/src/main/res/drawable-mdpi/star.png b/app/src/main/res/drawable-mdpi/star.png new file mode 100644 index 0000000..eec405a Binary files /dev/null and b/app/src/main/res/drawable-mdpi/star.png differ diff --git a/app/src/main/res/drawable-mdpi/star_.png b/app/src/main/res/drawable-mdpi/star_.png new file mode 100644 index 0000000..eda49c3 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/star_.png differ diff --git a/app/src/main/res/drawable-mdpi/start.png b/app/src/main/res/drawable-mdpi/start.png new file mode 100644 index 0000000..31e8455 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/start.png differ diff --git a/app/src/main/res/drawable-mdpi/switch_off.png b/app/src/main/res/drawable-mdpi/switch_off.png new file mode 100644 index 0000000..fcbc094 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/switch_off.png differ diff --git a/app/src/main/res/drawable-mdpi/switch_on.png b/app/src/main/res/drawable-mdpi/switch_on.png new file mode 100644 index 0000000..e644549 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/switch_on.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..2b068d1 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xhdpi/accept.png b/app/src/main/res/drawable-xhdpi/accept.png new file mode 100644 index 0000000..bbe7e52 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/accept.png differ diff --git a/app/src/main/res/drawable-xhdpi/alert.png b/app/src/main/res/drawable-xhdpi/alert.png new file mode 100644 index 0000000..84e99d4 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/alert.png differ diff --git a/app/src/main/res/drawable-xhdpi/app_logo.png b/app/src/main/res/drawable-xhdpi/app_logo.png new file mode 100644 index 0000000..fb28af3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/app_logo.png differ diff --git a/app/src/main/res/drawable-xhdpi/call.png b/app/src/main/res/drawable-xhdpi/call.png new file mode 100644 index 0000000..89a82e6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/call.png differ diff --git a/app/src/main/res/drawable-xhdpi/check.png b/app/src/main/res/drawable-xhdpi/check.png new file mode 100644 index 0000000..e3eb541 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/check.png differ diff --git a/app/src/main/res/drawable-xhdpi/checked.png b/app/src/main/res/drawable-xhdpi/checked.png new file mode 100644 index 0000000..da76b13 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/checked.png differ diff --git a/app/src/main/res/drawable-xhdpi/date.png b/app/src/main/res/drawable-xhdpi/date.png new file mode 100644 index 0000000..948f80b Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/date.png differ diff --git a/app/src/main/res/drawable-xhdpi/distance.png b/app/src/main/res/drawable-xhdpi/distance.png new file mode 100644 index 0000000..4327a07 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/distance.png differ diff --git a/app/src/main/res/drawable-xhdpi/doc_uploaded.png b/app/src/main/res/drawable-xhdpi/doc_uploaded.png new file mode 100644 index 0000000..3765bf1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/doc_uploaded.png differ diff --git a/app/src/main/res/drawable-xhdpi/duration.png b/app/src/main/res/drawable-xhdpi/duration.png new file mode 100644 index 0000000..2863ea2 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/duration.png differ diff --git a/app/src/main/res/drawable-xhdpi/earnings.png b/app/src/main/res/drawable-xhdpi/earnings.png new file mode 100644 index 0000000..97327e5 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/earnings.png differ diff --git a/app/src/main/res/drawable-xhdpi/find.png b/app/src/main/res/drawable-xhdpi/find.png new file mode 100644 index 0000000..e4ff491 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/find.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_driver_pin.png b/app/src/main/res/drawable-xhdpi/ic_driver_pin.png new file mode 100644 index 0000000..fdbdc0d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_driver_pin.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_locate.png b/app/src/main/res/drawable-xhdpi/ic_locate.png new file mode 100644 index 0000000..7334e8e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_locate.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_rider_pin.png b/app/src/main/res/drawable-xhdpi/ic_rider_pin.png new file mode 100644 index 0000000..eff4198 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_rider_pin.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_survey.png b/app/src/main/res/drawable-xhdpi/ic_survey.png new file mode 100644 index 0000000..aa99837 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_survey.png differ diff --git a/app/src/main/res/drawable-xhdpi/menu.png b/app/src/main/res/drawable-xhdpi/menu.png new file mode 100644 index 0000000..e087899 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/menu.png differ diff --git a/app/src/main/res/drawable-xhdpi/navigate.png b/app/src/main/res/drawable-xhdpi/navigate.png new file mode 100644 index 0000000..d81b3d8 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/navigate.png differ diff --git a/app/src/main/res/drawable-xhdpi/profile.png b/app/src/main/res/drawable-xhdpi/profile.png new file mode 100644 index 0000000..e276b7a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/profile.png differ diff --git a/app/src/main/res/drawable-xhdpi/reject.png b/app/src/main/res/drawable-xhdpi/reject.png new file mode 100644 index 0000000..a478f53 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/reject.png differ diff --git a/app/src/main/res/drawable-xhdpi/request.png b/app/src/main/res/drawable-xhdpi/request.png new file mode 100644 index 0000000..18bec34 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/request.png differ diff --git a/app/src/main/res/drawable-xhdpi/rides.png b/app/src/main/res/drawable-xhdpi/rides.png new file mode 100644 index 0000000..7a3a609 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/rides.png differ diff --git a/app/src/main/res/drawable-xhdpi/star.png b/app/src/main/res/drawable-xhdpi/star.png new file mode 100644 index 0000000..060c75d Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/star.png differ diff --git a/app/src/main/res/drawable-xhdpi/star_.png b/app/src/main/res/drawable-xhdpi/star_.png new file mode 100644 index 0000000..8523ef3 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/star_.png differ diff --git a/app/src/main/res/drawable-xhdpi/start.png b/app/src/main/res/drawable-xhdpi/start.png new file mode 100644 index 0000000..d478ee6 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/start.png differ diff --git a/app/src/main/res/drawable-xhdpi/switch_off.png b/app/src/main/res/drawable-xhdpi/switch_off.png new file mode 100644 index 0000000..699f7c1 Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/switch_off.png differ diff --git a/app/src/main/res/drawable-xhdpi/switch_on.png b/app/src/main/res/drawable-xhdpi/switch_on.png new file mode 100644 index 0000000..84d240c Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/switch_on.png differ diff --git a/app/src/main/res/drawable-xxhdpi/accept.png b/app/src/main/res/drawable-xxhdpi/accept.png new file mode 100644 index 0000000..ab31062 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/accept.png differ diff --git a/app/src/main/res/drawable-xxhdpi/alert.png b/app/src/main/res/drawable-xxhdpi/alert.png new file mode 100644 index 0000000..04ed0be Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/alert.png differ diff --git a/app/src/main/res/drawable-xxhdpi/app_logo.png b/app/src/main/res/drawable-xxhdpi/app_logo.png new file mode 100644 index 0000000..c9d0e39 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/app_logo.png differ diff --git a/app/src/main/res/drawable-xxhdpi/call.png b/app/src/main/res/drawable-xxhdpi/call.png new file mode 100644 index 0000000..25d0772 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/call.png differ diff --git a/app/src/main/res/drawable-xxhdpi/check.png b/app/src/main/res/drawable-xxhdpi/check.png new file mode 100644 index 0000000..78b9fc7 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/check.png differ diff --git a/app/src/main/res/drawable-xxhdpi/checked.png b/app/src/main/res/drawable-xxhdpi/checked.png new file mode 100644 index 0000000..ead9318 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/checked.png differ diff --git a/app/src/main/res/drawable-xxhdpi/date.png b/app/src/main/res/drawable-xxhdpi/date.png new file mode 100644 index 0000000..2050ebd Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/date.png differ diff --git a/app/src/main/res/drawable-xxhdpi/distance.png b/app/src/main/res/drawable-xxhdpi/distance.png new file mode 100644 index 0000000..6fbb80e Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/distance.png differ diff --git a/app/src/main/res/drawable-xxhdpi/doc_uploaded.png b/app/src/main/res/drawable-xxhdpi/doc_uploaded.png new file mode 100644 index 0000000..a6fccab Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/doc_uploaded.png differ diff --git a/app/src/main/res/drawable-xxhdpi/duration.png b/app/src/main/res/drawable-xxhdpi/duration.png new file mode 100644 index 0000000..f356492 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/duration.png differ diff --git a/app/src/main/res/drawable-xxhdpi/earnings.png b/app/src/main/res/drawable-xxhdpi/earnings.png new file mode 100644 index 0000000..9498f04 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/earnings.png differ diff --git a/app/src/main/res/drawable-xxhdpi/find.png b/app/src/main/res/drawable-xxhdpi/find.png new file mode 100644 index 0000000..55e265b Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/find.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_locate.png b/app/src/main/res/drawable-xxhdpi/ic_locate.png new file mode 100644 index 0000000..b871531 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_locate.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_survey.png b/app/src/main/res/drawable-xxhdpi/ic_survey.png new file mode 100644 index 0000000..11f7fa2 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_survey.png differ diff --git a/app/src/main/res/drawable-xxhdpi/menu.png b/app/src/main/res/drawable-xxhdpi/menu.png new file mode 100644 index 0000000..3bcb173 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/menu.png differ diff --git a/app/src/main/res/drawable-xxhdpi/navigate.png b/app/src/main/res/drawable-xxhdpi/navigate.png new file mode 100644 index 0000000..df0fd13 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/navigate.png differ diff --git a/app/src/main/res/drawable-xxhdpi/profile.png b/app/src/main/res/drawable-xxhdpi/profile.png new file mode 100644 index 0000000..d7c5f9c Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/profile.png differ diff --git a/app/src/main/res/drawable-xxhdpi/reject.png b/app/src/main/res/drawable-xxhdpi/reject.png new file mode 100644 index 0000000..65b6d84 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/reject.png differ diff --git a/app/src/main/res/drawable-xxhdpi/request.png b/app/src/main/res/drawable-xxhdpi/request.png new file mode 100644 index 0000000..68ecb81 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/request.png differ diff --git a/app/src/main/res/drawable-xxhdpi/rides.png b/app/src/main/res/drawable-xxhdpi/rides.png new file mode 100644 index 0000000..db67fe4 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/rides.png differ diff --git a/app/src/main/res/drawable-xxhdpi/star.png b/app/src/main/res/drawable-xxhdpi/star.png new file mode 100644 index 0000000..bbd385d Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/star.png differ diff --git a/app/src/main/res/drawable-xxhdpi/star_.png b/app/src/main/res/drawable-xxhdpi/star_.png new file mode 100644 index 0000000..1cc39c8 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/star_.png differ diff --git a/app/src/main/res/drawable-xxhdpi/start.png b/app/src/main/res/drawable-xxhdpi/start.png new file mode 100644 index 0000000..2d053e6 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/start.png differ diff --git a/app/src/main/res/drawable-xxhdpi/switch_off.png b/app/src/main/res/drawable-xxhdpi/switch_off.png new file mode 100644 index 0000000..7386612 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/switch_off.png differ diff --git a/app/src/main/res/drawable-xxhdpi/switch_on.png b/app/src/main/res/drawable-xxhdpi/switch_on.png new file mode 100644 index 0000000..e8b2f5f Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/switch_on.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/accept.png b/app/src/main/res/drawable-xxxhdpi/accept.png new file mode 100644 index 0000000..525668a Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/accept.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/alert.png b/app/src/main/res/drawable-xxxhdpi/alert.png new file mode 100644 index 0000000..f1c50e3 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/alert.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/app_logo.png b/app/src/main/res/drawable-xxxhdpi/app_logo.png new file mode 100644 index 0000000..1a989ba Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/app_logo.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/call.png b/app/src/main/res/drawable-xxxhdpi/call.png new file mode 100644 index 0000000..9d4230d Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/call.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/check.png b/app/src/main/res/drawable-xxxhdpi/check.png new file mode 100644 index 0000000..2861f49 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/check.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/checked.png b/app/src/main/res/drawable-xxxhdpi/checked.png new file mode 100644 index 0000000..066881c Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/checked.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/date.png b/app/src/main/res/drawable-xxxhdpi/date.png new file mode 100644 index 0000000..104fb7a Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/date.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/distance.png b/app/src/main/res/drawable-xxxhdpi/distance.png new file mode 100644 index 0000000..4d7222b Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/distance.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/doc_uploaded.png b/app/src/main/res/drawable-xxxhdpi/doc_uploaded.png new file mode 100644 index 0000000..641a7cc Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/doc_uploaded.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/duration.png b/app/src/main/res/drawable-xxxhdpi/duration.png new file mode 100644 index 0000000..82384bb Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/duration.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/earnings.png b/app/src/main/res/drawable-xxxhdpi/earnings.png new file mode 100644 index 0000000..4d7d8a0 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/earnings.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/find.png b/app/src/main/res/drawable-xxxhdpi/find.png new file mode 100644 index 0000000..345cf53 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/find.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/menu.png b/app/src/main/res/drawable-xxxhdpi/menu.png new file mode 100644 index 0000000..104928c Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/menu.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/navigate.png b/app/src/main/res/drawable-xxxhdpi/navigate.png new file mode 100644 index 0000000..e07491e Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/navigate.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/profile.png b/app/src/main/res/drawable-xxxhdpi/profile.png new file mode 100644 index 0000000..4bc9e52 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/profile.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/reject.png b/app/src/main/res/drawable-xxxhdpi/reject.png new file mode 100644 index 0000000..092727f Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/reject.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/request.png b/app/src/main/res/drawable-xxxhdpi/request.png new file mode 100644 index 0000000..ec59ff0 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/request.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/rides.png b/app/src/main/res/drawable-xxxhdpi/rides.png new file mode 100644 index 0000000..d7b70d8 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/rides.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/star.png b/app/src/main/res/drawable-xxxhdpi/star.png new file mode 100644 index 0000000..9fd6491 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/star.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/star_.png b/app/src/main/res/drawable-xxxhdpi/star_.png new file mode 100644 index 0000000..4929a33 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/star_.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/start.png b/app/src/main/res/drawable-xxxhdpi/start.png new file mode 100644 index 0000000..0a5efb3 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/start.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/switch_off.png b/app/src/main/res/drawable-xxxhdpi/switch_off.png new file mode 100644 index 0000000..efaab26 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/switch_off.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/switch_on.png b/app/src/main/res/drawable-xxxhdpi/switch_on.png new file mode 100644 index 0000000..4ddf6ac Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/switch_on.png differ diff --git a/app/src/main/res/drawable/bg_blue_focused_edittext.xml b/app/src/main/res/drawable/bg_blue_focused_edittext.xml new file mode 100644 index 0000000..d9b0db5 --- /dev/null +++ b/app/src/main/res/drawable/bg_blue_focused_edittext.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/bg_rounded_edittext.xml b/app/src/main/res/drawable/bg_rounded_edittext.xml new file mode 100644 index 0000000..fc8fc09 --- /dev/null +++ b/app/src/main/res/drawable/bg_rounded_edittext.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/doc_uploaded.png b/app/src/main/res/drawable/doc_uploaded.png new file mode 100644 index 0000000..7c077a4 Binary files /dev/null and b/app/src/main/res/drawable/doc_uploaded.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/layerlist.xml b/app/src/main/res/drawable/layerlist.xml new file mode 100644 index 0000000..2d35a4a --- /dev/null +++ b/app/src/main/res/drawable/layerlist.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/loader00.png b/app/src/main/res/drawable/loader00.png new file mode 100755 index 0000000..9fe5353 Binary files /dev/null and b/app/src/main/res/drawable/loader00.png differ diff --git a/app/src/main/res/drawable/loader01.png b/app/src/main/res/drawable/loader01.png new file mode 100755 index 0000000..4b5d3e4 Binary files /dev/null and b/app/src/main/res/drawable/loader01.png differ diff --git a/app/src/main/res/drawable/loader02.png b/app/src/main/res/drawable/loader02.png new file mode 100755 index 0000000..536945e Binary files /dev/null and b/app/src/main/res/drawable/loader02.png differ diff --git a/app/src/main/res/drawable/loader03.png b/app/src/main/res/drawable/loader03.png new file mode 100755 index 0000000..424a135 Binary files /dev/null and b/app/src/main/res/drawable/loader03.png differ diff --git a/app/src/main/res/drawable/loader04.png b/app/src/main/res/drawable/loader04.png new file mode 100755 index 0000000..226e4aa Binary files /dev/null and b/app/src/main/res/drawable/loader04.png differ diff --git a/app/src/main/res/drawable/loader05.png b/app/src/main/res/drawable/loader05.png new file mode 100755 index 0000000..9e1bfaf Binary files /dev/null and b/app/src/main/res/drawable/loader05.png differ diff --git a/app/src/main/res/drawable/loader06.png b/app/src/main/res/drawable/loader06.png new file mode 100755 index 0000000..c8ba1b2 Binary files /dev/null and b/app/src/main/res/drawable/loader06.png differ diff --git a/app/src/main/res/drawable/loader07.png b/app/src/main/res/drawable/loader07.png new file mode 100755 index 0000000..547f076 Binary files /dev/null and b/app/src/main/res/drawable/loader07.png differ diff --git a/app/src/main/res/drawable/loader08.png b/app/src/main/res/drawable/loader08.png new file mode 100755 index 0000000..e264022 Binary files /dev/null and b/app/src/main/res/drawable/loader08.png differ diff --git a/app/src/main/res/drawable/loader09.png b/app/src/main/res/drawable/loader09.png new file mode 100755 index 0000000..39e6b2e Binary files /dev/null and b/app/src/main/res/drawable/loader09.png differ diff --git a/app/src/main/res/drawable/loader10.png b/app/src/main/res/drawable/loader10.png new file mode 100755 index 0000000..9b91a61 Binary files /dev/null and b/app/src/main/res/drawable/loader10.png differ diff --git a/app/src/main/res/drawable/loader11.png b/app/src/main/res/drawable/loader11.png new file mode 100755 index 0000000..1ce6f63 Binary files /dev/null and b/app/src/main/res/drawable/loader11.png differ diff --git a/app/src/main/res/drawable/loader12.png b/app/src/main/res/drawable/loader12.png new file mode 100755 index 0000000..498732c Binary files /dev/null and b/app/src/main/res/drawable/loader12.png differ diff --git a/app/src/main/res/drawable/loader13.png b/app/src/main/res/drawable/loader13.png new file mode 100755 index 0000000..0d11330 Binary files /dev/null and b/app/src/main/res/drawable/loader13.png differ diff --git a/app/src/main/res/drawable/loader14.png b/app/src/main/res/drawable/loader14.png new file mode 100755 index 0000000..ed556e4 Binary files /dev/null and b/app/src/main/res/drawable/loader14.png differ diff --git a/app/src/main/res/drawable/loader15.png b/app/src/main/res/drawable/loader15.png new file mode 100755 index 0000000..80af555 Binary files /dev/null and b/app/src/main/res/drawable/loader15.png differ diff --git a/app/src/main/res/drawable/loader16.png b/app/src/main/res/drawable/loader16.png new file mode 100755 index 0000000..1a44f7e Binary files /dev/null and b/app/src/main/res/drawable/loader16.png differ diff --git a/app/src/main/res/drawable/loader17.png b/app/src/main/res/drawable/loader17.png new file mode 100755 index 0000000..026bebc Binary files /dev/null and b/app/src/main/res/drawable/loader17.png differ diff --git a/app/src/main/res/drawable/loader18.png b/app/src/main/res/drawable/loader18.png new file mode 100755 index 0000000..59b23c5 Binary files /dev/null and b/app/src/main/res/drawable/loader18.png differ diff --git a/app/src/main/res/drawable/loader19.png b/app/src/main/res/drawable/loader19.png new file mode 100755 index 0000000..c93f20b Binary files /dev/null and b/app/src/main/res/drawable/loader19.png differ diff --git a/app/src/main/res/drawable/loader20.png b/app/src/main/res/drawable/loader20.png new file mode 100755 index 0000000..7f589c5 Binary files /dev/null and b/app/src/main/res/drawable/loader20.png differ diff --git a/app/src/main/res/drawable/loader21.png b/app/src/main/res/drawable/loader21.png new file mode 100755 index 0000000..b9b1a5b Binary files /dev/null and b/app/src/main/res/drawable/loader21.png differ diff --git a/app/src/main/res/drawable/loader22.png b/app/src/main/res/drawable/loader22.png new file mode 100755 index 0000000..7f8065e Binary files /dev/null and b/app/src/main/res/drawable/loader22.png differ diff --git a/app/src/main/res/drawable/loader23.png b/app/src/main/res/drawable/loader23.png new file mode 100755 index 0000000..47b782d Binary files /dev/null and b/app/src/main/res/drawable/loader23.png differ diff --git a/app/src/main/res/drawable/loader24.png b/app/src/main/res/drawable/loader24.png new file mode 100755 index 0000000..fdf2a37 Binary files /dev/null and b/app/src/main/res/drawable/loader24.png differ diff --git a/app/src/main/res/drawable/loader25.png b/app/src/main/res/drawable/loader25.png new file mode 100755 index 0000000..73064df Binary files /dev/null and b/app/src/main/res/drawable/loader25.png differ diff --git a/app/src/main/res/drawable/loader26.png b/app/src/main/res/drawable/loader26.png new file mode 100755 index 0000000..f8961b7 Binary files /dev/null and b/app/src/main/res/drawable/loader26.png differ diff --git a/app/src/main/res/drawable/loader27.png b/app/src/main/res/drawable/loader27.png new file mode 100755 index 0000000..15f1cbf Binary files /dev/null and b/app/src/main/res/drawable/loader27.png differ diff --git a/app/src/main/res/drawable/loader28.png b/app/src/main/res/drawable/loader28.png new file mode 100755 index 0000000..fbc6946 Binary files /dev/null and b/app/src/main/res/drawable/loader28.png differ diff --git a/app/src/main/res/drawable/loader29.png b/app/src/main/res/drawable/loader29.png new file mode 100755 index 0000000..7737733 Binary files /dev/null and b/app/src/main/res/drawable/loader29.png differ diff --git a/app/src/main/res/drawable/loader30.png b/app/src/main/res/drawable/loader30.png new file mode 100755 index 0000000..2b0ad46 Binary files /dev/null and b/app/src/main/res/drawable/loader30.png differ diff --git a/app/src/main/res/drawable/loader31.png b/app/src/main/res/drawable/loader31.png new file mode 100755 index 0000000..ea6c1a7 Binary files /dev/null and b/app/src/main/res/drawable/loader31.png differ diff --git a/app/src/main/res/drawable/loader32.png b/app/src/main/res/drawable/loader32.png new file mode 100755 index 0000000..944e901 Binary files /dev/null and b/app/src/main/res/drawable/loader32.png differ diff --git a/app/src/main/res/drawable/loader33.png b/app/src/main/res/drawable/loader33.png new file mode 100755 index 0000000..30e1082 Binary files /dev/null and b/app/src/main/res/drawable/loader33.png differ diff --git a/app/src/main/res/drawable/loader34.png b/app/src/main/res/drawable/loader34.png new file mode 100755 index 0000000..44673f8 Binary files /dev/null and b/app/src/main/res/drawable/loader34.png differ diff --git a/app/src/main/res/drawable/loader35.png b/app/src/main/res/drawable/loader35.png new file mode 100755 index 0000000..7ad7b0e Binary files /dev/null and b/app/src/main/res/drawable/loader35.png differ diff --git a/app/src/main/res/drawable/loader36.png b/app/src/main/res/drawable/loader36.png new file mode 100755 index 0000000..75fd068 Binary files /dev/null and b/app/src/main/res/drawable/loader36.png differ diff --git a/app/src/main/res/drawable/loader37.png b/app/src/main/res/drawable/loader37.png new file mode 100755 index 0000000..e984d1b Binary files /dev/null and b/app/src/main/res/drawable/loader37.png differ diff --git a/app/src/main/res/drawable/loader38.png b/app/src/main/res/drawable/loader38.png new file mode 100755 index 0000000..57aa27c Binary files /dev/null and b/app/src/main/res/drawable/loader38.png differ diff --git a/app/src/main/res/drawable/loader39.png b/app/src/main/res/drawable/loader39.png new file mode 100755 index 0000000..06037dc Binary files /dev/null and b/app/src/main/res/drawable/loader39.png differ diff --git a/app/src/main/res/drawable/loader40.png b/app/src/main/res/drawable/loader40.png new file mode 100755 index 0000000..79c32cb Binary files /dev/null and b/app/src/main/res/drawable/loader40.png differ diff --git a/app/src/main/res/drawable/loader41.png b/app/src/main/res/drawable/loader41.png new file mode 100755 index 0000000..3d75a22 Binary files /dev/null and b/app/src/main/res/drawable/loader41.png differ diff --git a/app/src/main/res/drawable/loader42.png b/app/src/main/res/drawable/loader42.png new file mode 100755 index 0000000..e6bd89b Binary files /dev/null and b/app/src/main/res/drawable/loader42.png differ diff --git a/app/src/main/res/drawable/loader43.png b/app/src/main/res/drawable/loader43.png new file mode 100755 index 0000000..006a29c Binary files /dev/null and b/app/src/main/res/drawable/loader43.png differ diff --git a/app/src/main/res/drawable/loader44.png b/app/src/main/res/drawable/loader44.png new file mode 100755 index 0000000..f8f69f8 Binary files /dev/null and b/app/src/main/res/drawable/loader44.png differ diff --git a/app/src/main/res/drawable/loader45.png b/app/src/main/res/drawable/loader45.png new file mode 100755 index 0000000..200f3bd Binary files /dev/null and b/app/src/main/res/drawable/loader45.png differ diff --git a/app/src/main/res/drawable/loader46.png b/app/src/main/res/drawable/loader46.png new file mode 100755 index 0000000..225859d Binary files /dev/null and b/app/src/main/res/drawable/loader46.png differ diff --git a/app/src/main/res/drawable/loader47.png b/app/src/main/res/drawable/loader47.png new file mode 100755 index 0000000..bd79059 Binary files /dev/null and b/app/src/main/res/drawable/loader47.png differ diff --git a/app/src/main/res/drawable/loader48.png b/app/src/main/res/drawable/loader48.png new file mode 100755 index 0000000..119ff14 Binary files /dev/null and b/app/src/main/res/drawable/loader48.png differ diff --git a/app/src/main/res/drawable/loader49.png b/app/src/main/res/drawable/loader49.png new file mode 100755 index 0000000..f3590df Binary files /dev/null and b/app/src/main/res/drawable/loader49.png differ diff --git a/app/src/main/res/drawable/loader50.png b/app/src/main/res/drawable/loader50.png new file mode 100755 index 0000000..96bd559 Binary files /dev/null and b/app/src/main/res/drawable/loader50.png differ diff --git a/app/src/main/res/drawable/loader51.png b/app/src/main/res/drawable/loader51.png new file mode 100755 index 0000000..cbcb3b8 Binary files /dev/null and b/app/src/main/res/drawable/loader51.png differ diff --git a/app/src/main/res/drawable/loader52.png b/app/src/main/res/drawable/loader52.png new file mode 100755 index 0000000..9f66e57 Binary files /dev/null and b/app/src/main/res/drawable/loader52.png differ diff --git a/app/src/main/res/drawable/loader53.png b/app/src/main/res/drawable/loader53.png new file mode 100755 index 0000000..dacf073 Binary files /dev/null and b/app/src/main/res/drawable/loader53.png differ diff --git a/app/src/main/res/drawable/loader54.png b/app/src/main/res/drawable/loader54.png new file mode 100755 index 0000000..dba0b98 Binary files /dev/null and b/app/src/main/res/drawable/loader54.png differ diff --git a/app/src/main/res/drawable/loader55.png b/app/src/main/res/drawable/loader55.png new file mode 100755 index 0000000..1350d88 Binary files /dev/null and b/app/src/main/res/drawable/loader55.png differ diff --git a/app/src/main/res/drawable/loader56.png b/app/src/main/res/drawable/loader56.png new file mode 100755 index 0000000..de3b228 Binary files /dev/null and b/app/src/main/res/drawable/loader56.png differ diff --git a/app/src/main/res/drawable/loader57.png b/app/src/main/res/drawable/loader57.png new file mode 100755 index 0000000..7b4f02e Binary files /dev/null and b/app/src/main/res/drawable/loader57.png differ diff --git a/app/src/main/res/drawable/loader58.png b/app/src/main/res/drawable/loader58.png new file mode 100755 index 0000000..4efc577 Binary files /dev/null and b/app/src/main/res/drawable/loader58.png differ diff --git a/app/src/main/res/drawable/loader59.png b/app/src/main/res/drawable/loader59.png new file mode 100755 index 0000000..d562e46 Binary files /dev/null and b/app/src/main/res/drawable/loader59.png differ diff --git a/app/src/main/res/drawable/loader_animation.xml b/app/src/main/res/drawable/loader_animation.xml new file mode 100644 index 0000000..c4d42bd --- /dev/null +++ b/app/src/main/res/drawable/loader_animation.xml @@ -0,0 +1,63 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/profilepic.jpeg b/app/src/main/res/drawable/profilepic.jpeg new file mode 100644 index 0000000..b5e9def Binary files /dev/null and b/app/src/main/res/drawable/profilepic.jpeg differ diff --git a/app/src/main/res/drawable/remove.png b/app/src/main/res/drawable/remove.png new file mode 100644 index 0000000..4f79f6f Binary files /dev/null and b/app/src/main/res/drawable/remove.png differ diff --git a/app/src/main/res/drawable/rounded_button_grey.xml b/app/src/main/res/drawable/rounded_button_grey.xml new file mode 100644 index 0000000..5ee0610 --- /dev/null +++ b/app/src/main/res/drawable/rounded_button_grey.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/rounded_button_yellow.xml b/app/src/main/res/drawable/rounded_button_yellow.xml new file mode 100644 index 0000000..0aca962 --- /dev/null +++ b/app/src/main/res/drawable/rounded_button_yellow.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..d38f417 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,33 @@ + + + +