diff --git a/.gradle/5.1.1/executionHistory/executionHistory.bin b/.gradle/5.1.1/executionHistory/executionHistory.bin index 0fd0df10758226afe827100593f0cf9b2db17cf9..5e05b5c83bc039d3a12c4c8285be29f926e7da71 100644 Binary files a/.gradle/5.1.1/executionHistory/executionHistory.bin and b/.gradle/5.1.1/executionHistory/executionHistory.bin differ diff --git a/.gradle/5.1.1/executionHistory/executionHistory.lock b/.gradle/5.1.1/executionHistory/executionHistory.lock index 3d973e887ba3c52c01766f7b43532534ac3808fc..415387e03b87d85c1bc84b7476753c358d65c854 100644 Binary files a/.gradle/5.1.1/executionHistory/executionHistory.lock and b/.gradle/5.1.1/executionHistory/executionHistory.lock differ diff --git a/.gradle/5.1.1/fileHashes/fileHashes.bin b/.gradle/5.1.1/fileHashes/fileHashes.bin index 511e789b5019d85395b1fbe943fb88bca40a2028..dc3300ce8c7bf1a4691599ca3094d263eef1dba8 100644 Binary files a/.gradle/5.1.1/fileHashes/fileHashes.bin and b/.gradle/5.1.1/fileHashes/fileHashes.bin differ diff --git a/.gradle/5.1.1/fileHashes/fileHashes.lock b/.gradle/5.1.1/fileHashes/fileHashes.lock index 9baae47a6e0f89b1581b97321cb1cb84ae131247..f579f487e045ac4a2c83fa3b78138e1f1320bc5c 100644 Binary files a/.gradle/5.1.1/fileHashes/fileHashes.lock and b/.gradle/5.1.1/fileHashes/fileHashes.lock differ diff --git a/.gradle/5.1.1/javaCompile/classAnalysis.bin b/.gradle/5.1.1/javaCompile/classAnalysis.bin index 3cc94942aa6a2f61dca364122e76b37cbd5b53da..2704a597668195e60c7ac17e8d86137fc6c9f2e1 100644 Binary files a/.gradle/5.1.1/javaCompile/classAnalysis.bin and b/.gradle/5.1.1/javaCompile/classAnalysis.bin differ diff --git a/.gradle/5.1.1/javaCompile/javaCompile.lock b/.gradle/5.1.1/javaCompile/javaCompile.lock index 2b116de7a39a75602d86000187b680b6b3e13309..28a4867c4f9c734956fa9f8d33dd400e46222491 100644 Binary files a/.gradle/5.1.1/javaCompile/javaCompile.lock and b/.gradle/5.1.1/javaCompile/javaCompile.lock differ diff --git a/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/.gradle/buildOutputCleanup/buildOutputCleanup.lock index 2166c862a8de26119a24cb73441dd289ac3c319c..ad42a14159328ab70bf9782ca09da85cb41e81d9 100644 Binary files a/.gradle/buildOutputCleanup/buildOutputCleanup.lock and b/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index f44d2e3afff893e053aa6c9aee7625d95745f31a..25a247ee328d7cd72fb4a582899ede84373121d2 100644 Binary files a/.idea/caches/build_file_checksums.ser and b/.idea/caches/build_file_checksums.ser differ diff --git a/.idea/misc.xml b/.idea/misc.xml index f5c6d9eb6a991d73b50e99d55a1a22a208ef247d..0d45e8dac234fb8d8ce72a22fa160d3a6ababc22 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> - <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK" /> + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="1.8" project-jdk-type="JavaSDK" /> </project> \ No newline at end of file diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 35346b66a47287017b79e185d732753bbb905978..ef7e1e7db41448d635a67d70f20ea98999a14968 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -1,13 +1,20 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.liliyayankova.unirides"> + <!-- The ACCESS_COARSE/FINE_LOCATION permissions are not required to use Google Maps Android API v2, but you must specify either coarse or fine location permissions for the 'MyLocation' functionality. --> - <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> + + <!-- + The ACCESS_COARSE/FINE_LOCATION permissions are not required to use + Google Maps Android API v2, but you must specify either coarse or fine + location permissions for the 'MyLocation' functionality. + --> + <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> @@ -28,6 +35,7 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> + <!-- The API key for Google Maps-based APIs is defined as a string resource. (See the file "res/values/google_maps_api.xml"). @@ -40,6 +48,10 @@ android:name="com.google.android.geo.API_KEY" android:value="@string/google_maps_key" /> + <activity + android:name=".PlaceMarker" + android:label="@string/title_activity_place_marker"></activity> + <activity android:name=".SavedRoutes" /> <activity android:name=".Homepage" android:label="@string/app_name" @@ -50,7 +62,8 @@ <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> - <activity android:name=".Offline_Map" + <activity + android:name=".Offline_Map" android:label="@string/offline_map" /> <activity android:name=".Login" @@ -78,7 +91,7 @@ android:screenOrientation="portrait" /> <activity android:name=".Driver_Edit_Profile" - android:label="@string/profile"/> + android:label="@string/profile" /> <activity android:name=".Driver_Profile" android:label="@string/profile" /> diff --git a/src/main/java/com/example/liliyayankova/unirides/Driver_Main.java b/src/main/java/com/example/liliyayankova/unirides/Driver_Main.java index 65046f801e100277adc2796d9d13bd0068f1f065..0e8577f927bc2129303693fa8439fe83292fc0bb 100644 --- a/src/main/java/com/example/liliyayankova/unirides/Driver_Main.java +++ b/src/main/java/com/example/liliyayankova/unirides/Driver_Main.java @@ -48,6 +48,16 @@ public class Driver_Main extends AppCompatActivity { } }); + ImageButton saved_routes_button = findViewById(R.id.saved_routes_button); + saved_routes_button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Intent route_i = new Intent(Driver_Main.this, SavedRoutes.class); + route_i.putExtra("userType", Login.userType.DRIVER); + startActivity(route_i); + } + }); + } //Override for the user_toolbar menu items diff --git a/src/main/java/com/example/liliyayankova/unirides/Homepage.java b/src/main/java/com/example/liliyayankova/unirides/Homepage.java index 6f36676c9ef9dc03c85262b65c4220da6a58cac4..2e56ec156dfd37413d1e5ecda9849d9f37e739c8 100644 --- a/src/main/java/com/example/liliyayankova/unirides/Homepage.java +++ b/src/main/java/com/example/liliyayankova/unirides/Homepage.java @@ -20,6 +20,7 @@ public class Homepage extends AppCompatActivity { private Button login; private Button register; private ImageButton offline_map; + private ImageButton offline_routes; @Override protected void onCreate(Bundle savedInstanceState) { @@ -31,6 +32,7 @@ public class Homepage extends AppCompatActivity { this.login = (Button) findViewById(R.id.loginB); this.register = (Button) findViewById(R.id.registerB); this.offline_map = findViewById(R.id.offline_map); + this.offline_routes = findViewById(R.id.offline_route_button); //setting the user_toolbar layout as the action bar Toolbar toolbar = findViewById(R.id.toolbar); @@ -48,6 +50,15 @@ public class Homepage extends AppCompatActivity { } }); + this.offline_routes.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent route_i = new Intent(Homepage.this, SavedRoutes.class); + route_i.putExtra("userType", Login.userType.NONE); + startActivity(route_i); + } + }); + this.login.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { diff --git a/src/main/java/com/example/liliyayankova/unirides/Login.java b/src/main/java/com/example/liliyayankova/unirides/Login.java index 0b7c3cd9d8b90152d38173ebf7255f29b936545d..544d1cff96ad155679f4a403a03a89ccfd16197c 100644 --- a/src/main/java/com/example/liliyayankova/unirides/Login.java +++ b/src/main/java/com/example/liliyayankova/unirides/Login.java @@ -19,8 +19,13 @@ import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.provider.ContactsContract; +import android.support.v7.widget.Toolbar; import android.text.TextUtils; +import android.util.Log; import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.view.WindowManager; @@ -118,6 +123,14 @@ public class Login extends AppCompatActivity implements LoaderCallbacks<Cursor> } }; + //setting the user_toolbar layout as the action bar + Toolbar toolbar = findViewById(R.id.toolbar); + try { + setSupportActionBar(toolbar); + } catch (Exception e) { + Log.e("TOOLBAR", e.toString()); + } + // Set up the login form. mEmailView = (AutoCompleteTextView) findViewById(R.id.email); populateAutoComplete(); @@ -493,5 +506,30 @@ public class Login extends AppCompatActivity implements LoaderCallbacks<Cursor> showProgress(false); } } + //Override for the user_toolbar menu items + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater menuInflater = getMenuInflater(); + menuInflater.inflate(R.menu.offline_toolbar_menu, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + //checks the id of the item, if the item id matches a case id then the code in that case block will execute + switch(item.getItemId()){ + + case(R.id.item_settings): + + Intent settings_i = new Intent(Login.this, Settings.class); + settings_i.putExtra("userType", Login.userType.NONE); + startActivity(settings_i); + return true; + + } + + return super.onOptionsItemSelected(item); + } } diff --git a/src/main/java/com/example/liliyayankova/unirides/PlaceMarker.java b/src/main/java/com/example/liliyayankova/unirides/PlaceMarker.java new file mode 100644 index 0000000000000000000000000000000000000000..41ac130fa1ceab9bee215e25b3470087f920df47 --- /dev/null +++ b/src/main/java/com/example/liliyayankova/unirides/PlaceMarker.java @@ -0,0 +1,358 @@ +package com.example.liliyayankova.unirides; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.location.Address; +import android.location.Geocoder; +import android.location.Location; +import android.location.LocationManager; +import android.os.Build; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v4.app.ActivityCompat; +import android.os.Bundle; +import android.support.v4.content.ContextCompat; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.widget.Toolbar; +import android.util.Log; +import android.view.KeyEvent; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.View; +import android.view.WindowManager; +import android.view.inputmethod.EditorInfo; +import android.widget.Button; +import android.widget.EditText; +import android.widget.SearchView; +import android.widget.TextView; +import android.widget.Toast; + +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.api.GoogleApiClient; +import com.google.android.gms.location.LocationRequest; +import com.google.android.gms.location.LocationListener; +import com.google.android.gms.location.LocationServices; +import com.google.android.gms.maps.CameraUpdateFactory; +import com.google.android.gms.maps.GoogleMap; +import com.google.android.gms.maps.OnMapReadyCallback; +import com.google.android.gms.maps.SupportMapFragment; +import com.google.android.gms.maps.model.BitmapDescriptorFactory; +import com.google.android.gms.maps.model.LatLng; +import com.google.android.gms.maps.model.Marker; +import com.google.android.gms.maps.model.MarkerOptions; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class PlaceMarker extends AppCompatActivity implements + OnMapReadyCallback, + GoogleApiClient.ConnectionCallbacks, + GoogleApiClient.OnConnectionFailedListener, + LocationListener { + + LocationManager locationManager; + private GoogleMap mMap; + private GoogleApiClient mGoogleApiClient; + private LocationRequest mLocationRequest; + private Location currentLocation; + private Marker myLocation; + private static final int REQUEST_USER_LOCATION_CODE = 99; + + //lat & lng variables + private double lat; + private double lng; + private boolean isStart; + private boolean noValues; + private boolean updatedValues; + + //UI + private Button doneButton; + private EditText searchbar; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_place_marker); + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M){ + checkUserLocationPermission(); + } + // Obtain the SupportMapFragment and get notified when the map is ready to be used. + SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() + .findFragmentById(R.id.map); + mapFragment.getMapAsync(this); + + this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); + + Toast.makeText(PlaceMarker.this, "Hold your finger on the marker to drag it, alternatively you can search for the location using the search bar", Toast.LENGTH_LONG).show(); + + updatedValues = false; + + searchbar = findViewById(R.id.searchbar); + + locationManager = (LocationManager) getSystemService(LOCATION_SERVICE); + + //assume there were no previous lat or lng values until proven otherwise + noValues = true; + + if(getIntent().getExtras() != null){ + if(getIntent().getExtras().get("location").toString().equals("start")) { + isStart = true; + if(!getIntent().getExtras().get("lat_start").toString().equals("") & !updatedValues){ + noValues = false; + lat = Float.parseFloat(getIntent().getExtras().get("lat_start").toString()); + lng = Float.parseFloat(getIntent().getExtras().get("lng_start").toString()); + updatedValues = true; + } + }else{ + isStart = false; + if(!getIntent().getExtras().get("lat_end").toString().equals("") & !updatedValues){ + noValues = false; + lat = Float.parseFloat(getIntent().getExtras().get("lat_end").toString()); + lng = Float.parseFloat(getIntent().getExtras().get("lng_end").toString()); + updatedValues = true; + } + } + } + + searchbar.setOnEditorActionListener(new TextView.OnEditorActionListener() { + @Override + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + + if(actionId == EditorInfo.IME_ACTION_SEARCH + || actionId == EditorInfo.IME_ACTION_DONE + || event.getAction() == KeyEvent.ACTION_DOWN + || event.getAction() == KeyEvent.KEYCODE_ENTER){ + + geoLocate(); + } + + return false; + } + }); + + doneButton = findViewById(R.id.done_button); + doneButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + Intent return_to_route = new Intent(PlaceMarker.this, Route.class); + if(isStart) { + //set the new values for the start location + return_to_route.putExtra("location", "start"); + return_to_route.putExtra("lat_start", lat); + return_to_route.putExtra("lng_start", lng); + + //return the previous values from the route activity + return_to_route.putExtra("lat_end", getIntent().getExtras().get("lat_end").toString()); + return_to_route.putExtra("lng_end", getIntent().getExtras().get("lng_end").toString()); + return_to_route.putExtra("date", getIntent().getExtras().get("date").toString()); + return_to_route.putExtra("time", getIntent().getExtras().get("time").toString()); + return_to_route.putExtra("n_seats", getIntent().getExtras().get("n_seats").toString()); + return_to_route.putExtra("price", getIntent().getExtras().get("price").toString()); + + }else{ + //set the new values for the end location + return_to_route.putExtra("location", "end"); + return_to_route.putExtra("lat_end", lat); + return_to_route.putExtra("lng_end", lng); + + //return the previous values from the route activity + return_to_route.putExtra("lat_start", getIntent().getExtras().get("lat_start").toString()); + return_to_route.putExtra("lng_start", getIntent().getExtras().get("lng_start").toString()); + return_to_route.putExtra("date", getIntent().getExtras().get("date").toString()); + return_to_route.putExtra("time", getIntent().getExtras().get("time").toString()); + return_to_route.putExtra("n_seats", getIntent().getExtras().get("n_seats").toString()); + return_to_route.putExtra("price", getIntent().getExtras().get("price").toString()); + + } + + startActivity(return_to_route); + } + }); + + } + + @Override + public void onMapReady(GoogleMap googleMap) { + mMap = googleMap; + if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) + == PackageManager.PERMISSION_GRANTED) { + + buildGoogleApiClient(); + + mMap.setMyLocationEnabled(true); + } + + mMap.setOnMarkerDragListener(new GoogleMap.OnMarkerDragListener() { + @Override + public void onMarkerDragStart(Marker marker) { + + } + + @Override + public void onMarkerDrag(Marker marker) { + + } + + @Override + public void onMarkerDragEnd(Marker marker) { + lat = myLocation.getPosition().latitude; + lng = myLocation.getPosition().longitude; + } + }); + } + + public boolean checkUserLocationPermission(){ + if(ContextCompat.checkSelfPermission(this, + Manifest.permission.ACCESS_FINE_LOCATION) + != PackageManager.PERMISSION_GRANTED){ + if(ActivityCompat.shouldShowRequestPermissionRationale(this, + Manifest.permission.ACCESS_FINE_LOCATION)){ + ActivityCompat.requestPermissions(this, new String[] + {Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_USER_LOCATION_CODE); + }else{ + ActivityCompat.requestPermissions(this, new String[] + {Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_USER_LOCATION_CODE); + } + return false; + }else{ + return true; + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, + @NonNull int[] grantResults) { + switch (requestCode){ + case REQUEST_USER_LOCATION_CODE: + if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + if (ContextCompat.checkSelfPermission(this, + Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { + if (mGoogleApiClient == null) { + buildGoogleApiClient(); + } + mMap.setMyLocationEnabled(true); + } + }else{ + Toast.makeText(this, "Permission Denied.", Toast.LENGTH_SHORT).show(); + } + return; + } + } + + protected synchronized void buildGoogleApiClient(){ + mGoogleApiClient = new GoogleApiClient.Builder(this) + .addConnectionCallbacks(this) + .addOnConnectionFailedListener(this) + .addApi(LocationServices.API) + .build(); + + mGoogleApiClient.connect(); + } + + @Override + public void onLocationChanged(Location location) { + + if(noValues & !updatedValues) { + + currentLocation = location; + lat = location.getLatitude(); + lng = location.getLongitude(); + + LatLng latLng = new LatLng(lat, lng); + if (isStart) { + moveCamera(latLng, "Start Position"); + } else { + moveCamera(latLng, "End Position"); + } + + updatedValues = true; + + }else{ + + if(myLocation == null) { + LatLng latLng = new LatLng(lat, lng); + + if (isStart) { + moveCamera(latLng, "Start Position"); + } else { + moveCamera(latLng, "End Position"); + } + } + + } + + } + + public void moveCamera(LatLng latLng, String title){ + + if(myLocation != null){ + myLocation.remove(); + } + float zoomLevel = 14.0f; + MarkerOptions markerOptions = new MarkerOptions(); + markerOptions.title(title); + markerOptions.position(latLng); + markerOptions.draggable(true); + markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_CYAN)); + mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, zoomLevel)); + myLocation = mMap.addMarker(markerOptions); + } + + public void geoLocate(){ + String searchtext = searchbar.getText().toString(); + + Geocoder geocoder = new Geocoder(PlaceMarker.this); + List<Address> list = new ArrayList<>(); + try{ + list = geocoder.getFromLocationName(searchtext, 1); + }catch(IOException e){ + e.printStackTrace(); + } + + //if there was a result from the search then get that result + if(list.size() > 0){ + Address address = list.get(0); + lat = address.getLatitude(); + lng = address.getLongitude(); + if(isStart) { + moveCamera(new LatLng(lat,lng), "Start Position"); + }else{ + moveCamera(new LatLng(lat,lng), "End Position"); + } + } + } + + @Override + public void onConnected(@Nullable Bundle bundle) { + + + mLocationRequest = new LocationRequest(); + mLocationRequest.setInterval(1000); + mLocationRequest.setFastestInterval(1000); + mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); + + if (ContextCompat.checkSelfPermission(this, + Manifest.permission.ACCESS_FINE_LOCATION) + == PackageManager.PERMISSION_GRANTED) { + LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, + mLocationRequest, this); + } + + } + + @Override + public void onConnectionSuspended(int i) { + + } + + @Override + public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { + + } + +} diff --git a/src/main/java/com/example/liliyayankova/unirides/Route.java b/src/main/java/com/example/liliyayankova/unirides/Route.java index ae16fbf7d27a2e1e88e4679b2f4de38faacd5b50..057c5165cc0ace16388b8b372fb3492b999626ab 100644 --- a/src/main/java/com/example/liliyayankova/unirides/Route.java +++ b/src/main/java/com/example/liliyayankova/unirides/Route.java @@ -1,11 +1,16 @@ package com.example.liliyayankova.unirides; +import android.Manifest; import android.app.DatePickerDialog; import android.app.Dialog; import android.app.TimePickerDialog; import android.content.Intent; +import android.content.pm.PackageManager; import android.location.LocationManager; +import android.os.Build; +import android.os.Environment; import android.support.annotation.NonNull; +import android.support.annotation.RequiresApi; import android.support.v4.app.DialogFragment; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; @@ -44,9 +49,14 @@ import com.google.firebase.database.DatabaseReference; import com.google.firebase.database.FirebaseDatabase; import com.google.firebase.database.ValueEventListener; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.text.DateFormat; import java.text.DecimalFormat; +import java.text.SimpleDateFormat; import java.util.Calendar; +import java.util.Date; public class Route extends AppCompatActivity implements DatePickerDialog.OnDateSetListener, TimePickerDialog.OnTimeSetListener { @@ -58,11 +68,16 @@ public class Route extends AppCompatActivity implements DatePickerDialog.OnDateS private String n_seats; private String price; + private boolean isDriver; + private boolean isLoggedIn; + //UI elements private Button date_button; private Button time_button; private Button save_route; private Button post_route; + private Button place_marker_start; + private Button place_marker_end; private EditText n_seats_edit; private EditText price_edit; @@ -76,6 +91,12 @@ public class Route extends AppCompatActivity implements DatePickerDialog.OnDateS private TextView date_text; private TextView time_text; + private String[] saveText; + private File storageDir; + private File textFile; + + private final int MY_PERMISSIONS_REQUEST_EXTERNAL_STORAGE = 2; + String userId; long current_val; @@ -120,19 +141,107 @@ public class Route extends AppCompatActivity implements DatePickerDialog.OnDateS date_text = findViewById(R.id.text_date); time_text = findViewById(R.id.text_time); + //initialising values + date = ""; + time = ""; + isLoggedIn = true; + this.firebaseAuth = FirebaseAuth.getInstance(); this.firebaseDatabase = FirebaseDatabase.getInstance(); this.dbReference = firebaseDatabase.getReference(); + storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), "UniRides/Routes"); + + saveText = new String[7]; + + /* checking if there are any bundle extras */ + if(getIntent().getExtras() != null) { + if(getIntent().getExtras().get("route_0") != null){ + + String start_loc = getIntent().getExtras().get("route_0").toString(); + String end_loc = getIntent().getExtras().get("route_1").toString(); + + //converting location string to individual lat lang values + String s1 = ""; + String s2 = ""; + boolean islat = true; + int j = 0; + for(int i = 0; i < start_loc.length(); i++){ + if(start_loc.charAt(i) == ',') { + islat = false; + } + if(islat){ + s1 += start_loc.charAt(i); + }else{ + j++; + } + if(!islat && j > 2){ + s2 += start_loc.charAt(i); + } + } + lat_start.setText(s1); + lng_start.setText(s2); + + s1 = ""; + s2 = ""; + islat = true; + j = 0; + for(int i = 0; i < end_loc.length(); i++){ + if(end_loc.charAt(i) == ',') { + islat = false; + } + if(islat){ + s1 += end_loc.charAt(i); + }else{ + j++; + } + if(!islat && j > 2){ + s2 += end_loc.charAt(i); + } + } + lat_end.setText(s1); + lng_end.setText(s2); + + date = getIntent().getExtras().get("route_2").toString(); + date_text.setText(date); + time = getIntent().getExtras().get("route_3").toString(); + time_text.setText(time); + n_seats_edit.setText((getIntent().getExtras().get("route_4")).toString()); + price_edit.setText((getIntent().getExtras().get("route_5")).toString()); + } + + if(getIntent().getExtras().get("location") != null) { + lat_start.setText(getIntent().getExtras().get("lat_start").toString()); + lat_end.setText(getIntent().getExtras().get("lat_end").toString()); + lng_start.setText(getIntent().getExtras().get("lng_start").toString()); + lng_end.setText(getIntent().getExtras().get("lng_end").toString()); + date = getIntent().getExtras().get("date").toString(); + date_text.setText(date); + time = getIntent().getExtras().get("time").toString(); + time_text.setText(time); + n_seats_edit.setText(getIntent().getExtras().get("n_seats").toString()); + price_edit.setText(getIntent().getExtras().get("price").toString()); + } + + //setting userType to this result (DRIVER or PASSENGER) + if(getIntent().getExtras().get("userType") == Login.userType.DRIVER){ + isDriver = true; + } + + //if coming from the homepage (not signed in) set logged in to false + if(getIntent().getExtras().get("userType") == Login.userType.NONE){ + isLoggedIn = false; + } + } + dbReference.child("routes").addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot dataSnapshot) { - if(dataSnapshot.child("n_of_routes").exists()) { + if(dataSnapshot.getChildrenCount() > 0) { //set current value to the number of routes (using current routes as a route ID) - current_val = (long)dataSnapshot.child("n_of_routes").getValue(); - dbReference.child("routes").child("n_of_routes").setValue(current_val); + current_val = dataSnapshot.getChildrenCount(); + Toast.makeText(Route.this, Long.toString(current_val), Toast.LENGTH_SHORT).show(); }else{ - dbReference.child("routes").child("n_of_routes").setValue(1); current_val = 0; } } @@ -143,6 +252,45 @@ public class Route extends AppCompatActivity implements DatePickerDialog.OnDateS } }); + place_marker_start = findViewById(R.id.place_marker_start); + place_marker_start.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent i = new Intent(Route.this, PlaceMarker.class); + i.putExtra("location", "start"); + + i.putExtra("lat_start", lat_start.getText()); + i.putExtra("lat_end", lat_end.getText()); + i.putExtra("lng_start", lng_start.getText()); + i.putExtra("lng_end", lng_end.getText()); + i.putExtra("date", date); + i.putExtra("time", time); + i.putExtra("n_seats", n_seats_edit.getText()); + i.putExtra("price", price_edit.getText()); + + startActivity(i); + } + }); + + place_marker_end = findViewById(R.id.place_marker_end); + place_marker_end.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent i = new Intent(Route.this, PlaceMarker.class); + i.putExtra("location", "end"); + + i.putExtra("lat_start", lat_start.getText()); + i.putExtra("lat_end", lat_end.getText()); + i.putExtra("lng_start", lng_start.getText()); + i.putExtra("lng_end", lng_end.getText()); + i.putExtra("date", date); + i.putExtra("time", time); + i.putExtra("n_seats", n_seats_edit.getText()); + i.putExtra("price", price_edit.getText()); + + startActivity(i); + } + }); //date button date_button = findViewById(R.id.button_date); @@ -182,12 +330,16 @@ public class Route extends AppCompatActivity implements DatePickerDialog.OnDateS post_route.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - if(postRoute()) { - Toast.makeText(Route.this, "Route posted successfully!", Toast.LENGTH_SHORT).show(); - Intent i = new Intent(Route.this, Driver_Main.class); - startActivity(i); + if(isLoggedIn) { + if (postRoute()) { + Toast.makeText(Route.this, "Route posted successfully!", Toast.LENGTH_SHORT).show(); + Intent i = new Intent(Route.this, Driver_Main.class); + startActivity(i); + } else { + Toast.makeText(Route.this, "Failed to post route", Toast.LENGTH_SHORT).show(); + } }else{ - Toast.makeText(Route.this, "Failed to post route", Toast.LENGTH_SHORT).show(); + Toast.makeText(Route.this, "Cannot post route while offline! You can save it though!", Toast.LENGTH_LONG).show(); } } }); @@ -214,10 +366,75 @@ public class Route extends AppCompatActivity implements DatePickerDialog.OnDateS time_text.setText(time); } + public void retrieveData(){ + start_location = lat_start.getText().toString() + ", " + lng_start.getText().toString(); + end_location = lat_end.getText().toString() + ", " + lng_end.getText().toString(); + n_seats = n_seats_edit.getText().toString(); + price = price_edit.getText().toString(); + } + //method for saving route to device + @RequiresApi(api = Build.VERSION_CODES.M) public boolean saveRoute(){ - //save to device - return true; + /**Checks for permissions for using the external storage - SD card*/ + if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + + requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + MY_PERMISSIONS_REQUEST_EXTERNAL_STORAGE); + } + + + /**Creates a directory for storage*/ + if (! storageDir.exists()){ + if (! storageDir.mkdirs()){ + Log.d("UniRides", "failed to create directory"); + return false; + } + } + + + try{ + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); + textFile = new File(storageDir.getPath() + File.separator + + "route_" + timeStamp + ".txt"); + FileOutputStream fs = new FileOutputStream(textFile); + if(fs != null){ + + //sets the strings to the values in the widgets + retrieveData(); + + //first index stores starting location + saveText[0] = start_location; + //second index stores end location + saveText[1] = end_location; + //third index stores date + saveText[2] = date; + //fourth index stores time + saveText[3] = time; + //fifth index stores number of seats + saveText[4] = n_seats; + //sixth index stores price + saveText[5] = price; + //seventh index stores user + saveText[6] = firebaseAuth.getCurrentUser().getUid(); + + for(int i = 0; i < saveText.length; i++) { + fs.write((saveText[i] + "\n").getBytes()); + } + + fs.close(); + + return true; + } + + } + catch(IOException e){ + e.printStackTrace(); + return false; + } + + return false; } //method for posting route to database @@ -232,11 +449,8 @@ public class Route extends AppCompatActivity implements DatePickerDialog.OnDateS userId = firebaseAuth.getCurrentUser().getUid(); } - start_location = lat_start.getText().toString() + ", " + lng_start.getText().toString(); - end_location = lat_end.getText().toString() + ", " + lng_end.getText().toString(); - n_seats = n_seats_edit.getText().toString(); - price = price_edit.getText().toString(); - + //sets the strings to the values in the widgets + retrieveData(); if(TextUtils.isEmpty(start_location) || TextUtils.isEmpty(end_location) || TextUtils.isEmpty(n_seats) || TextUtils.isEmpty(price) @@ -264,25 +478,40 @@ public class Route extends AppCompatActivity implements DatePickerDialog.OnDateS //Override for the user_toolbar menu items @Override public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater menuInflater = getMenuInflater(); - menuInflater.inflate(R.menu.toolbar_menu, menu); - return true; + + //setting toolbar options depending on user logged in (offline or online) + if(isLoggedIn){ + MenuInflater menuInflater = getMenuInflater(); + menuInflater.inflate(R.menu.toolbar_menu, menu); + return true; + }else { + MenuInflater menuInflater = getMenuInflater(); + menuInflater.inflate(R.menu.offline_toolbar_menu, menu); + return true; + } } @Override public boolean onOptionsItemSelected(MenuItem item) { - //checks the id of the item, if the item id matches a case id then the code in that case block will execute - switch(item.getItemId()){ + /* checks if user is logged in, if not it shows a different toolbar */ + if(isLoggedIn) { + //checks the id of the item, if the item id matches a case id then the code in that case block will execute + switch (item.getItemId()) { - case(R.id.item_home): + case (R.id.item_home): - Intent home_i = new Intent(Route.this, Driver_Main.class); - startActivity(home_i); - return true; + if (isDriver) { + Intent home_i = new Intent(Route.this, Driver_Main.class); + startActivity(home_i); + return true; + } else { + Intent home_i = new Intent(Route.this, User_Main.class); + startActivity(home_i); + return true; + } - - case(R.id.item_logout): + case (R.id.item_logout): /* TODO: @@ -293,27 +522,48 @@ public class Route extends AppCompatActivity implements DatePickerDialog.OnDateS for now i have just set it so it goes back to the homepage (where you can register or login). */ - Toast.makeText(Route.this, "successfully logged out", Toast.LENGTH_SHORT).show(); - Intent logout_i = new Intent(Route.this, Homepage.class); - startActivity(logout_i); + Toast.makeText(Route.this, "successfully logged out", Toast.LENGTH_SHORT).show(); + Intent logout_i = new Intent(Route.this, Homepage.class); + startActivity(logout_i); - return true; + return true; - case(R.id.item_profile): + case (R.id.item_profile): - Intent profile_i = new Intent(Route.this, Driver_Profile.class); - profile_i.putExtra("userType", Login.userType.DRIVER); - startActivity(profile_i); + Intent profile_i; - return true; + if (isDriver) { + profile_i = new Intent(Route.this, Driver_Profile.class); + profile_i.putExtra("userType", Login.userType.DRIVER); + } else { + profile_i = new Intent(Route.this, User_Profile.class); + profile_i.putExtra("userType", Login.userType.PASSENGER); + } - case(R.id.item_settings): + startActivity(profile_i); - Intent settings_i = new Intent(Route.this, Settings.class); - settings_i.putExtra("userType", Login.userType.DRIVER); - startActivity(settings_i); - return true; + return true; + case (R.id.item_settings): + + Intent settings_i = new Intent(Route.this, Settings.class); + settings_i.putExtra("userType", Login.userType.DRIVER); + startActivity(settings_i); + return true; + + } + + }else{ + + switch (item.getItemId()){ + + case(R.id.item_settings): + + Intent settings_i = new Intent(Route.this, Settings.class); + settings_i.putExtra("userType", Login.userType.NONE); + startActivity(settings_i); + return true; + } } return super.onOptionsItemSelected(item); diff --git a/src/main/java/com/example/liliyayankova/unirides/SavedRoutes.java b/src/main/java/com/example/liliyayankova/unirides/SavedRoutes.java new file mode 100644 index 0000000000000000000000000000000000000000..daf0a925bd7de3bd0fb3824d3317057733535a53 --- /dev/null +++ b/src/main/java/com/example/liliyayankova/unirides/SavedRoutes.java @@ -0,0 +1,294 @@ +package com.example.liliyayankova.unirides; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Environment; +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import android.support.v7.widget.Toolbar; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.CompoundButton; +import android.widget.LinearLayout; +import android.widget.ListView; +import android.widget.ScrollView; +import android.widget.TextView; +import android.widget.Toast; +import android.widget.ToggleButton; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; + +public class SavedRoutes extends AppCompatActivity { + + private String[] loadText; + private File storageDir; + + //values + private String start_location; + private String end_location; + private String date; + private String time; + private String n_seats; + private String price; + private File file_clicked; + private ArrayList<String> routelist; + private boolean delete_mode; + private boolean isDriver; + private boolean isLoggedIn; + + //UI + private TextView title; + private ListView list_view; + private ToggleButton delete_button; + + private final int MY_PERMISSIONS_REQUEST_EXTERNAL_STORAGE = 2; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_saved_routes); + + //setting the user_toolbar layout as the action bar + Toolbar toolbar = findViewById(R.id.toolbar); + try { + setSupportActionBar(toolbar); + } catch (Exception e) { + Log.e("TOOLBAR", e.toString()); + } + + isLoggedIn = true; + + /* checking if there are any bundle extras (should be the userType) */ + if(getIntent().getExtras() != null) { + //setting userType to this result (DRIVER or PASSENGER) + if(getIntent().getExtras().get("userType") == Login.userType.DRIVER){ + isDriver = true; + } + //if coming from the homepage (not signed in) set logged in to false + if(getIntent().getExtras().get("userType") == Login.userType.NONE){ + isLoggedIn = false; + } + } + + //start the app in with delete mode OFF, so you don't accidentally delete a route + delete_mode = false; + delete_button = findViewById(R.id.delete_button); + delete_button.setChecked(false); + + delete_button.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + delete_mode = isChecked; + } + }); + + loadText = new String[7]; + + title = findViewById(R.id.saved_route_text); + list_view = findViewById(R.id.route_listview); + + storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), "UniRides/Routes"); + final File[] files = storageDir.listFiles(); + + //initialise route list + routelist = new ArrayList<>(files.length); + + //getting all the file names and storing them in a string array for an array adapter + for(int i = 0; i < files.length; i++){ + routelist.add(files[i].getName()); + } + + final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, routelist); + list_view.setAdapter(arrayAdapter); + list_view.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + + if(!delete_mode) { + String name = list_view.getItemAtPosition(position).toString(); + + //check which file has been clicked + file_clicked = null; + for (File f : files) { + if (f.getName().equals(name)) { + file_clicked = f; + } + } + + //load values from that file + if (loadFile(file_clicked)) { + + Intent post_route_i = new Intent(SavedRoutes.this, Route.class); + for (int i = 0; i < loadText.length; i++) { + post_route_i.putExtra("route_" + i, loadText[i]); + } + if(!isLoggedIn & !isDriver){ + post_route_i.putExtra("userType", Login.userType.NONE); + }else{ + post_route_i.putExtra("userType", Login.userType.DRIVER); + } + startActivity(post_route_i); + + } + }else{ + + //delete the file and remove it from the array + files[position].delete(); + routelist.remove(position); + arrayAdapter.notifyDataSetChanged(); + } + } + }); + + + + } + + public boolean loadFile(File location){ + + /**Checks for permissions for using the external storage - SD card*/ + if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + + requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, + MY_PERMISSIONS_REQUEST_EXTERNAL_STORAGE); + return false; + }else{ + + if(location == null){ + return false; + }else { + + try { + FileInputStream fs = new FileInputStream(location); + if (fs != null) { + InputStreamReader isr = new InputStreamReader(fs); + BufferedReader br = new BufferedReader(isr); + + int index = 0; + + String line = null; + while ((line = br.readLine()) != null) { + loadText[index] = line.trim(); + index++; + } + fs.close(); + } + + return true; + + } catch (IOException e) { + e.printStackTrace(); + return false; + } + } + } + + } + + //Override for the user_toolbar menu items + @Override + public boolean onCreateOptionsMenu(Menu menu) { + + //setting toolbar options depending on user logged in (offline or online) + if(isLoggedIn){ + MenuInflater menuInflater = getMenuInflater(); + menuInflater.inflate(R.menu.toolbar_menu, menu); + return true; + }else { + MenuInflater menuInflater = getMenuInflater(); + menuInflater.inflate(R.menu.offline_toolbar_menu, menu); + return true; + } + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + + /* checks if user is logged in, if not it shows a different toolbar */ + if(isLoggedIn) { + //checks the id of the item, if the item id matches a case id then the code in that case block will execute + switch (item.getItemId()) { + + case (R.id.item_home): + + if (isDriver) { + Intent home_i = new Intent(SavedRoutes.this, Driver_Main.class); + startActivity(home_i); + return true; + } else { + Intent home_i = new Intent(SavedRoutes.this, User_Main.class); + startActivity(home_i); + return true; + } + + case (R.id.item_logout): + + /* + TODO: + Possibly add a way to log out here? (not sure if we are even tracking the login instance + within each activity? as far as I understand the login just gets you to the next activity + however if you "logout" and just press the back button after it takes you back to the homepage + it will act as if you are still logged in when you reenter). + for now i have just set it so it goes back to the homepage (where you can register or login). + */ + + Toast.makeText(SavedRoutes.this, "successfully logged out", Toast.LENGTH_SHORT).show(); + Intent logout_i = new Intent(SavedRoutes.this, Homepage.class); + startActivity(logout_i); + + return true; + + case (R.id.item_profile): + + Intent profile_i; + + if (isDriver) { + profile_i = new Intent(SavedRoutes.this, Driver_Profile.class); + profile_i.putExtra("userType", Login.userType.DRIVER); + } else { + profile_i = new Intent(SavedRoutes.this, User_Profile.class); + profile_i.putExtra("userType", Login.userType.PASSENGER); + } + + startActivity(profile_i); + + return true; + + case (R.id.item_settings): + + Intent settings_i = new Intent(SavedRoutes.this, Settings.class); + settings_i.putExtra("userType", Login.userType.DRIVER); + startActivity(settings_i); + return true; + + } + + }else{ + + switch (item.getItemId()){ + + case(R.id.item_settings): + + Intent settings_i = new Intent(SavedRoutes.this, Settings.class); + settings_i.putExtra("userType", Login.userType.NONE); + startActivity(settings_i); + return true; + } + } + + return super.onOptionsItemSelected(item); + } +} diff --git a/src/main/java/com/example/liliyayankova/unirides/Settings.java b/src/main/java/com/example/liliyayankova/unirides/Settings.java index e94d40277a8e65b90bc6db3d3bc5093abc6c94c6..e5585c13213708fd3aed4312cedbea2ce5d72dbb 100644 --- a/src/main/java/com/example/liliyayankova/unirides/Settings.java +++ b/src/main/java/com/example/liliyayankova/unirides/Settings.java @@ -1,6 +1,11 @@ package com.example.liliyayankova.unirides; +import android.Manifest; import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Environment; +import android.support.annotation.RequiresApi; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.Toolbar; @@ -16,8 +21,26 @@ import android.widget.Spinner; import android.widget.Toast; import android.widget.ToggleButton; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.text.SimpleDateFormat; +import java.util.Date; + public class Settings extends AppCompatActivity { + //number of settings defined, need to change if you add more settings! + public final int N_SETTINGS = 3; + + private String[] loadText; + private String[] saveText; + + private ArrayAdapter<CharSequence> save_location_adapter; + private ArrayAdapter<CharSequence> language_adapter; + private boolean isDriver; private boolean isLoggedIn; private boolean isSoundOn; @@ -27,7 +50,10 @@ public class Settings extends AppCompatActivity { private Spinner save_location; private Button save_button; + private File storageDir; + private File textFile; + private final int MY_PERMISSIONS_REQUEST_EXTERNAL_STORAGE = 2; @Override protected void onCreate(Bundle savedInstanceState) { @@ -41,6 +67,13 @@ public class Settings extends AppCompatActivity { isDriver = false; isLoggedIn = true; + saveText = new String[N_SETTINGS]; + loadText = new String[N_SETTINGS]; + + storageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS), "UniRides"); + textFile = new File(storageDir.getPath() + File.separator + + "settings.txt"); + /* checking if there are any bundle extras (should be the userType) */ if(getIntent().getExtras() != null) { //setting userType to this result (DRIVER or PASSENGER) @@ -62,19 +95,18 @@ public class Settings extends AppCompatActivity { } this.language = findViewById(R.id.language_spinner); - ArrayAdapter<CharSequence> l_adapter = ArrayAdapter.createFromResource(this, + language_adapter = ArrayAdapter.createFromResource(this, R.array.languages, android.R.layout.simple_spinner_item); - l_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - language.setAdapter(l_adapter); + language_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + language.setAdapter(language_adapter); this.save_location = findViewById(R.id.save_location_spinner); - ArrayAdapter<CharSequence> s_adapter = ArrayAdapter.createFromResource(this, + save_location_adapter = ArrayAdapter.createFromResource(this, R.array.save_locations, android.R.layout.simple_spinner_item); - s_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - save_location.setAdapter(s_adapter); + save_location_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + save_location.setAdapter(save_location_adapter); this.sound = findViewById(R.id.sound_toggle); - this.sound.setChecked(isSoundOn); // set the current state of a toggle button this.sound.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { @@ -84,7 +116,7 @@ public class Settings extends AppCompatActivity { }); //if no settings file found, set to default values - if(!loadSettings()){ + if(!loadSettings()) { sound.setChecked(true); save_location.setSelection(0); language.setSelection(0); @@ -117,22 +149,110 @@ public class Settings extends AppCompatActivity { }); } - //TODO: save settings to device or database + @RequiresApi(api = Build.VERSION_CODES.M) public boolean saveSettings(){ - //if save is successful -> return true - return true; + /**Checks for permissions for using the external storage - SD card*/ + if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + + requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, + MY_PERMISSIONS_REQUEST_EXTERNAL_STORAGE); + } + + + /**Creates a directory for storage*/ + if (! storageDir.exists()){ + if (! storageDir.mkdirs()){ + Log.d("UniRides", "failed to create directory"); + return false; + } + } + + + if(textFile == null){ + return false; + } + + try{ + FileOutputStream fs = new FileOutputStream(textFile); + if(fs != null){ + + //first index stores sound + saveText[0] = Boolean.toString(isSoundOn); + //second index stores language + saveText[1] = Integer.toString(language.getSelectedItemPosition()); + //third index stores save location + saveText[2] = Integer.toString(save_location.getSelectedItemPosition()); + + for(int i = 0; i < N_SETTINGS; i++) { + fs.write((saveText[i] + "\n").getBytes()); + } + + fs.close(); + + return true; + } + + } + catch(IOException e){ + e.printStackTrace(); + return false; + } + + return false; - //if not successful -> return false } - //TODO: load settings from device or database public boolean loadSettings(){ - //if file found -> extract values -> return true + /**Checks for permissions for using the external storage - SD card*/ + if (checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + + requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, + MY_PERMISSIONS_REQUEST_EXTERNAL_STORAGE); + return false; + }else{ + + if(textFile == null){ + return false; + }else { + + try { + FileInputStream fs = new FileInputStream(textFile); + if (fs != null) { + InputStreamReader isr = new InputStreamReader(fs); + BufferedReader br = new BufferedReader(isr); + + int index = 0; + + String line = null; + while ((line = br.readLine()) != null) { + loadText[index] = line.trim(); + index++; + } + fs.close(); + } + + isSoundOn = Boolean.parseBoolean(loadText[0]); + sound.setChecked(isSoundOn); + + int i = Integer.parseInt(loadText[1]); + language.setSelection(i); + + i = Integer.parseInt(loadText[2]); + save_location.setSelection(i); + + return true; + + } catch (IOException e) { + e.printStackTrace(); + return false; + } + } + } - //if no file found -> return false - return false; } //Override for the user_toolbar menu items diff --git a/src/main/res/drawable/icon_save.png b/src/main/res/drawable/icon_save.png new file mode 100644 index 0000000000000000000000000000000000000000..63ec3809486f00d4046a2275ba8bb3c0eea3c3f2 Binary files /dev/null and b/src/main/res/drawable/icon_save.png differ diff --git a/src/main/res/layout/activity_driver_main.xml b/src/main/res/layout/activity_driver_main.xml index 77d46787a05cdebfc12e7acf0a284babb1de2070..61b8efcc2df6ba83d8e8c4a9ccf8e73564838902 100644 --- a/src/main/res/layout/activity_driver_main.xml +++ b/src/main/res/layout/activity_driver_main.xml @@ -30,9 +30,9 @@ android:id="@+id/view_route_button" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_margin="30dp" + android:layout_margin="20dp" android:layout_weight="1" - android:background="@color/common_google_signin_btn_text_dark_disabled" + android:background="@color/common_google_signin_btn_text_dark_default" android:contentDescription="@string/view_routes" android:scaleType="fitCenter" android:src="@drawable/icon_map" @@ -42,13 +42,25 @@ android:id="@+id/create_route_button" android:layout_width="match_parent" android:layout_height="match_parent" - android:layout_margin="30dp" + android:layout_margin="20dp" android:layout_weight="1" - android:background="@color/common_google_signin_btn_text_dark_disabled" + android:background="@color/common_google_signin_btn_text_dark_default" android:contentDescription="@string/create_route" android:scaleType="fitCenter" android:src="@drawable/icon_plus" android:text="@string/title_activity_map" /> + + <ImageButton + android:id="@+id/saved_routes_button" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_margin="20dp" + android:layout_weight="1" + android:background="@color/common_google_signin_btn_text_dark_default" + android:contentDescription="@string/saved_routes" + android:scaleType="fitCenter" + app:srcCompat="@drawable/icon_save" /> + </LinearLayout> <LinearLayout @@ -66,17 +78,26 @@ android:gravity="center" android:text="@string/view_routes" android:textAllCaps="false" - android:textSize="30sp" /> + android:textSize="18sp" /> <TextView - android:id="@+id/create_route_text" + android:id="@+id/saved_route_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" android:text="@string/create_route" android:textAllCaps="false" - android:textSize="30sp" /> + android:textSize="18sp" /> + + <TextView + android:id="@+id/saved_routes_text" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:gravity="center" + android:text="@string/view_saved" + android:textSize="18sp" /> </LinearLayout> diff --git a/src/main/res/layout/activity_homepage.xml b/src/main/res/layout/activity_homepage.xml index ecd055ca955d738a918afdea167102c1e25e09d4..ad6b38edc9e829f0c584b917ae88ba7b472cf511 100644 --- a/src/main/res/layout/activity_homepage.xml +++ b/src/main/res/layout/activity_homepage.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" @@ -39,6 +40,7 @@ android:id="@+id/subh" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginBottom="20dp" android:gravity="top" android:text="@string/subheading" android:textAlignment="center" @@ -46,27 +48,60 @@ android:textSize="18sp" android:textStyle="italic" /> - <ImageButton - android:id="@+id/offline_map" - android:layout_width="200dp" - android:layout_height="200dp" - android:layout_gravity="center" - android:layout_marginTop="30dp" - android:contentDescription="@string/offline_map" - android:scaleType="fitCenter" - android:src="@drawable/icon_map" /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_weight="1.5" + android:orientation="horizontal"> - <TextView - android:id="@+id/map_title" + <ImageButton + android:id="@+id/offline_map" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="center" + android:layout_margin="10dp" + android:layout_weight="1" + android:contentDescription="@string/offline_map" + android:scaleType="fitCenter" + android:src="@drawable/icon_map" /> + + <ImageButton + android:id="@+id/offline_route_button" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_margin="10dp" + android:layout_weight="1" + android:scaleType="fitCenter" + app:srcCompat="@drawable/icon_save" /> + </LinearLayout> + + <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" - android:fontFamily="sans-serif" - android:gravity="top" - android:text="@string/offline_map" - android:textAlignment="center" - android:textAppearance="@style/TextAppearance.AppCompat.Medium" - android:textColor="@color/colorPrimary" - android:textSize="18sp" /> + android:orientation="horizontal"> + + <TextView + android:id="@+id/map_title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:fontFamily="sans-serif" + android:gravity="top" + android:text="@string/offline_map" + android:textAlignment="center" + android:textAppearance="@style/TextAppearance.AppCompat.Medium" + android:textColor="@color/colorPrimary" + android:textSize="18sp" /> + + <TextView + android:id="@+id/saved_routes_title" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:gravity="center" + android:text="@string/view_saved" + android:textSize="18sp" /> + </LinearLayout> <LinearLayout android:layout_width="match_parent" diff --git a/src/main/res/layout/activity_login.xml b/src/main/res/layout/activity_login.xml index d6c8087c2edec6488d97cd02acae2a4a9c9d32d7..3c76f7e7b073693c6e9db9dd214d4a826763470c 100644 --- a/src/main/res/layout/activity_login.xml +++ b/src/main/res/layout/activity_login.xml @@ -5,12 +5,12 @@ android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" - android:paddingLeft="@dimen/activity_horizontal_margin" - android:paddingTop="@dimen/activity_vertical_margin" - android:paddingRight="@dimen/activity_horizontal_margin" - android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".Login"> + <include + android:id="@+id/toolbar" + layout="@layout/user_toolbar" /> + <!-- Login progress --> <ProgressBar android:id="@+id/login_progress" @@ -25,7 +25,8 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" - android:foregroundGravity="center"> + android:foregroundGravity="center" + android:padding="10dp"> <LinearLayout android:id="@+id/email_login_form" diff --git a/src/main/res/layout/activity_place_marker.xml b/src/main/res/layout/activity_place_marker.xml new file mode 100644 index 0000000000000000000000000000000000000000..4a9fc2ffeba58f061ba97d06c8c138b0b9b6c10e --- /dev/null +++ b/src/main/res/layout/activity_place_marker.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="center" + android:orientation="vertical" + tools:context=".PlaceMarker"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_weight="6" + android:orientation="horizontal"> + + <ImageView + android:id="@+id/searchimage" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_marginStart="5dp" + android:layout_marginEnd="5dp" + android:layout_weight="10" + android:scaleType="fitCenter" + app:srcCompat="@android:drawable/ic_search_category_default" /> + + <EditText + android:id="@+id/searchbar" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:ems="10" + android:gravity="start|top" + android:inputType="text" + android:maxLines="1" /> + </LinearLayout> + + <fragment + android:id="@+id/map" + android:name="com.google.android.gms.maps.SupportMapFragment" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_weight="1" + tools:context=".PlaceMarker" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="5dp"> + + <Button + android:id="@+id/done_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_margin="5dp" + android:background="@color/colorPrimary" + android:text="@string/done" + android:textColor="@color/common_google_signin_btn_text_dark_default" /> + </LinearLayout> + + +</LinearLayout> \ No newline at end of file diff --git a/src/main/res/layout/activity_route.xml b/src/main/res/layout/activity_route.xml index a7c32c25a4ada4a1474acbdfbac7180547e5c463..977da04f7b588b535db2e45afca6b9de2711cdbb 100644 --- a/src/main/res/layout/activity_route.xml +++ b/src/main/res/layout/activity_route.xml @@ -5,14 +5,14 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" - tools:context=".Settings"> + tools:context=".Route"> <include android:id="@+id/toolbar" layout="@layout/user_toolbar" /> <TextView - android:id="@+id/create_route_text" + android:id="@+id/saved_route_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="20dp" @@ -28,75 +28,117 @@ android:layout_weight="1" android:orientation="vertical"> - <TextView - android:id="@+id/text_start_location" + <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" - android:gravity="center" - android:text="@string/start_location" /> + android:background="@color/colorPrimary" + android:orientation="horizontal"> + + <TextView + android:id="@+id/text_start_location" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:gravity="center" + android:text="@string/start_location" + android:textColor="@color/common_google_signin_btn_text_dark_pressed" + android:textSize="14sp" + android:textStyle="bold" /> + + <Button + android:id="@+id/place_marker_start" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="@string/pick_marker" /> + </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" + android:background="@color/colorPrimary" android:orientation="horizontal"> <TextView - android:id="@+id/long_text" + android:id="@+id/lat_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" - android:text="@string/lon" /> + android:text="@string/lat" + android:textColor="@color/common_google_signin_btn_text_dark_default" /> <EditText - android:id="@+id/long_num" + android:id="@+id/lat_num" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:ems="10" - android:inputType="numberDecimal" /> + android:inputType="numberDecimal" + android:textColor="@color/common_google_signin_btn_text_dark_default" /> <TextView - android:id="@+id/lat_text" + android:id="@+id/long_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" - android:text="@string/lat" /> + android:text="@string/lon" + android:textColor="@color/common_google_signin_btn_text_dark_default" /> <EditText - android:id="@+id/lat_num" + android:id="@+id/long_num" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:ems="10" - android:inputType="numberDecimal" /> + android:inputType="numberDecimal" + android:textColor="@color/common_google_signin_btn_text_dark_default" /> + </LinearLayout> - <TextView - android:id="@+id/text_end_location" + + <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" - android:gravity="center" - android:text="@string/end_location" /> + android:background="@color/colorPrimaryDark" + android:orientation="horizontal"> + + <TextView + android:id="@+id/text_end_location" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:gravity="center" + android:text="@string/end_location" + android:textColor="@color/common_google_signin_btn_text_dark_focused" + android:textStyle="bold" /> + <Button + android:id="@+id/place_marker_end" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="@string/pick_marker" /> + </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" + android:background="@color/colorPrimaryDark" android:orientation="horizontal"> <TextView - android:id="@+id/long_text2" + android:id="@+id/lat_text2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" - android:text="@string/lon" /> + android:text="@string/lat" /> <EditText - android:id="@+id/long_num2" + android:id="@+id/lat_num2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" @@ -104,15 +146,15 @@ android:inputType="numberDecimal" /> <TextView - android:id="@+id/lat_text2" + android:id="@+id/long_text2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:gravity="center" - android:text="@string/lat" /> + android:text="@string/lon" /> <EditText - android:id="@+id/lat_num2" + android:id="@+id/long_num2" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" @@ -120,11 +162,6 @@ android:inputType="numberDecimal" /> </LinearLayout> - <LinearLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:orientation="horizontal"></LinearLayout> - <TextView android:id="@+id/text_date" android:layout_width="match_parent" @@ -200,7 +237,8 @@ android:layout_margin="10dp" android:layout_weight="1" android:background="@color/colorPrimary" - android:text="@string/post_route" /> + android:text="@string/post_route" + android:textColor="@color/common_google_signin_btn_text_dark_default" /> </LinearLayout> diff --git a/src/main/res/layout/activity_saved_routes.xml b/src/main/res/layout/activity_saved_routes.xml new file mode 100644 index 0000000000000000000000000000000000000000..2e4ccf2a6fdd803d464cf5931a955c87ace12a9d --- /dev/null +++ b/src/main/res/layout/activity_saved_routes.xml @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + tools:context=".SavedRoutes"> + + <include + android:id="@+id/toolbar" + layout="@layout/user_toolbar" /> + + <TextView + android:id="@+id/saved_route_text" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="20dp" + android:gravity="center" + android:text="@string/saved_routes" + android:textSize="30sp" /> + + <ListView + android:id="@+id/route_listview" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_weight="1"> + + </ListView> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:background="@color/colorPrimary" + android:orientation="horizontal"> + + <TextView + android:id="@+id/delete_text" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="10dp" + android:layout_weight="1" + android:gravity="center" + android:text="@string/delete_route" + android:textColor="@color/common_google_signin_btn_text_dark_default" + android:textSize="18sp" /> + + <ToggleButton + android:id="@+id/delete_button" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="10dp" + android:layout_weight="1" + android:background="@color/common_google_signin_btn_text_dark_default" + android:text="ToggleButton" + android:textOff="@string/off" + android:textOn="@string/on" /> + + </LinearLayout> + + +</LinearLayout> \ No newline at end of file diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 3a2c06f7d42c4ec8ae2831306862d9ad1c517a14..8174f97ca437a847ac0edc9d0130b815ef6fbba4 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -57,8 +57,9 @@ <string name="back">Back</string> <!-- route creation strings --> - <string name="start_location">Start Location</string> - <string name="end_location">End Location</string> + <string name="start_location">Start Location:</string> + <string name="end_location">End Location:</string> + <string name="pick_marker">Place Marker</string> <string name="price">Price (£):</string> <string name="date">Date</string> <string name="time">Start Time</string> @@ -72,6 +73,11 @@ <string name="done">Done</string> <string name="lon">Longitude:</string> <string name="lat">Latitude:</string> + <string name="view_saved">View Saved Routes</string> + <string name="saved_routes">Saved Routes:</string> + <string name="delete_route">Delete Route Mode:</string> + <string name="on">On</string> + <string name="off">Off</string> <!-- settings activity strings --> <string name="language">Language</string> @@ -85,8 +91,7 @@ </string-array> <!-- spinner values for SAVE_LOCATION --> - <string-array name="save_locations"> - <item>Device</item> + <string-array name="save_locations">s <item>SD Card</item> </string-array> @@ -103,6 +108,7 @@ <string name="edit_driving">Time Driving:</string> <string name="edit_model">Car Model:</string> <string name="take_pic">Take a picture</string> + <string name="title_activity_place_marker">Map</string> </resources>