diff --git a/projects/CitiSimApp/.gitignore b/projects/CitiSimApp/.gitignore new file mode 100644 index 00000000..2b75303a --- /dev/null +++ b/projects/CitiSimApp/.gitignore @@ -0,0 +1,13 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild diff --git a/projects/CitiSimApp/.idea/codeStyles/Project.xml b/projects/CitiSimApp/.idea/codeStyles/Project.xml new file mode 100644 index 00000000..30aa626c --- /dev/null +++ b/projects/CitiSimApp/.idea/codeStyles/Project.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/projects/CitiSimApp/.idea/gradle.xml b/projects/CitiSimApp/.idea/gradle.xml new file mode 100644 index 00000000..2996d531 --- /dev/null +++ b/projects/CitiSimApp/.idea/gradle.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/projects/CitiSimApp/.idea/misc.xml b/projects/CitiSimApp/.idea/misc.xml new file mode 100644 index 00000000..af0bbdde --- /dev/null +++ b/projects/CitiSimApp/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/projects/CitiSimApp/.idea/runConfigurations.xml b/projects/CitiSimApp/.idea/runConfigurations.xml new file mode 100644 index 00000000..7f68460d --- /dev/null +++ b/projects/CitiSimApp/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/projects/CitiSimApp/app/.gitignore b/projects/CitiSimApp/app/.gitignore new file mode 100644 index 00000000..796b96d1 --- /dev/null +++ b/projects/CitiSimApp/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/projects/CitiSimApp/app/build.gradle b/projects/CitiSimApp/app/build.gradle new file mode 100644 index 00000000..fedd5b3b --- /dev/null +++ b/projects/CitiSimApp/app/build.gradle @@ -0,0 +1,34 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 28 + defaultConfig { + applicationId "com.main.citisim" + minSdkVersion 15 + targetSdkVersion 28 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'com.google.android.gms:play-services-location:15.0.1' + implementation 'com.google.maps.android:android-maps-utils:0.5+' ///////////////// + implementation 'com.android.support.constraint:constraint-layout:1.1.3' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + implementation 'com.google.android.gms:play-services-maps:16.1.0' + implementation 'com.google.android.gms:play-services-plus:16.0.0' + implementation 'com.android.volley:volley:1.1.1' + +} diff --git a/projects/CitiSimApp/app/proguard-rules.pro b/projects/CitiSimApp/app/proguard-rules.pro new file mode 100644 index 00000000..f1b42451 --- /dev/null +++ b/projects/CitiSimApp/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/projects/CitiSimApp/app/src/androidTest/java/com/main/citisim/ExampleInstrumentedTest.java b/projects/CitiSimApp/app/src/androidTest/java/com/main/citisim/ExampleInstrumentedTest.java new file mode 100644 index 00000000..e268ee1b --- /dev/null +++ b/projects/CitiSimApp/app/src/androidTest/java/com/main/citisim/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.main.citisim; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.main.citisim", appContext.getPackageName()); + } +} diff --git a/projects/CitiSimApp/app/src/main/AndroidManifest.xml b/projects/CitiSimApp/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000..b134fe3c --- /dev/null +++ b/projects/CitiSimApp/app/src/main/AndroidManifest.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/projects/CitiSimApp/app/src/main/java/com/main/citisim/MainActivity.java b/projects/CitiSimApp/app/src/main/java/com/main/citisim/MainActivity.java new file mode 100644 index 00000000..2bcf1236 --- /dev/null +++ b/projects/CitiSimApp/app/src/main/java/com/main/citisim/MainActivity.java @@ -0,0 +1,119 @@ +package com.main.citisim; + +import android.app.Dialog; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import com.android.volley.AuthFailureError; +import com.android.volley.NoConnectionError; +import com.android.volley.Request; +import com.android.volley.Response; +import com.android.volley.TimeoutError; +import com.android.volley.VolleyError; +import com.android.volley.toolbox.JsonObjectRequest; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.GoogleApiAvailability; + +import org.json.JSONObject; + +import java.util.HashMap; + +public class MainActivity extends AppCompatActivity { + + private static final String TAG = "MainActivity"; + private static final int ERROR_DIALOG_REQUEST = 9001; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_main); + + Button addBtn = (Button) findViewById(R.id.addBtn); + addBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + EditText username = (EditText) findViewById(R.id.username); + EditText password = (EditText) findViewById(R.id.password); + final TextView okmsg = (TextView) findViewById(R.id.okmsg); + + + //------LOGARE------- + okmsg.setText(""); + HashMap data = new HashMap(); + data.put("username", username.getText().toString()); + data.put("password", password.getText().toString()); + data.put("rememberMe", true); + + String url =getResources().getString(R.string.api_server)+"/api/authenticate"; + + JsonObjectRequest jsonObjectRequest = new JsonObjectRequest + (Request.Method.POST, url, new JSONObject(data), new Response.Listener() { + + @Override + public void onResponse(JSONObject response) { + okmsg.setText("Response: " + response.toString()); + openMap(); + } + }, new Response.ErrorListener() { + + @Override + public void onErrorResponse(VolleyError error) { + // TODO: Handle error + if(error instanceof TimeoutError || error instanceof NoConnectionError){ + Toast.makeText(getApplicationContext(),"no internet connection",Toast.LENGTH_SHORT).show(); + }else if(error instanceof AuthFailureError){ + Toast.makeText(getApplicationContext(),"wronguser/pass",Toast.LENGTH_SHORT).show(); + } + else{ + Toast.makeText(getApplicationContext(),"????",Toast.LENGTH_SHORT).show(); + } + } + }); + +// Access the RequestQueue through your singleton class. + MyVolleyQueue.getInstance(getApplicationContext()).addToRequestQueue(jsonObjectRequest); + + + //------LOGARE-------// + } + }); + } + + public void openMap(){ + Intent intent = new Intent(this, Map.class); + startActivity(intent); + } + + + public boolean isServicesOK(){ + Log.d(TAG,"isServicesOK: checking google services version"); + + int available = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(MainActivity.this); + + if(available == ConnectionResult.SUCCESS) { + Log.d(TAG,"isServicesOK: Google Play Services is working"); + return true; + } + else if(GoogleApiAvailability.getInstance().isUserResolvableError(available)) { + Log.d(TAG,"isServicesOK: a version error occured"); + Dialog dialog = GoogleApiAvailability.getInstance().getErrorDialog(MainActivity.this,available,ERROR_DIALOG_REQUEST); + dialog.show(); + }else { + Toast.makeText(this,"an error occured",Toast.LENGTH_SHORT).show(); + } + return false; + } + + + + + +} + diff --git a/projects/CitiSimApp/app/src/main/java/com/main/citisim/Map.java b/projects/CitiSimApp/app/src/main/java/com/main/citisim/Map.java new file mode 100644 index 00000000..e3622dda --- /dev/null +++ b/projects/CitiSimApp/app/src/main/java/com/main/citisim/Map.java @@ -0,0 +1,236 @@ +package com.main.citisim; + +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.location.Location; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; +import android.support.v7.app.AppCompatActivity; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.Toast; + +import com.google.android.gms.location.FusedLocationProviderClient; +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.LatLng; +import com.google.android.gms.maps.model.TileOverlay; +import com.google.android.gms.maps.model.TileOverlayOptions; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.Task; +import com.google.maps.android.heatmaps.HeatmapTileProvider; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +public class Map extends AppCompatActivity implements OnMapReadyCallback { + + @Override + public void onMapReady(GoogleMap googleMap) { + mMap = googleMap; + + if (mLocationPermissionsGranted) { + getDeviceLocation(); + if (ActivityCompat.checkSelfPermission(this, + Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, + Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + return; + } + mMap.setMyLocationEnabled(true); + //mMap.getUiSettings(). different settings + } + + } + + private static final String TAG = "Map"; + + private static final String FINE_LOCATION=Manifest.permission.ACCESS_FINE_LOCATION; + private static final String COURSE_LOCATION=Manifest.permission.ACCESS_COARSE_LOCATION; + private static final int LOCATION_PERMISSION_REQUEST_CODE = 1234; + private static final float DEFAULT_ZOOM=15f; + //vars + private Boolean mLocationPermissionsGranted=false; + private GoogleMap mMap; + private FusedLocationProviderClient mFusedLocationProviderClient; + private Button button2; + public static double latitude; + public static double longitude; + + private HeatmapTileProvider mProvider; + + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_map); + + getLocationPermission(); + + button2=(Button)findViewById(R.id.button2); + button2.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + openNewReport(); + } + }); + + } + + + + /////////////////////////////////////////////////////// + + + + private void addHeatMap() { + List list = null; + + // Get the data: latitude/longitude positions of police stations. + try { + list = readItems(R.raw.reports); + } catch (JSONException e) { + Toast.makeText(this, "Problem reading list of locations.", Toast.LENGTH_LONG).show(); + } + + // Create a heat map tile provider, passing it the latlngs of the police stations. + mProvider = new HeatmapTileProvider.Builder() + .data(list) + .build(); + // Add a tile overlay to the map, using the heat map tile provider. + final TileOverlay mOverlay = mMap.addTileOverlay(new TileOverlayOptions().tileProvider(mProvider)); + } + + + private ArrayList readItems(int resource) throws JSONException { + ArrayList list = new ArrayList(); + InputStream inputStream = getResources().openRawResource(resource); + String json = new Scanner(inputStream).useDelimiter("\\A").next(); + JSONArray array = new JSONArray(json); + for (int i = 0; i < array.length(); i++) { + JSONObject object = array.getJSONObject(i); + double lat = object.getDouble("lat"); + double lng = object.getDouble("lng"); + list.add(new LatLng(lat, lng)); + } + return list; + } + + +//////////////////////////////////////////////////////////// + + public void openNewReport(){ + Intent intent = new Intent(this,NewReport.class); + startActivity(intent); + } + + public void getDeviceLocation(){ + mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this); + try { + if(mLocationPermissionsGranted){ + Task location = mFusedLocationProviderClient.getLastLocation(); + location.addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + if(task.isSuccessful()){ + + addHeatMap(); //////////// + Log.d(TAG, "onComplete: found location!"); + Location currentLocation = (Location) task.getResult(); + + moveCamera(new LatLng(currentLocation.getLatitude(),currentLocation.getLongitude()), + DEFAULT_ZOOM ); + + latitude=currentLocation.getLatitude(); + longitude=currentLocation.getLongitude(); + + + + }else{ + Log.d(TAG, "onComplete: current location is null"); + Toast.makeText(Map.this, "unable to get current location", Toast.LENGTH_SHORT).show(); + } + } + }); + } + }catch(SecurityException e){ + Log.e(TAG, "getDeviceLocation: SecurityException: " +e.getMessage() ); + } + } + + + + + private void moveCamera(LatLng latLng, float zoom){ + mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng,zoom)); + } + + private void initMap(){ + SupportMapFragment mapFragment=(SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); + + mapFragment.getMapAsync(Map.this); + } + + private void getLocationPermission(){ + String[] permissions={Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.ACCESS_COARSE_LOCATION}; + + if(ContextCompat.checkSelfPermission(this.getApplicationContext(), + FINE_LOCATION)== PackageManager.PERMISSION_GRANTED) { + if(ContextCompat.checkSelfPermission(this.getApplicationContext(), + COURSE_LOCATION)== PackageManager.PERMISSION_GRANTED) { + mLocationPermissionsGranted = true; + initMap(); + }else{ + ActivityCompat.requestPermissions(this, + permissions, + LOCATION_PERMISSION_REQUEST_CODE); + + } + }else{ + ActivityCompat.requestPermissions(this, + permissions, + LOCATION_PERMISSION_REQUEST_CODE); + + } + + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + mLocationPermissionsGranted = false; + + switch(requestCode) { + case LOCATION_PERMISSION_REQUEST_CODE: { + if(grantResults.length>0) { + for(int i=0;i + cache = new LruCache(20); + + @Override + public Bitmap getBitmap(String url) { + return cache.get(url); + } + + @Override + public void putBitmap(String url, Bitmap bitmap) { + cache.put(url, bitmap); + } + }); + } + + public static synchronized MyVolleyQueue getInstance(Context context) { + if (instance == null) { + instance = new MyVolleyQueue(context); + } + return instance; + } + + public RequestQueue getRequestQueue() { + if (requestQueue == null) { + // getApplicationContext() is key, it keeps you from leaking the + // Activity or BroadcastReceiver if someone passes one in. + requestQueue = Volley.newRequestQueue(ctx.getApplicationContext()); + } + return requestQueue; + } + + public void addToRequestQueue(Request req) { + getRequestQueue().add(req); + } + + public ImageLoader getImageLoader() { + return imageLoader; + } +} \ No newline at end of file diff --git a/projects/CitiSimApp/app/src/main/java/com/main/citisim/NewReport.java b/projects/CitiSimApp/app/src/main/java/com/main/citisim/NewReport.java new file mode 100644 index 00000000..923a29bc --- /dev/null +++ b/projects/CitiSimApp/app/src/main/java/com/main/citisim/NewReport.java @@ -0,0 +1,122 @@ +package com.main.citisim; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.provider.MediaStore; +import android.support.v7.app.AppCompatActivity; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; + +import java.io.FileOutputStream; +import java.io.IOException; + +public class NewReport extends AppCompatActivity { + + //vars + private Button backToReports; + private Button addImage; + private Button submitImage; + ImageView image; + private static final int PICK_IMAGE=100; + Uri imageUri; + EditText latitude; + EditText longitude; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_new_report); + + latitude=(EditText)findViewById(R.id.latitudeView); + longitude=(EditText)findViewById(R.id.longitudeView); + + image=(ImageView)findViewById(R.id.image) ; + backToReports=(Button)findViewById(R.id.backToReports); + backToReports.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + openMap2(); + } + }); + + addImage=(Button)findViewById(R.id.addImage); + addImage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + openGallery(); + } + }); + + submitImage=(Button)findViewById(R.id. submitImage); + submitImage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + + latitude.setText(Double.toString(Map.latitude)); + longitude.setText(Double.toString(Map.longitude)); + //writeToFile(""); + //write to reports.json + + + } + }); + + + } + + + + ////////////////////////////........ + + + public static void writeToFile(Context context, String fileName, String str){ + try{ + FileOutputStream fos = context.openFileOutput(fileName,Context.MODE_PRIVATE); + fos.write(str.getBytes(),0,str.length()); + fos.close(); + }catch (IOException e){ + e.printStackTrace(); + } + } + +///////////////////////////////.......... + + + + + private void openGallery(){ + Intent gallery = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI); + startActivityForResult(gallery, PICK_IMAGE); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data){ + super.onActivityResult(requestCode,resultCode,data); + if(resultCode == RESULT_OK && requestCode == PICK_IMAGE) { + imageUri = data.getData(); + image.setImageURI(imageUri); + //aici imaginea trebuie rotita + //aici imaginea trebuie rotita + //aici imaginea trebuie rotita + //aici imaginea trebuie rotita + } + + + + } + + + + + + public void openMap2(){ + Intent intent = new Intent(this, Map.class); + startActivity(intent); + } + +} diff --git a/projects/CitiSimApp/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/projects/CitiSimApp/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 00000000..1f6bb290 --- /dev/null +++ b/projects/CitiSimApp/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/projects/CitiSimApp/app/src/main/res/drawable/ic_launcher_background.xml b/projects/CitiSimApp/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000..0d025f9b --- /dev/null +++ b/projects/CitiSimApp/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/CitiSimApp/app/src/main/res/drawable/logo.png b/projects/CitiSimApp/app/src/main/res/drawable/logo.png new file mode 100644 index 00000000..fd21090e Binary files /dev/null and b/projects/CitiSimApp/app/src/main/res/drawable/logo.png differ diff --git a/projects/CitiSimApp/app/src/main/res/layout/activity_main.xml b/projects/CitiSimApp/app/src/main/res/layout/activity_main.xml new file mode 100644 index 00000000..33a7d497 --- /dev/null +++ b/projects/CitiSimApp/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,133 @@ + + + + + + + + + + + +