From 55b96b14acc16b9fb5beecc2d43f1e9e5a94157f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yi=C4=9Fit=20=C3=87olako=C4=9Flu?= Date: Sat, 8 Jun 2019 09:44:28 +0300 Subject: [PATCH] Added several functions - Added complete complaints functionality to android app -Added a presentation mode that hides unnecessary items from navigation drawer to android app -Added a button to return to home -Setup the server side so that ML functions only get activated on windows machines TODO: - Add ambulance tracking to denunciation - Add car crash reporting to android app --- MyCity/.gitignore | 11 + MyCity/app/build.gradle | 10 +- MyCity/app/src/main/AndroidManifest.xml | 1 + .../java/gq/yigit/mycity/MainActivity.java | 103 ++- .../java/gq/yigit/mycity/MainFragment.java | 18 +- .../java/gq/yigit/mycity/ParkFragment.java | 2 +- .../main/java/gq/yigit/mycity/QRFragment.java | 2 +- .../java/gq/yigit/mycity/RateFragment.java | 2 +- .../complaintsFragment/ComplaintFragment.java | 209 ++++++ .../ComplaintViewFragment.java | 116 ++++ .../complaintsFragment/ComplaintsContent.java | 110 +++ .../ComplaintsFragment.java | 134 ++++ .../MyComplaintRecyclerViewAdapter.java | 108 +++ .../mycity/navigation/TransitFragment.java | 2 +- .../gq/yigit/mycity/tools/WebRequest.java | 2 - .../gq/yigit/mycity/utility/UtilityMain.java | 2 +- .../mycity/votesFragment/VoteFragment.java | 2 +- .../main/res/drawable-v24/side_nav_bar.xml | 6 +- MyCity/app/src/main/res/drawable/camera.xml | 4 + MyCity/app/src/main/res/drawable/ic_home.xml | 5 + .../src/main/res/drawable/road_cracked.xml | 4 + .../app/src/main/res/drawable/status_done.xml | 4 + .../src/main/res/drawable/status_pending.xml | 6 + .../main/res/layout/fragment_complaint.xml | 42 ++ .../res/layout/fragment_complaint_list.xml | 15 + .../res/layout/fragment_complaint_view.xml | 81 +++ .../src/main/res/layout/nav_header_main.xml | 2 +- .../main/res/menu/activity_main_drawer.xml | 20 +- MyCity/app/src/main/res/menu/main.xml | 12 + MyCity/app/src/main/res/values/colors.xml | 4 +- MyCity/app/src/main/res/values/strings.xml | 2 +- server_side/{apia => api}/app.py | 6 +- .../encryption/mycity-decrypted.key | 0 .../{apia => api}/encryption/mycity.crt | 0 .../{apia => api}/encryption/mycity.csr | 0 .../{apia => api}/encryption/mycity.key | 0 .../{apia => api}/encryption/mycity.pem | 0 .../9vard12ty0ad2yvwp3q53rsf3h43r2vq.png | Bin 0 -> 16812 bytes .../{apia => api}/images/muhtarlik.jpg | Bin server_side/{apia => api}/images/park.jpg | Bin server_side/{apia => api}/images/voting.jpg | Bin .../{apia => api}/modules/SpotSelector.py | 0 server_side/{apia => api/modules}/__init__.py | 0 .../{apia => api}/modules/announcements.py | 0 .../{apia => api}/modules/bus_stops.py | 0 server_side/api/modules/complaint.py | 143 ++++ .../modules/databases/announcements.json | 0 .../{apia => api}/modules/databases/bus.json | 0 .../modules/databases/bus_locations.json | 0 .../api/modules/databases/complaints.json | 26 + .../api/modules/databases/denunciations.json | 3 + .../modules/databases/locations.json | 0 .../modules/databases/park_data.json | 0 .../modules/databases/ratings.json | 0 .../modules/databases/users.json | 0 .../modules/databases/votings.json | 0 .../{apia => api}/modules/denunciation.py | 0 server_side/{apia => api}/modules/image5.jpg | Bin server_side/{apia => api}/modules/lot.jpg | Bin .../{apia => api}/modules/navigation.py | 0 .../{apia => api}/modules/rating_system.py | 0 .../{apia => api}/modules/smart_park.py | 1 - .../{apia => api}/modules/user_info.py | 0 server_side/{apia => api}/modules/utility.py | 0 server_side/{apia => api}/modules/utils.py | 0 .../{apia => api}/modules/voting_system.py | 0 server_side/{apia => api}/requirements.txt | 0 .../9vard12ty0ad2yvwp3q53rsf3h43r2vq.png | Bin 7660 -> 0 bytes .../9vard12ty0ad2yvwp3q53rsf3h43r2vq_qr.png | Bin 802 -> 0 bytes server_side/apia/modules/__init__.py | 0 .../apia/modules/databases/denunciations.json | 206 ------ traffic_analyzer/ambulance_detect.py | 144 ++-- traffic_analyzer/{ => debug_data}/amb_1.mp4 | Bin traffic_analyzer/{ => debug_data}/amb_2.mp4 | Bin .../{ => debug_data}/frame_data.pkl | Bin .../images/1_coordinates.txt | 0 traffic_analyzer/images/coordinates.json | 626 ++++++++++++++++++ traffic_analyzer/images/train_image_taker.py | 95 +++ .../data/mscoco_label_map.pbtxt | 4 +- traffic_analyzer/receive.py | 53 -- traffic_analyzer/saver.py | 11 - traffic_analyzer/sender.py | 112 ---- traffic_analyzer/traffic_analyzer.iml | 3 + traffic_analyzer/train_image_taker.py | 66 -- traffic_analyzer/windowsTemp.py | 73 -- 85 files changed, 1995 insertions(+), 618 deletions(-) create mode 100644 MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/ComplaintFragment.java create mode 100644 MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/ComplaintViewFragment.java create mode 100644 MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/ComplaintsContent.java create mode 100644 MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/ComplaintsFragment.java create mode 100644 MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/MyComplaintRecyclerViewAdapter.java create mode 100644 MyCity/app/src/main/res/drawable/camera.xml create mode 100644 MyCity/app/src/main/res/drawable/ic_home.xml create mode 100644 MyCity/app/src/main/res/drawable/road_cracked.xml create mode 100644 MyCity/app/src/main/res/drawable/status_done.xml create mode 100644 MyCity/app/src/main/res/drawable/status_pending.xml create mode 100644 MyCity/app/src/main/res/layout/fragment_complaint.xml create mode 100644 MyCity/app/src/main/res/layout/fragment_complaint_list.xml create mode 100644 MyCity/app/src/main/res/layout/fragment_complaint_view.xml rename server_side/{apia => api}/app.py (85%) rename server_side/{apia => api}/encryption/mycity-decrypted.key (100%) rename server_side/{apia => api}/encryption/mycity.crt (100%) rename server_side/{apia => api}/encryption/mycity.csr (100%) rename server_side/{apia => api}/encryption/mycity.key (100%) rename server_side/{apia => api}/encryption/mycity.pem (100%) create mode 100644 server_side/api/images/9vard12ty0ad2yvwp3q53rsf3h43r2vq.png rename server_side/{apia => api}/images/muhtarlik.jpg (100%) rename server_side/{apia => api}/images/park.jpg (100%) rename server_side/{apia => api}/images/voting.jpg (100%) rename server_side/{apia => api}/modules/SpotSelector.py (100%) rename server_side/{apia => api/modules}/__init__.py (100%) rename server_side/{apia => api}/modules/announcements.py (100%) rename server_side/{apia => api}/modules/bus_stops.py (100%) create mode 100644 server_side/api/modules/complaint.py rename server_side/{apia => api}/modules/databases/announcements.json (100%) rename server_side/{apia => api}/modules/databases/bus.json (100%) rename server_side/{apia => api}/modules/databases/bus_locations.json (100%) create mode 100644 server_side/api/modules/databases/complaints.json create mode 100644 server_side/api/modules/databases/denunciations.json rename server_side/{apia => api}/modules/databases/locations.json (100%) rename server_side/{apia => api}/modules/databases/park_data.json (100%) rename server_side/{apia => api}/modules/databases/ratings.json (100%) rename server_side/{apia => api}/modules/databases/users.json (100%) rename server_side/{apia => api}/modules/databases/votings.json (100%) rename server_side/{apia => api}/modules/denunciation.py (100%) rename server_side/{apia => api}/modules/image5.jpg (100%) rename server_side/{apia => api}/modules/lot.jpg (100%) rename server_side/{apia => api}/modules/navigation.py (100%) rename server_side/{apia => api}/modules/rating_system.py (100%) rename server_side/{apia => api}/modules/smart_park.py (98%) rename server_side/{apia => api}/modules/user_info.py (100%) rename server_side/{apia => api}/modules/utility.py (100%) rename server_side/{apia => api}/modules/utils.py (100%) rename server_side/{apia => api}/modules/voting_system.py (100%) rename server_side/{apia => api}/requirements.txt (100%) delete mode 100644 server_side/apia/images/9vard12ty0ad2yvwp3q53rsf3h43r2vq.png delete mode 100644 server_side/apia/images/9vard12ty0ad2yvwp3q53rsf3h43r2vq_qr.png delete mode 100644 server_side/apia/modules/__init__.py delete mode 100644 server_side/apia/modules/databases/denunciations.json rename traffic_analyzer/{ => debug_data}/amb_1.mp4 (100%) rename traffic_analyzer/{ => debug_data}/amb_2.mp4 (100%) rename traffic_analyzer/{ => debug_data}/frame_data.pkl (100%) rename server_side/apia/__init__.py~f939ad8155badff39792aaabe628f74142004970 => traffic_analyzer/images/1_coordinates.txt (100%) create mode 100644 traffic_analyzer/images/coordinates.json create mode 100644 traffic_analyzer/images/train_image_taker.py delete mode 100644 traffic_analyzer/receive.py delete mode 100644 traffic_analyzer/saver.py delete mode 100644 traffic_analyzer/sender.py delete mode 100644 traffic_analyzer/train_image_taker.py delete mode 100644 traffic_analyzer/windowsTemp.py diff --git a/MyCity/.gitignore b/MyCity/.gitignore index 4237d26..d985e48 100644 --- a/MyCity/.gitignore +++ b/MyCity/.gitignore @@ -13,3 +13,14 @@ rfcn_resnet101_coco_11_06_2017\ ssd_inception_v2_coco_2017_11_17\ ssd_mobilenet_v1_coco_2017_11_17\ faster_rcnn_resnet101_coco_11_06_2017\ +ssd_resnet101_v1_fpn_shared_box_predictor_oid_512x512_sync_2019_01_20/ +road.svg +ssd_resnet101_v1_fpn_shared_box_predictor_oid_512x512_sync_2019_01_20/ +ssd_resnet101_v1_fpn_shared_box_predictor_oid_512x512_sync_2019_01_20/ +frozen_inference_graph.pb +model.ckpt.data-00000-of-00001 +model.ckpt.index +model.ckpt.meta +pipeline.config +saved_model.pb +variables/ diff --git a/MyCity/app/build.gradle b/MyCity/app/build.gradle index 33ba7a0..e729ae4 100644 --- a/MyCity/app/build.gradle +++ b/MyCity/app/build.gradle @@ -12,7 +12,7 @@ android { android.defaultConfig.vectorDrawables.useSupportLibrary = true multiDexEnabled true - + } buildTypes { release { @@ -23,15 +23,13 @@ android { } - - } dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') api 'cz.msebera.android:httpclient:4.4.1.2' - implementation ('com.github.chathuralakmal:AndroidImagePopup:1.2.1',{ + implementation('com.github.chathuralakmal:AndroidImagePopup:1.2.1', { exclude module: "com.github.bumptech.glide" }) implementation 'com.journeyapps:zxing-android-embedded:3.6.0' @@ -45,9 +43,9 @@ dependencies { testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' - implementation ('com.google.android.libraries.places:places:1.1.0',{ + implementation('com.google.android.libraries.places:places:1.1.0', { exclude group: "com.github.bumptech.glide" }) implementation 'com.google.android.gms:play-services-maps:16.1.0' -} \ No newline at end of file +} diff --git a/MyCity/app/src/main/AndroidManifest.xml b/MyCity/app/src/main/AndroidManifest.xml index 28861f6..6574e58 100644 --- a/MyCity/app/src/main/AndroidManifest.xml +++ b/MyCity/app/src/main/AndroidManifest.xml @@ -38,6 +38,7 @@ + \ No newline at end of file diff --git a/MyCity/app/src/main/java/gq/yigit/mycity/MainActivity.java b/MyCity/app/src/main/java/gq/yigit/mycity/MainActivity.java index 311eb00..16f8dfc 100644 --- a/MyCity/app/src/main/java/gq/yigit/mycity/MainActivity.java +++ b/MyCity/app/src/main/java/gq/yigit/mycity/MainActivity.java @@ -2,20 +2,25 @@ package gq.yigit.mycity; import android.Manifest; import android.app.Activity; +import android.app.Fragment; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; import android.net.Uri; import android.os.Bundle; -import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.design.widget.NavigationView.OnNavigationItemSelectedListener; import android.support.v4.app.ActivityCompat; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.support.v4.content.ContextCompat; import android.support.v7.app.AlertDialog; +import android.util.DisplayMetrics; import android.util.Log; import android.view.*; import android.support.design.widget.NavigationView; @@ -28,7 +33,10 @@ import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; -import com.bumptech.glide.Glide; +import gq.yigit.mycity.complaintsFragment.ComplaintFragment; +import gq.yigit.mycity.complaintsFragment.ComplaintViewFragment; +import gq.yigit.mycity.complaintsFragment.ComplaintsContent; +import gq.yigit.mycity.complaintsFragment.ComplaintsFragment; import gq.yigit.mycity.navigation.TransitFragment; import gq.yigit.mycity.tools.*; import gq.yigit.mycity.tools.WebRequest.responseListener; @@ -40,6 +48,7 @@ import gq.yigit.mycity.votesFragment.VotesFragment.OnListFragmentInteractionList import org.json.JSONArray; import org.json.JSONObject; +import java.util.ArrayList; import java.util.HashMap; import static gq.yigit.mycity.tools.ImageDownload.*; @@ -56,6 +65,9 @@ public class MainActivity extends AppCompatActivity QRFragment.OnFragmentInteractionListener, OnFragmentInteractionListener, ParkFragment.OnFragmentInteractionListener, + ComplaintFragment.OnComplaintsClicked, + ComplaintsFragment.OnListFragmentInteractionListener, + ComplaintViewFragment.OnFragmentInteractionListener, responseListener, imageListener { @@ -66,13 +78,54 @@ public class MainActivity extends AppCompatActivity private ImageView avatarView; private TextView userName; public static Activity mainActivity; + public static DisplayMetrics pix_density; public static String apikey = "AIzaSyBuOC03IHPA_6TPnfk18b0SAgD1uge4-dk"; - + public boolean present = true; + public MenuItem present_item; + public static LocationManager locationManager; @Override protected void onCreate(Bundle savedInstanceState) { Log.d("[BOOKMARK]","Started creating activity"); super.onCreate(savedInstanceState); + pix_density = getApplicationContext().getResources().getDisplayMetrics(); + locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); + if ( ContextCompat.checkSelfPermission( this, android.Manifest.permission.ACCESS_COARSE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) { + + ActivityCompat.requestPermissions( this, new String[] { android.Manifest.permission.ACCESS_COARSE_LOCATION }, + 1 ); + }else if( ContextCompat.checkSelfPermission( this, Manifest.permission.ACCESS_FINE_LOCATION ) != PackageManager.PERMISSION_GRANTED ) { + + ActivityCompat.requestPermissions( this, new String[] { Manifest.permission.ACCESS_FINE_LOCATION }, + 1 ); + + } + + try { + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 10, new LocationListener() { + @Override + public void onLocationChanged(Location location) { + Log.i("[INFO]", "Location changed to lat:" + location.getLatitude() + " lng:" + location.getLongitude()); + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) { + } + + @Override + public void onProviderEnabled(String provider) { + Log.i("[INFO]", "Provider enabled: " + provider); + } + + @Override + public void onProviderDisabled(String provider) { + Log.i("[INFO]", "Provider disabled: " + provider); + + } + }); + }catch (SecurityException e){ + Log.e("[ERROR]", "An error occured with location permissions"); + } setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); @@ -83,6 +136,7 @@ public class MainActivity extends AppCompatActivity drawer.addDrawerListener(toggle); toggle.syncState(); + FileActions file_manager = new FileActions(); url = file_manager.readFromFile(cntxt,"server.config").trim(); HashMap request = new HashMap<>(); @@ -95,6 +149,9 @@ public class MainActivity extends AppCompatActivity NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view); navigationView.setNavigationItemSelectedListener(this); + Menu menu = navigationView.getMenu(); + present_item = menu.findItem(R.id.present_items); + present_item.setVisible(!present); MainFragment fragment = new MainFragment(); View header = navigationView.getHeaderView(0); @@ -154,6 +211,15 @@ public class MainActivity extends AppCompatActivity alert.show(); return true; + }else if(id == R.id.action_presentation){ + present = !present; + present_item.setVisible(!present); + Toast.makeText(getApplicationContext(),"Toggled presentation mode!",Toast.LENGTH_LONG).show(); + }else if(id == R.id.action_restart){ + Intent intent = new Intent(this, MainActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + finish(); } return super.onOptionsItemSelected(item); @@ -201,10 +267,13 @@ public class MainActivity extends AppCompatActivity QRFragment fragment= new QRFragment(); fragmentTransaction.replace(R.id.app_bar_main, fragment); fragmentTransaction.commit(); + }else if (id == R.id.complaint){ + ComplaintFragment fragment= new ComplaintFragment(); + fragmentTransaction.replace(R.id.app_bar_main, fragment); + fragmentTransaction.commit(); } - - + fragmentTransaction.addToBackStack(null); DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout); drawer.closeDrawer(GravityCompat.START); return true; @@ -219,6 +288,20 @@ public class MainActivity extends AppCompatActivity } public void onFragmentInteraction(Uri uri){ + } + + public void ComplaintsClicked(@Nullable ComplaintsContent.ComplaintItem item){ + + if(item == null) { + FragmentManager fragmentManager = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + + ComplaintsFragment fragment = new ComplaintsFragment(); + fragmentTransaction.replace(R.id.app_bar_main, fragment); + fragmentTransaction.commit(); + return; + } + } @@ -255,5 +338,15 @@ public class MainActivity extends AppCompatActivity } } + @Override + public void onListFragmentInteraction(ComplaintsContent.ComplaintItem item){ + FragmentManager fragmentManager = getSupportFragmentManager(); + FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); + + ComplaintViewFragment fragment = ComplaintViewFragment.newInstance(item.toString()); + fragmentTransaction.replace(R.id.app_bar_main, fragment); + fragmentTransaction.commit(); + } + } diff --git a/MyCity/app/src/main/java/gq/yigit/mycity/MainFragment.java b/MyCity/app/src/main/java/gq/yigit/mycity/MainFragment.java index b8dd28c..e723843 100644 --- a/MyCity/app/src/main/java/gq/yigit/mycity/MainFragment.java +++ b/MyCity/app/src/main/java/gq/yigit/mycity/MainFragment.java @@ -2,6 +2,8 @@ package gq.yigit.mycity; import android.content.Context; import android.graphics.Bitmap; +import android.location.Location; +import android.location.LocationManager; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.Fragment; @@ -36,6 +38,7 @@ public class MainFragment extends Fragment implements WebRequest.responseListene private TextView temp_text; private TextView humi_text; private TextView pres_text; + private TextView city_text; private ImageView weather_img; private RecyclerView recyclerView; private SwipeRefreshLayout swipeRefreshLayout; @@ -64,13 +67,22 @@ public class MainFragment extends Fragment implements WebRequest.responseListene View rootView = inflater.inflate(R.layout.fragment_main, container, false); temp_text = rootView.findViewById(R.id.temp_text); humi_text = rootView.findViewById(R.id.humidity); + city_text = rootView.findViewById(R.id.city_name); pres_text = rootView.findViewById(R.id.pressure); weather_img = rootView.findViewById(R.id.forecast_img); recyclerView = rootView.findViewById(R.id.anouncements); swipeRefreshLayout = rootView.findViewById(R.id.simpleSwipeRefreshLayout); HashMap params = new HashMap<>(); - params.put("q","Ankara,tr"); + + try { + Location curloc = MainActivity.locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); + params.put("lat",String.valueOf(curloc.getLatitude())); + params.put("lon",String.valueOf(curloc.getLongitude())); + }catch (SecurityException e){ + Log.e("[ERROR]", "An error occured with location permissions"); + + } params.put("appid",key); FileActions file_manager = new FileActions(); @@ -108,7 +120,7 @@ public class MainFragment extends Fragment implements WebRequest.responseListene mListener = (OnFragmentInteractionListener) context; } else { throw new RuntimeException(context.toString() - + " must implement OnFragmentInteractionListener"); + + " must implement OnComplaintsClicked"); } } @@ -132,7 +144,7 @@ public class MainFragment extends Fragment implements WebRequest.responseListene temp_text.setText((int)(Float.parseFloat(temp.getString("temp")) - 272.15) + " °C"); humi_text.setText("Humidity: %" + temp.getString("humidity")); pres_text.setText("Pressure: " + temp.getString("pressure") + "hpa"); - + city_text.setText(new JSONObject(response).getString("name")); ImageDownload imageDownload = new ImageDownload(); imageDownload.addListener(this); imageDownload.execute(String.format("http://openweathermap.org/img/w/%s.png", weatherdata.getString("icon"))); diff --git a/MyCity/app/src/main/java/gq/yigit/mycity/ParkFragment.java b/MyCity/app/src/main/java/gq/yigit/mycity/ParkFragment.java index d7b4bbb..d399d88 100644 --- a/MyCity/app/src/main/java/gq/yigit/mycity/ParkFragment.java +++ b/MyCity/app/src/main/java/gq/yigit/mycity/ParkFragment.java @@ -132,7 +132,7 @@ public class ParkFragment extends Fragment implements WebRequest.responseListene mListener = (OnFragmentInteractionListener) context; } else { throw new RuntimeException(context.toString() - + " must implement OnFragmentInteractionListener"); + + " must implement OnComplaintsClicked"); } } diff --git a/MyCity/app/src/main/java/gq/yigit/mycity/QRFragment.java b/MyCity/app/src/main/java/gq/yigit/mycity/QRFragment.java index afd6d0f..0b0ed1f 100644 --- a/MyCity/app/src/main/java/gq/yigit/mycity/QRFragment.java +++ b/MyCity/app/src/main/java/gq/yigit/mycity/QRFragment.java @@ -71,7 +71,7 @@ public class QRFragment extends Fragment { mListener = (OnFragmentInteractionListener) context; } else { throw new RuntimeException(context.toString() - + " must implement OnFragmentInteractionListener"); + + " must implement OnComplaintsClicked"); } } diff --git a/MyCity/app/src/main/java/gq/yigit/mycity/RateFragment.java b/MyCity/app/src/main/java/gq/yigit/mycity/RateFragment.java index f4a70e3..98d4f69 100644 --- a/MyCity/app/src/main/java/gq/yigit/mycity/RateFragment.java +++ b/MyCity/app/src/main/java/gq/yigit/mycity/RateFragment.java @@ -152,7 +152,7 @@ public class RateFragment extends Fragment implements WebRequest.responseListene mListener = (OnFragmentInteractionListener) context; } else { throw new RuntimeException(context.toString() - + " must implement OnFragmentInteractionListener"); + + " must implement OnComplaintsClicked"); } } diff --git a/MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/ComplaintFragment.java b/MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/ComplaintFragment.java new file mode 100644 index 0000000..ed644c4 --- /dev/null +++ b/MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/ComplaintFragment.java @@ -0,0 +1,209 @@ +package gq.yigit.mycity.complaintsFragment; + +import android.content.Context; +import android.content.Intent; +import android.graphics.Bitmap; +import android.location.Location; +import android.location.LocationManager; +import android.net.Uri; +import android.os.Bundle; +import android.os.Environment; +import android.provider.MediaStore; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.util.Base64; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.Toast; +import gq.yigit.mycity.MainActivity; +import gq.yigit.mycity.R; +import gq.yigit.mycity.tools.FileActions; +import gq.yigit.mycity.tools.WebRequest; +import org.json.JSONException; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.util.HashMap; + +import static android.app.Activity.RESULT_OK; + + +public class ComplaintFragment extends Fragment implements WebRequest.responseListener { + + private OnComplaintsClicked mListener; + private ImageView complaint_image; + private ComplaintFragment activity; + private Uri mImageUri; + private Bitmap img; + private String img_b64 = ""; + private Button submit_button; + private EditText text_in; + private String url; + + public ComplaintFragment() { + // Required empty public constructor + } + + public static ComplaintFragment newInstance(String param1, String param2) { + ComplaintFragment fragment = new ComplaintFragment(); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + } + + private File createTemporaryFile(String part, String ext) throws Exception + { + File tempDir= Environment.getExternalStorageDirectory(); + tempDir=new File(tempDir.getAbsolutePath()+"/.temp/"); + if(!tempDir.exists()) + { + tempDir.mkdirs(); + } + return File.createTempFile(part, ext, tempDir); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_complaint, container, false); + activity = this; + + FileActions file_manager = new FileActions(); + url = file_manager.readFromFile(getContext(),"server.config").trim(); + + complaint_image = rootView.findViewById(R.id.complaint_image); + submit_button = rootView.findViewById(R.id.compaint_submit); + text_in = rootView.findViewById(R.id.complaint_text); + + rootView.findViewById(R.id.complaints_button).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mListener.ComplaintsClicked(null); + } + }); + submit_button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + HashMap params = new HashMap<>(); + + try { + Location curloc = MainActivity.locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); + params.put("lat",String.valueOf(curloc.getLatitude())); + params.put("lng",String.valueOf(curloc.getLongitude())); + }catch (SecurityException e){ + Log.e("[ERROR]", "An error occured with location permissions"); + + } + if(img_b64.isEmpty()){ + Toast.makeText(getContext(),"Please take a photo of the complaint!",Toast.LENGTH_LONG).show(); + return; + } + + if(text_in.getText().toString().length() < 10){ + Toast.makeText(getContext(),"Complaint should be minimum 10 characters",Toast.LENGTH_LONG).show(); + return; + } + + params.put("img",img_b64); + params.put("content",text_in.getText().toString()); + try { + params.put("id", MainActivity.userData.getString("id")); + }catch (JSONException e){ + Log.e("[ERROR]","Cannot get id"); + } + + WebRequest request = new WebRequest(url+"/complaint",false, params,0); + request.addListener(activity); + request.execute(); + + } + + }); + + complaint_image.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + File photo; + Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + + try + { + // place where to store camera taken picture + photo = createTemporaryFile("picture", ".jpg"); + photo.delete(); + Uri mImageUri = Uri.fromFile(photo); + } + catch(Exception e) + { + Log.v("[ERROR]", "Can't create file to take picture!"); + Toast.makeText(getContext(), "Please check SD card! Image shot is impossible!", Toast.LENGTH_LONG); + } + intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri); + //start camera intent + activity.startActivityForResult(intent, 100); + } + }); + + + + return rootView; + } + + + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof OnComplaintsClicked) { + mListener = (OnComplaintsClicked) context; + } else { + throw new RuntimeException(context.toString() + + " must implement OnComplaintsClicked"); + } + } + + @Override + public void onDetach() { + super.onDetach(); + mListener = null; + } + + public interface OnComplaintsClicked { + void ComplaintsClicked(@Nullable ComplaintsContent.ComplaintItem item); + } + + + //called after camera intent finished + @Override + public void onActivityResult(int requestCode, int resultCode, Intent data) + { + if(requestCode==100 && resultCode==RESULT_OK) + { + Bitmap photo = (Bitmap) data.getExtras().get("data"); + img = photo; + complaint_image.setImageBitmap(img); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + img.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream); + byte[] byteArray = byteArrayOutputStream.toByteArray(); + img_b64= Base64.encodeToString(byteArray, Base64.DEFAULT); + } + super.onActivityResult(requestCode, resultCode, data); + } + + @Override + public void receivedResponse(boolean success, String response,int id){ + if(success){ + Toast.makeText(getContext(),"Complaint send successfully!",Toast.LENGTH_SHORT).show(); + } + } +} diff --git a/MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/ComplaintViewFragment.java b/MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/ComplaintViewFragment.java new file mode 100644 index 0000000..0bb2145 --- /dev/null +++ b/MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/ComplaintViewFragment.java @@ -0,0 +1,116 @@ +package gq.yigit.mycity.complaintsFragment; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.util.Base64; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import gq.yigit.mycity.R; +import org.json.JSONException; +import org.json.JSONObject; + +public class ComplaintViewFragment extends Fragment { + // TODO: Rename parameter arguments, choose names that match + // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER + private static final String ARG_PARAM1 = "param1"; + + // TODO: Rename and change types of parameters + private JSONObject mParam1; + + private OnFragmentInteractionListener mListener; + + public ComplaintViewFragment() { + // Required empty public constructor + } + + public static ComplaintViewFragment newInstance(String param1) { + ComplaintViewFragment fragment = new ComplaintViewFragment(); + Bundle args = new Bundle(); + args.putString(ARG_PARAM1, param1); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if (getArguments() != null) { + try { + mParam1 = new JSONObject(getArguments().getString(ARG_PARAM1)); + }catch(JSONException e){ + Log.e("[ERROR]", "JSON error occured while getting params in ComplaintViewFragment"); + } + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_complaint_view, container, false); + TextView address = rootView.findViewById(R.id.cv_address); + TextView comment = rootView.findViewById(R.id.cv_message); + TextView priority = rootView.findViewById(R.id.cv_priority); + TextView comment_action = rootView.findViewById(R.id.cv_response_message); + TextView main_action = rootView.findViewById(R.id.cv_state_text); + ImageView image_main = rootView.findViewById(R.id.cv_image); + ImageView action_image = rootView.findViewById(R.id.cv_state_img); + try { + address.setText(mParam1.getString("address")); + comment.setText(mParam1.getString("content")); + priority.setText(mParam1.getJSONObject("status").getString("priority")); + + main_action.setText("Your complaint is being processed"); + comment_action.setText("Your complaint is being processed"); + action_image.setImageResource(R.drawable.status_pending); + + if(mParam1.getJSONObject("status").getBoolean("status")){ + main_action.setText("Your complaint has been processed"); + comment_action.setText(mParam1.getJSONObject("status").getString("comment")); + action_image.setImageResource(R.drawable.status_done); + } + byte[] decodedString = Base64.decode(mParam1.getString("img"), Base64.DEFAULT); + Bitmap decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length); + image_main.setImageBitmap(decodedByte); + }catch (JSONException e){ + Log.e("[ERROR]","JSONException occured while setting up ComplaintViewFragment"); + } + return rootView; + } + + public void onButtonPressed(Uri uri) { + if (mListener != null) { + mListener.onFragmentInteraction(uri); + } + } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof OnFragmentInteractionListener) { + mListener = (OnFragmentInteractionListener) context; + } else { + throw new RuntimeException(context.toString() + + " must implement OnFragmentInteractionListener"); + } + } + + @Override + public void onDetach() { + super.onDetach(); + mListener = null; + } + + public interface OnFragmentInteractionListener { + // TODO: Update argument type and name + void onFragmentInteraction(Uri uri); + } +} diff --git a/MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/ComplaintsContent.java b/MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/ComplaintsContent.java new file mode 100644 index 0000000..390842c --- /dev/null +++ b/MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/ComplaintsContent.java @@ -0,0 +1,110 @@ +package gq.yigit.mycity.complaintsFragment; + +import android.graphics.Bitmap; +import android.location.Address; +import android.location.Geocoder; +import android.util.Log; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ComplaintsContent { + + public static final List ITEMS = new ArrayList(); + + public static final Map ITEM_MAP = new HashMap(); + + + + public static void addItem(ComplaintItem item) { + ITEMS.add(item); + ITEM_MAP.put(item.id, item); + } + + public static ComplaintItem createComplaintItem(JSONObject obj,Geocoder geocoder, ArrayList stat_imgs) throws JSONException{ + List
addresses = null; + try { + addresses = geocoder.getFromLocation( + Double.parseDouble(obj.getString("lat")), + Double.parseDouble(obj.getString("lng")), + 1); + } catch (IOException ioException) { + // Catch network or other I/O problems. + Log.e("[ERROR]", "Service not available", ioException); + } catch (IllegalArgumentException illegalArgumentException) { + // Catch invalid latitude or longitude values. + Log.e("[ERROR]", "LatLng not appropriate. Lattitude:" + + obj.getString("lat") + + ", Longitude = " + + obj.getString("lng"), illegalArgumentException); + } + Address address = null; + if (!(addresses == null || addresses.size() == 0)) { + address = addresses.get(0); + ArrayList addressFragments = new ArrayList(); + + for(int i = 0; i <= address.getMaxAddressLineIndex(); i++) { + addressFragments.add(address.getAddressLine(i)); + } + Log.i("[INFO]", "Address found " + address.getAddressLine(0)); + } + + Bitmap stat_img = stat_imgs.get(1); + if(obj.getJSONObject("response").getBoolean("status")){ + stat_img = stat_imgs.get(0); + } + return new ComplaintItem(address.getAddressLine(0), + obj.getString("datetime"), + obj.getString("img"), + obj.getJSONObject("response"), + obj.getString("content"), + String.valueOf(ITEMS.size()), + stat_img + ); + } + + + public static class ComplaintItem{ + public final String loc; + public final String datetime; + public final String image; + public final JSONObject status; + public final String content; + public final String id; + public final Bitmap status_img; + public ComplaintItem(String loc, String datetime, String image, JSONObject status, String content, String id, Bitmap status_img) { + this.loc = loc; + this.datetime = datetime; + this.image = image; + this.status = status; + this.content = content; + this.id = id; + this.status_img = status_img; + } + + @Override + public String toString() { + String data = ""; + try{ + JSONObject obj = new JSONObject(); + obj.put("address",loc); + obj.put("datetime",datetime); + obj.put("img",image); + obj.put("status",status); + obj.put("content",content); + + data = obj.toString(); + }catch (JSONException e){ + Log.e("[ERROR]","JSONException occured in ComplaintItem.toString() method"); + } + + return data; + } + } + +} diff --git a/MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/ComplaintsFragment.java b/MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/ComplaintsFragment.java new file mode 100644 index 0000000..c736a00 --- /dev/null +++ b/MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/ComplaintsFragment.java @@ -0,0 +1,134 @@ +package gq.yigit.mycity.complaintsFragment; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.location.Geocoder; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import gq.yigit.mycity.MainActivity; +import gq.yigit.mycity.R; +import gq.yigit.mycity.complaintsFragment.ComplaintsContent.ComplaintItem; +import gq.yigit.mycity.tools.FileActions; +import gq.yigit.mycity.tools.WebRequest; +import org.json.JSONArray; +import org.json.JSONException; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; + + +public class ComplaintsFragment extends Fragment implements WebRequest.responseListener { + + private static final String ARG_COLUMN_COUNT = "column-count"; + private int mColumnCount = 1; + private OnListFragmentInteractionListener mListener; + public static Geocoder geocoder; + public ArrayList stat_imgs; + private RecyclerView recyclerView; + public ComplaintsFragment() { + } + + @SuppressWarnings("unused") + public static ComplaintsFragment newInstance(int columnCount) { + ComplaintsFragment fragment = new ComplaintsFragment(); + Bundle args = new Bundle(); + args.putInt(ARG_COLUMN_COUNT, columnCount); + fragment.setArguments(args); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + if (getArguments() != null) { + mColumnCount = getArguments().getInt(ARG_COLUMN_COUNT); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_complaint_list, container, false); + geocoder = new Geocoder(getContext(), Locale.getDefault()); + HashMap params = new HashMap<>(); + ComplaintsContent.ITEMS.clear(); + ComplaintsContent.ITEM_MAP.clear(); + + try { + params.put("id", MainActivity.userData.getString("id")); + }catch (JSONException e){ + Log.e("[ERROR]","Cannot get id"); + } + stat_imgs = new ArrayList<>(); + stat_imgs.add(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.status_done)); + stat_imgs.add(BitmapFactory.decodeResource(getContext().getResources(), R.drawable.status_pending)); + FileActions file_manager = new FileActions(); + String url = file_manager.readFromFile(getContext(),"server.config").trim(); + + WebRequest request = new WebRequest(url + "/complaints",false,params,0); + request.addListener(this); + request.execute(); + + if (view instanceof RecyclerView) { + Context context = view.getContext(); + recyclerView = (RecyclerView) view; + if (mColumnCount <= 1) { + recyclerView.setLayoutManager(new LinearLayoutManager(context)); + } else { + recyclerView.setLayoutManager(new GridLayoutManager(context, mColumnCount)); + } + + } + return view; + } + + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof OnListFragmentInteractionListener) { + mListener = (OnListFragmentInteractionListener) context; + } else { + } + } + + @Override + public void onDetach() { + super.onDetach(); + mListener = null; + } + + public interface OnListFragmentInteractionListener { + + void onListFragmentInteraction(ComplaintItem item); + } + + @Override + public void receivedResponse(boolean success,String response,int id){ + if(success) { + try { + JSONArray data = new JSONArray(response); + + for (int i = 0; i < data.length(); i++) { + ComplaintItem item =ComplaintsContent.createComplaintItem(data.getJSONObject(i), geocoder, stat_imgs); + ComplaintsContent.addItem(item); + } + } catch (JSONException e) { + Log.e("[ERROR]", "Error occured with complaints response!"); + } + + recyclerView.setAdapter(new MyComplaintRecyclerViewAdapter(ComplaintsContent.ITEMS, mListener)); + } + } +} diff --git a/MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/MyComplaintRecyclerViewAdapter.java b/MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/MyComplaintRecyclerViewAdapter.java new file mode 100644 index 0000000..b057069 --- /dev/null +++ b/MyCity/app/src/main/java/gq/yigit/mycity/complaintsFragment/MyComplaintRecyclerViewAdapter.java @@ -0,0 +1,108 @@ +package gq.yigit.mycity.complaintsFragment; + +import android.graphics.BitmapFactory; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import gq.yigit.mycity.MainActivity; +import gq.yigit.mycity.R; +import org.json.JSONException; + + +import java.util.List; + +public class MyComplaintRecyclerViewAdapter extends RecyclerView.Adapter { + + private final List mValues; + private final ComplaintsFragment.OnListFragmentInteractionListener mListener; + + public MyComplaintRecyclerViewAdapter(List items, ComplaintsFragment.OnListFragmentInteractionListener listener) { + mValues = items; + mListener = listener; + } + + @Override + public MyComplaintRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()) + .inflate(R.layout.votes_list_item, parent, false); + return new MyComplaintRecyclerViewAdapter.ViewHolder(view); + } + + @Override + public void onBindViewHolder(final MyComplaintRecyclerViewAdapter.ViewHolder holder, int position) { + + holder.mItem = mValues.get(position); + holder.mIdView.setText(mValues.get(position).loc); + holder.mContentView.setText(mValues.get(position).datetime); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT + ); + params.height = (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + 50, + MainActivity.pix_density + ); + params.width = (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + 70, + MainActivity.pix_density + ); + params.topMargin = (int) TypedValue.applyDimension( + TypedValue.COMPLEX_UNIT_DIP, + 10, + MainActivity.pix_density + ); + holder.mImageView.setLayoutParams(params); + try { + holder.mImageView.setImageResource(R.drawable.status_pending); + if (mValues.get(position).status.getBoolean("status")) { + holder.mImageView.setImageResource(R.drawable.status_done); + } + }catch (JSONException e){ + Log.e("[ERROR]","An error occured with image"); + } + holder.mView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (null != mListener) { + mListener.onListFragmentInteraction(holder.mItem); + } + } + }); + } + + @Override + public int getItemCount() { + return mValues.size(); + } + + public class ViewHolder extends RecyclerView.ViewHolder { + public final View mView; + public final TextView mIdView; + public final TextView mContentView; + public final ImageView mImageView; + public ComplaintsContent.ComplaintItem mItem; + + public ViewHolder(View view) { + super(view); + mView = view; + mIdView = (TextView) view.findViewById(R.id.item_number); + mContentView = (TextView) view.findViewById(R.id.content); + mImageView = (ImageView) view.findViewById(R.id.vote_img); + } + + @Override + public String toString() { + return super.toString() + " '" + mContentView.getText() + "'"; + } + } +} diff --git a/MyCity/app/src/main/java/gq/yigit/mycity/navigation/TransitFragment.java b/MyCity/app/src/main/java/gq/yigit/mycity/navigation/TransitFragment.java index 657abf5..592a8bb 100644 --- a/MyCity/app/src/main/java/gq/yigit/mycity/navigation/TransitFragment.java +++ b/MyCity/app/src/main/java/gq/yigit/mycity/navigation/TransitFragment.java @@ -123,7 +123,7 @@ public class TransitFragment extends Fragment implements WebRequest.responseList mListener = (OnFragmentInteractionListener) context; } else { throw new RuntimeException(context.toString() - + " must implement OnFragmentInteractionListener"); + + " must implement OnComplaintsClicked"); } } diff --git a/MyCity/app/src/main/java/gq/yigit/mycity/tools/WebRequest.java b/MyCity/app/src/main/java/gq/yigit/mycity/tools/WebRequest.java index 0c96385..f65cc57 100644 --- a/MyCity/app/src/main/java/gq/yigit/mycity/tools/WebRequest.java +++ b/MyCity/app/src/main/java/gq/yigit/mycity/tools/WebRequest.java @@ -80,9 +80,7 @@ public class WebRequest extends AsyncTask { iterator.remove(); } post_request.setEntity(new UrlEncodedFormEntity(pairs)); - Log.d("[BOOKMARK]","Started execute"); response = client.execute(post_request); - Log.d("[BOOKMARK]","Done execute"); }catch (Exception e){ Log.e("[ERROR](request:86): ", e.toString()); } diff --git a/MyCity/app/src/main/java/gq/yigit/mycity/utility/UtilityMain.java b/MyCity/app/src/main/java/gq/yigit/mycity/utility/UtilityMain.java index 8549b37..ba2f62e 100644 --- a/MyCity/app/src/main/java/gq/yigit/mycity/utility/UtilityMain.java +++ b/MyCity/app/src/main/java/gq/yigit/mycity/utility/UtilityMain.java @@ -84,7 +84,7 @@ public class UtilityMain extends Fragment { mListener = (OnFragmentInteractionListener) context; } else { throw new RuntimeException(context.toString() - + " must implement OnFragmentInteractionListener"); + + " must implement OnComplaintsClicked"); } } diff --git a/MyCity/app/src/main/java/gq/yigit/mycity/votesFragment/VoteFragment.java b/MyCity/app/src/main/java/gq/yigit/mycity/votesFragment/VoteFragment.java index e87331b..efc3089 100644 --- a/MyCity/app/src/main/java/gq/yigit/mycity/votesFragment/VoteFragment.java +++ b/MyCity/app/src/main/java/gq/yigit/mycity/votesFragment/VoteFragment.java @@ -95,7 +95,7 @@ public class VoteFragment extends Fragment implements responseListener, imageLis mListener = (OnFragmentInteractionListener) context; } else { throw new RuntimeException(context.toString() - + " must implement OnFragmentInteractionListener"); + + " must implement OnComplaintsClicked"); } } diff --git a/MyCity/app/src/main/res/drawable-v24/side_nav_bar.xml b/MyCity/app/src/main/res/drawable-v24/side_nav_bar.xml index 098108c..247c6b0 100644 --- a/MyCity/app/src/main/res/drawable-v24/side_nav_bar.xml +++ b/MyCity/app/src/main/res/drawable-v24/side_nav_bar.xml @@ -2,8 +2,8 @@ android:shape="rectangle"> \ No newline at end of file diff --git a/MyCity/app/src/main/res/drawable/camera.xml b/MyCity/app/src/main/res/drawable/camera.xml new file mode 100644 index 0000000..6d9be5b --- /dev/null +++ b/MyCity/app/src/main/res/drawable/camera.xml @@ -0,0 +1,4 @@ + + + diff --git a/MyCity/app/src/main/res/drawable/ic_home.xml b/MyCity/app/src/main/res/drawable/ic_home.xml new file mode 100644 index 0000000..051f0d2 --- /dev/null +++ b/MyCity/app/src/main/res/drawable/ic_home.xml @@ -0,0 +1,5 @@ + + + + diff --git a/MyCity/app/src/main/res/drawable/road_cracked.xml b/MyCity/app/src/main/res/drawable/road_cracked.xml new file mode 100644 index 0000000..3be5064 --- /dev/null +++ b/MyCity/app/src/main/res/drawable/road_cracked.xml @@ -0,0 +1,4 @@ + + + diff --git a/MyCity/app/src/main/res/drawable/status_done.xml b/MyCity/app/src/main/res/drawable/status_done.xml new file mode 100644 index 0000000..be7d36b --- /dev/null +++ b/MyCity/app/src/main/res/drawable/status_done.xml @@ -0,0 +1,4 @@ + + + diff --git a/MyCity/app/src/main/res/drawable/status_pending.xml b/MyCity/app/src/main/res/drawable/status_pending.xml new file mode 100644 index 0000000..9591000 --- /dev/null +++ b/MyCity/app/src/main/res/drawable/status_pending.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/MyCity/app/src/main/res/layout/fragment_complaint.xml b/MyCity/app/src/main/res/layout/fragment_complaint.xml new file mode 100644 index 0000000..d8a86df --- /dev/null +++ b/MyCity/app/src/main/res/layout/fragment_complaint.xml @@ -0,0 +1,42 @@ + + + + +