diff --git a/trazador/.gitignore b/trazador/.gitignore
new file mode 100644
index 0000000..c6cbe56
--- /dev/null
+++ b/trazador/.gitignore
@@ -0,0 +1,8 @@
+*.iml
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
diff --git a/trazador/.idea/compiler.xml b/trazador/.idea/compiler.xml
new file mode 100644
index 0000000..96cc43e
--- /dev/null
+++ b/trazador/.idea/compiler.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/trazador/.idea/copyright/profiles_settings.xml b/trazador/.idea/copyright/profiles_settings.xml
new file mode 100644
index 0000000..e7bedf3
--- /dev/null
+++ b/trazador/.idea/copyright/profiles_settings.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/trazador/.idea/encodings.xml b/trazador/.idea/encodings.xml
new file mode 100644
index 0000000..97626ba
--- /dev/null
+++ b/trazador/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/trazador/.idea/gradle.xml b/trazador/.idea/gradle.xml
new file mode 100644
index 0000000..cd2ead8
--- /dev/null
+++ b/trazador/.idea/gradle.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/trazador/.idea/misc.xml b/trazador/.idea/misc.xml
new file mode 100644
index 0000000..5d19981
--- /dev/null
+++ b/trazador/.idea/misc.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/trazador/.idea/modules.xml b/trazador/.idea/modules.xml
new file mode 100644
index 0000000..67de8c2
--- /dev/null
+++ b/trazador/.idea/modules.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/trazador/.idea/runConfigurations.xml b/trazador/.idea/runConfigurations.xml
new file mode 100644
index 0000000..7f68460
--- /dev/null
+++ b/trazador/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/trazador/.idea/vcs.xml b/trazador/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/trazador/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/trazador/README.md b/trazador/README.md
new file mode 100644
index 0000000..7e7f9d4
--- /dev/null
+++ b/trazador/README.md
@@ -0,0 +1,31 @@
+# Trazador
+
+
+
+## Generar el APK
+
+Correr el comando
+
+```
+gradle assemble
+```
+
+Esto generará el APK en el folder /build/apk/
+
+## Características del app
+
+
+1. Grabar una ruta con puntos y paradas
+2. Descartas o finalizar un ruta
+3. Agregar metadatos a la ruta
+
+
+## Por hacer
+
+
+1. Prevenir problemas de pérdida de datos de ubicación debido a una pérdida de coneccion con el servidor.
+2. Separar el SDK para conectarse al servidor del App para poder utilizarlo en otros proyectos.
+3. Refactorizar codigo para adaptarlo a estándares adecuados.
+6. Dibujar al trazado de ruta sobre el mapa
+
+
diff --git a/trazador/app/.gitignore b/trazador/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/trazador/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/trazador/app/build.gradle b/trazador/app/build.gradle
new file mode 100644
index 0000000..e9f05f1
--- /dev/null
+++ b/trazador/app/build.gradle
@@ -0,0 +1,54 @@
+apply plugin: 'com.android.application'
+
+android {
+ compileSdkVersion 24
+ buildToolsVersion "24.0.2"
+ defaultConfig {
+ applicationId "com.example.xavi.trazador_v10"
+ minSdkVersion 16
+ targetSdkVersion 24
+ versionCode 1
+ versionName "1.0"
+ vectorDrawables.useSupportLibrary = true
+ }
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+ }
+ }
+ productFlavors {
+ }
+}
+
+dependencies {
+ compile fileTree(dir: 'libs', include: ['*.jar'])
+ testCompile 'junit:junit:4.12'
+
+ compile 'com.google.code.gson:gson:2.6.2'
+ compile 'com.squareup.okhttp3:okhttp:3.4.2'
+ compile 'com.android.support:appcompat-v7:24.2.1'
+ compile 'com.jakewharton.threetenabp:threetenabp:1.0.4'
+
+ compile 'com.android.support:appcompat-v7:24.2.0'
+
+ compile 'com.android.support:design:24.2.0'
+
+ compile 'org.osmdroid:osmdroid-android:5.5:release@aar'
+
+ compile 'com.github.MKergall:osmbonuspack:6.0'
+
+ compile ('com.mapbox.mapboxsdk:mapbox-android-sdk:4.2.0-beta.4@aar'){
+ transitive=true
+ }
+
+
+
+}
+
+
+
+
+
+
+
diff --git a/trazador/app/proguard-rules.pro b/trazador/app/proguard-rules.pro
new file mode 100644
index 0000000..28c9d78
--- /dev/null
+++ b/trazador/app/proguard-rules.pro
@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in /home/xavi/Android/Sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# 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 *;
+#}
diff --git a/trazador/app/src/androidTest/java/com/example/xavi/trazador_v10/ApplicationTest.java b/trazador/app/src/androidTest/java/com/example/xavi/trazador_v10/ApplicationTest.java
new file mode 100644
index 0000000..6a6ed82
--- /dev/null
+++ b/trazador/app/src/androidTest/java/com/example/xavi/trazador_v10/ApplicationTest.java
@@ -0,0 +1,13 @@
+package com.example.xavi.trazador_v10;
+
+import android.app.Application;
+import android.test.ApplicationTestCase;
+
+/**
+ * Testing Fundamentals
+ */
+public class ApplicationTest extends ApplicationTestCase {
+ public ApplicationTest() {
+ super(Application.class);
+ }
+}
\ No newline at end of file
diff --git a/trazador/app/src/main/AndroidManifest.xml b/trazador/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..4ed4fe4
--- /dev/null
+++ b/trazador/app/src/main/AndroidManifest.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/trazador/app/src/main/btn_savemetadata-web.png b/trazador/app/src/main/btn_savemetadata-web.png
new file mode 100644
index 0000000..e46a8a0
Binary files /dev/null and b/trazador/app/src/main/btn_savemetadata-web.png differ
diff --git a/trazador/app/src/main/ic_launcher-web.png b/trazador/app/src/main/ic_launcher-web.png
new file mode 100644
index 0000000..3106933
Binary files /dev/null and b/trazador/app/src/main/ic_launcher-web.png differ
diff --git a/trazador/app/src/main/java/com/example/xavi/trazador_v10/Finalize.java b/trazador/app/src/main/java/com/example/xavi/trazador_v10/Finalize.java
new file mode 100644
index 0000000..2e479fb
--- /dev/null
+++ b/trazador/app/src/main/java/com/example/xavi/trazador_v10/Finalize.java
@@ -0,0 +1,64 @@
+package com.example.xavi.trazador_v10;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.design.widget.FloatingActionButton;
+import android.support.design.widget.Snackbar;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.View;
+import android.widget.Toast;
+
+public class Finalize extends AppCompatActivity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_finalize);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ FloatingActionButton guardar = (FloatingActionButton) findViewById(R.id.btn_guardar);
+ FloatingActionButton cancelar = (FloatingActionButton) findViewById(R.id.btn_cancelar);
+
+
+
+ guardar.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ MainActivity.state = 0;
+ Toast.makeText(getBaseContext(), "Fin de ruta", Toast.LENGTH_SHORT).show();
+ MainActivity.btnInicio.setBackgroundResource(R.drawable.btn_iniciar);
+
+ MainActivity.trace.finished();
+ Intent intent = new Intent();
+ setResult(RESULT_OK, intent);
+ clearMapMarks();
+ finish();
+
+ }
+ });
+ cancelar.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ MainActivity.state = 0;
+ Toast.makeText(getBaseContext(), "Fin de ruta", Toast.LENGTH_SHORT).show();
+ MainActivity.btnInicio.setBackgroundResource(R.drawable.btn_iniciar);
+ clearMapMarks();
+ MainActivity.trace.discarded();
+ Intent intent = new Intent();
+ setResult(RESULT_OK, intent);
+ finish();
+
+ }
+ });
+ }
+
+ private void clearMapMarks() {
+ for (int x = 0; x< MainActivity.points.size() ; x++ ){
+ MainActivity.map.getOverlays().remove(MainActivity.points.get(x));
+ }
+ MainActivity.points.clear();
+ }
+
+}
diff --git a/trazador/app/src/main/java/com/example/xavi/trazador_v10/GPS_Service.java b/trazador/app/src/main/java/com/example/xavi/trazador_v10/GPS_Service.java
new file mode 100644
index 0000000..230b40a
--- /dev/null
+++ b/trazador/app/src/main/java/com/example/xavi/trazador_v10/GPS_Service.java
@@ -0,0 +1,142 @@
+package com.example.xavi.trazador_v10;
+
+
+import android.Manifest;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.provider.Settings;
+import android.support.annotation.Nullable;
+
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.content.ContextCompat;
+import android.support.v4.content.res.ResourcesCompat;
+import android.widget.Toast;
+
+import com.mapbox.mapboxsdk.geometry.LatLng;
+
+import org.osmdroid.util.GeoPoint;
+import org.osmdroid.views.overlay.Marker;
+
+/**
+ * Created by xavi on 29/09/16.
+ */
+public class GPS_Service extends Service {
+
+ private LocationListener listener;
+ private LocationManager locationManager;
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+
+ @Override
+ public void onCreate() {
+
+
+ listener = new LocationListener() {
+ @Override
+ public void onLocationChanged(Location location) {
+ Intent i = new Intent("location_update");
+ //i.putExtra("coordinates",location.getLongitude() + " " + location.getLatitude());
+
+ double latitude = location.getLatitude();
+ double longitude = location.getLongitude();
+ LatLng newPosition = new LatLng(latitude, longitude);
+
+ i.putExtra("latitude", latitude);
+ i.putExtra("longitude", longitude);
+ i.putExtra("coordinates", location.getLongitude() + " " + location.getLatitude());
+ i.putExtra("newPosition", newPosition);
+
+ sendBroadcast(i);
+ if (MainActivity.state == 1) {
+
+ MainActivity.trace.addPoint(location.getLatitude(), location.getLongitude());
+ GeoPoint position = new GeoPoint(location.getLatitude(), location.getLongitude());
+ String nombre = "punto";
+ addPoint(position, nombre, R.drawable.ic_menu_mylocation);
+
+
+ } else if (MainActivity.state == 2) {
+ //Toast.makeText(getBaseContext(), "Agrega posicion como parada", Toast.LENGTH_SHORT).show();
+ MainActivity.trace.addStop(location.getLatitude(), location.getLongitude());
+ GeoPoint position = new GeoPoint(location.getLatitude(), location.getLongitude());
+ String nombre = "parada";
+ addPoint(position, nombre, R.drawable.ic_launcher);
+ MainActivity.state = 1;
+ }
+
+
+ }
+
+ @Override
+ public void onStatusChanged(String provider, int status, Bundle extras) {
+
+ }
+
+ @Override
+ public void onProviderEnabled(String provider) {
+
+ }
+
+ @Override
+ public void onProviderDisabled(String provider) {
+ Intent i = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
+ i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(i);
+ }
+ };
+
+ locationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
+ //noinspection MissingPermission
+
+
+ locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, listener);
+
+
+
+
+ }
+
+ private void addPoint(GeoPoint position, String nombre, int drawable ) {
+ Marker point;
+ point = new Marker(MainActivity.map);
+ point.setPosition(position);
+ point.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
+
+ Drawable myIcon = ResourcesCompat.getDrawable(getResources(), drawable, null);
+ point.setIcon(myIcon);
+ MainActivity.map.getOverlays().add(point);
+ point.setTitle(nombre);
+ MainActivity.points.add(point);
+ MainActivity.map.invalidate();
+
+ }
+
+ @Override
+ public void onTaskRemoved (Intent rootIntent){
+ MainActivity.trace.discarded();
+ super.onTaskRemoved (rootIntent);
+ }
+ @Override
+ public void onDestroy() {
+
+
+ super.onDestroy();
+ if(locationManager != null)
+ //noinspection MissingPermission
+ locationManager.removeUpdates(listener);
+ }
+
+}
diff --git a/trazador/app/src/main/java/com/example/xavi/trazador_v10/MainActivity.java b/trazador/app/src/main/java/com/example/xavi/trazador_v10/MainActivity.java
new file mode 100644
index 0000000..d288d80
--- /dev/null
+++ b/trazador/app/src/main/java/com/example/xavi/trazador_v10/MainActivity.java
@@ -0,0 +1,305 @@
+package com.example.xavi.trazador_v10;
+
+import android.Manifest;
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+import android.location.SettingInjectorService;
+import android.os.Build;
+import android.provider.Settings;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
+import android.support.v4.content.ContextCompat;
+import android.support.v4.content.res.ResourcesCompat;
+import android.support.v7.app.AppCompatActivity;
+import android.os.Bundle;
+import android.support.v7.util.SortedList;
+import android.telephony.TelephonyManager;
+import android.view.View;
+import android.widget.Button;
+import android.widget.Toast;
+
+import com.jakewharton.threetenabp.AndroidThreeTen;
+
+import org.labexp.traces.Trace;
+import org.osmdroid.tileprovider.constants.OpenStreetMapTileProviderConstants;
+import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
+import org.osmdroid.util.GeoPoint;
+import org.osmdroid.views.MapView;
+import org.osmdroid.views.overlay.ItemizedIconOverlay;
+import org.osmdroid.views.overlay.ItemizedOverlay;
+import org.osmdroid.views.overlay.ItemizedOverlayWithFocus;
+import org.osmdroid.views.overlay.OverlayItem;
+import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider;
+import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.UUID;
+
+
+import org.osmdroid.api.IMapController;
+import org.osmdroid.bonuspack.routing.OSRMRoadManager;
+import org.osmdroid.bonuspack.routing.Road;
+import org.osmdroid.bonuspack.routing.RoadManager;
+import org.osmdroid.views.overlay.Marker;
+import com.mapbox.mapboxsdk.geometry.LatLng;
+import org.osmdroid.views.overlay.PathOverlay;
+import org.osmdroid.views.overlay.Polyline;
+import org.osmdroid.views.overlay.mylocation.IMyLocationProvider;
+
+
+
+
+public class MainActivity extends FragmentActivity implements NoticeDialogFragment.NoticeDialogListener{
+
+ public static Button btnInicio;
+ private FloatingActionButton btnStop;
+ private FloatingActionButton btnInfo;
+
+
+ public static Trace trace;
+
+ private Button btnParada;
+ boolean isPressed = false;
+
+ private BroadcastReceiver broadcastReceiver;
+
+ Location location;
+
+ private LocationManager locationManager;
+ private LocationListener locationListener;
+
+
+
+
+ private double latitud = 0.0;
+ private double longitud = 0.0;
+
+
+
+ static MapView map;
+ static Marker actualPositionMarker;
+
+ static ArrayList points = new ArrayList<>();
+
+
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ //important! set your user agent to prevent getting banned from the osm servers
+ OpenStreetMapTileProviderConstants.setUserAgentValue(BuildConfig.APPLICATION_ID);
+
+
+ Intent i = new Intent(getApplicationContext(),GPS_Service.class);
+ startService(i);
+
+ btnInicio = (Button) findViewById(R.id.btn_iniciar);
+ btnStop = (FloatingActionButton) findViewById(R.id.btn_stop);
+ btnInfo = (FloatingActionButton) findViewById(R.id.btn_info);
+
+
+
+ map = (MapView) findViewById(R.id.map);
+
+ map.setTileSource(TileSourceFactory.MAPNIK);
+ map.setBuiltInZoomControls(true);
+ map.setMultiTouchControls(true);
+ map.getController().setZoom(18);
+
+
+
+ if(!runtime_permissions()) {
+ enable_buttons();
+ }
+ AndroidThreeTen.init(this);
+
+
+
+
+ }
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if(broadcastReceiver == null){
+ broadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ /*Toast.makeText(getApplicationContext(), "Lat: " + intent.getExtras().get("latitude") + "Long: " +
+ intent.getExtras().get("longitude"),
+ Toast.LENGTH_LONG).show();*/
+
+ latitud = Double.parseDouble(intent.getExtras().get("latitude").toString());
+ longitud = Double.parseDouble(intent.getExtras().get("longitude").toString());
+
+ GeoPoint position = new GeoPoint(latitud,longitud);
+ map.getController().setCenter(position);
+
+
+
+ marketCurrentPosition(position);
+
+ }
+ };
+ }
+
+ registerReceiver(broadcastReceiver, new IntentFilter("location_update"));
+ }
+
+ private void marketCurrentPosition(GeoPoint position) {
+ map.getOverlays().remove(actualPositionMarker);
+ actualPositionMarker = new Marker(map);
+ actualPositionMarker.setPosition(position);
+ actualPositionMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
+ Drawable myIcon = ResourcesCompat.getDrawable(getResources(), R.drawable.ic_follow_me, null);
+ actualPositionMarker.setIcon(myIcon);
+ map.getOverlays().add(actualPositionMarker);
+ map.invalidate();
+
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if(broadcastReceiver != null){
+ unregisterReceiver(broadcastReceiver);
+ }
+ }
+
+ static int state = 0;
+ private void enable_buttons(){
+
+
+ btnInicio.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ if (v == btnInicio && state == 0) {
+ final TelephonyManager tm = (TelephonyManager) getBaseContext().getSystemService(Context.TELEPHONY_SERVICE);
+ final String tmDevice, tmSerial, androidId;
+ tmDevice = "" + tm.getDeviceId();
+ tmSerial = "" + tm.getSimSerialNumber();
+ androidId = "" + android.provider.Settings.Secure.getString(getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
+ UUID deviceUuid = new UUID(androidId.hashCode(), ((long)tmDevice.hashCode() << 32) | tmSerial.hashCode());
+ String deviceId = deviceUuid.toString();
+ MainActivity.trace = new Trace(deviceId);
+
+ try {
+ MainActivity.trace.start("http://buses.tec.siua.ac.cr");
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ state = 1;
+ //Toast.makeText(getBaseContext(), "Inicio de ruta", Toast.LENGTH_SHORT).show();
+ btnInicio.setBackgroundResource( R.drawable.btn_parada);
+ GeoPoint parada = new GeoPoint(latitud, longitud);
+ marketCurrentPosition(parada);
+ }
+ else if (v == btnInicio && state == 1){
+ state = 2;
+ }
+ }
+ });
+
+ btnStop.setOnClickListener(new View.OnClickListener(){
+ @Override
+ public void onClick (View v){
+ if (state != 0) {
+ Intent myIntent = new Intent(getApplicationContext(), Finalize.class);
+ startActivityForResult(myIntent, 0);
+ }
+
+ }
+
+ });
+
+ btnInfo.setOnClickListener(new View.OnClickListener(){
+ @Override
+ public void onClick (View v){
+
+ Intent myIntent = new Intent(getApplicationContext(), metadata.class);
+ startActivityForResult(myIntent, 0);
+
+ }
+
+ });
+
+
+
+ }
+
+
+ private boolean runtime_permissions(){
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ContextCompat.checkSelfPermission(this,Manifest.permission
+ .ACCESS_FINE_LOCATION)!=PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this,
+ Manifest.permission.ACCESS_COARSE_LOCATION ) != PackageManager.PERMISSION_GRANTED
+ && ContextCompat.checkSelfPermission(this,
+ Manifest.permission.READ_PHONE_STATE ) != PackageManager.PERMISSION_GRANTED){
+ requestPermissions(new String[]{
+ Manifest.permission.ACCESS_FINE_LOCATION,
+ Manifest.permission.ACCESS_NETWORK_STATE,
+ Manifest.permission.ACCESS_COARSE_LOCATION,
+ Manifest.permission.WRITE_EXTERNAL_STORAGE,
+ Manifest.permission.READ_PHONE_STATE,
+ Manifest.permission.INTERNET}, 100);
+
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+
+ if(requestCode == 100){
+
+ if(grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager
+ .PERMISSION_GRANTED){
+ enable_buttons();
+ }else {
+ runtime_permissions();
+ }
+
+
+ }
+ }
+
+ public void showNoticeDialog() {
+ // Create an instance of the dialog fragment and show it
+ DialogFragment dialog = new NoticeDialogFragment();
+ dialog.show(getSupportFragmentManager(), "NoticeDialogFragment");
+
+
+
+ }
+
+
+ @Override
+ public void onDialogPositiveClick(DialogFragment dialog) {
+
+ Toast.makeText(getBaseContext(),"Aceptar",Toast.LENGTH_SHORT).show();
+
+ }
+
+ @Override
+ public void onDialogNegativeClick(DialogFragment dialog) {
+
+ Toast.makeText(getBaseContext(),"Cancelar",Toast.LENGTH_SHORT).show();
+
+ }
+}
+
diff --git a/trazador/app/src/main/java/com/example/xavi/trazador_v10/NoticeDialogFragment.java b/trazador/app/src/main/java/com/example/xavi/trazador_v10/NoticeDialogFragment.java
new file mode 100644
index 0000000..0ce0073
--- /dev/null
+++ b/trazador/app/src/main/java/com/example/xavi/trazador_v10/NoticeDialogFragment.java
@@ -0,0 +1,37 @@
+package com.example.xavi.trazador_v10;
+
+import android.app.Activity;
+import android.support.v4.app.DialogFragment;
+
+/**
+ * Created by xavi on 06/10/16.
+ */
+public class NoticeDialogFragment extends DialogFragment {
+
+ /* The activity that creates an instance of this dialog fragment must
+ * implement this interface in order to receive event callbacks.
+ * Each method passes the DialogFragment in case the host needs to query it. */
+ public interface NoticeDialogListener {
+ public void onDialogPositiveClick(DialogFragment dialog);
+ public void onDialogNegativeClick(DialogFragment dialog);
+ }
+
+ // Use this instance of the interface to deliver action events
+ NoticeDialogListener mListener;
+
+ // Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ // Verify that the host activity implements the callback interface
+ try {
+ // Instantiate the NoticeDialogListener so we can send events to the host
+ mListener = (NoticeDialogListener) activity;
+ } catch (ClassCastException e) {
+ // The activity doesn't implement the interface, throw exception
+ throw new ClassCastException(activity.toString()
+ + " must implement NoticeDialogListener");
+ }
+ }
+
+}
diff --git a/trazador/app/src/main/java/com/example/xavi/trazador_v10/metadata.java b/trazador/app/src/main/java/com/example/xavi/trazador_v10/metadata.java
new file mode 100644
index 0000000..ac0af5f
--- /dev/null
+++ b/trazador/app/src/main/java/com/example/xavi/trazador_v10/metadata.java
@@ -0,0 +1,66 @@
+package com.example.xavi.trazador_v10;
+
+import android.os.Bundle;
+import android.support.design.widget.FloatingActionButton;
+import android.support.design.widget.Snackbar;
+import android.support.design.widget.TextInputEditText;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.Toolbar;
+import android.view.View;
+import android.content.Intent;
+import android.widget.EditText;
+
+public class metadata extends AppCompatActivity {
+
+ EditText Codigo;
+ EditText Nombre;
+ EditText Costo;
+
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_metadata);
+ Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
+ setSupportActionBar(toolbar);
+
+ FloatingActionButton btnGuardar;
+ FloatingActionButton btnCancelar;
+ Codigo = (EditText) findViewById(R.id.editText);
+ Nombre = (EditText) findViewById(R.id.editText2);
+ Costo = (EditText) findViewById(R.id.editText3);
+
+ btnGuardar = (FloatingActionButton) findViewById(R.id.btn_guardar);
+ btnCancelar = (FloatingActionButton) findViewById(R.id.btn_cancelar);
+
+ btnGuardar.setOnClickListener(new View.OnClickListener(){
+ @Override
+ public void onClick (View v){
+ String textCodigo = Codigo.getText().toString();
+ String textNombre = Nombre.getText().toString();
+ String textCosto = Costo.getText().toString();
+ MainActivity.trace.setMetadata(textCodigo, textNombre, textCosto);
+
+ Intent intent = new Intent();
+ setResult(RESULT_OK, intent);
+ finish();
+ }
+ });
+
+ btnCancelar.setOnClickListener(new View.OnClickListener(){
+ @Override
+ public void onClick (View v){
+
+ Intent intent = new Intent();
+ setResult(RESULT_OK, intent);
+ finish();
+
+
+ }
+
+ });
+
+ }
+
+}
diff --git "a/trazador/app/src/main/java/org/Icon\r" "b/trazador/app/src/main/java/org/Icon\r"
new file mode 100644
index 0000000..e69de29
diff --git "a/trazador/app/src/main/java/org/labexp/Icon\r" "b/trazador/app/src/main/java/org/labexp/Icon\r"
new file mode 100644
index 0000000..e69de29
diff --git a/trazador/app/src/main/java/org/labexp/traces/ApiConnector.java b/trazador/app/src/main/java/org/labexp/traces/ApiConnector.java
new file mode 100644
index 0000000..15d4556
--- /dev/null
+++ b/trazador/app/src/main/java/org/labexp/traces/ApiConnector.java
@@ -0,0 +1,481 @@
+package org.labexp.traces;
+
+/*
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.ClientResponse;
+import com.sun.jersey.api.client.WebResource;
+
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+
+import com.sun.jersey.api.json.JSONConfiguration;
+import com.sun.jersey.json.impl.provider.entity.JSONListElementProvider;
+import com.sun.jersey.api.client.config.ClientConfig;
+
+
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+*/
+import android.os.Build;
+import android.support.annotation.RequiresApi;
+
+import okhttp3.MediaType;
+import okhttp3.OkHttpClient;
+
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.concurrent.ExecutionException;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.json.JSONArray;
+import org.threeten.bp.Instant;
+import org.threeten.bp.ZoneId;
+import org.threeten.bp.ZonedDateTime;
+import org.threeten.bp.format.DateTimeFormatter;
+
+/**
+ * This class is a direct connection to the API server .
+ */
+public class ApiConnector {
+ /**
+ * jersey client to connect the server.
+ */
+ private static OkHttpClient client;
+ /*private static Client client;
+ /**
+ * Server url.
+ */
+ private static String apiBaseUrl ;
+ /**
+ * Format to save date on the server.
+ */
+ private static final String DATE_FORMAT = "MM/dd/yyyy HH:mm:ss";
+ /**
+ * sub-url to Post trace start.
+ */
+ private static final String POST_START_TRACE = "/buses/v0.1/trace";
+ /**
+ * sub-url to Post a list of points.
+ */
+ private static final String POST_POINTS = "/buses/v0.1/trace//points";
+ /**
+ * sub-url to Post a stop point.
+ */
+ private static final String POST_STOP = "/buses/v0.1/trace//stop";
+ /**
+ * sub-url to put metadata
+ */
+ private static final String PUT_METADATA = "/buses/v0.1/trace//metadata";
+ /**
+ * sub-url to finalize trace.
+ */
+ private static final String PUT_FINALIZE = "/buses/v0.1/trace/";
+ /**
+ * server response ok.
+ */
+ private static final int OK_RESPONSE = 200;
+
+ public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
+
+ public static String localtraceId = "";
+
+
+ /**
+ * Starts Jersey client.
+ */
+ public static void createClient(String url) {
+ apiBaseUrl = url;
+
+
+ /*
+ ClientConfig clientConfig = new DefaultClientConfig();
+ clientConfig.getFeatures().put(
+ JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
+ client = Client.create(clientConfig);
+ */
+ }
+ /**
+ * Starts trace on server.
+ * @param deviceId A unique identificator for the client device.
+ * @return unique trace identificator
+ */
+ public static String startTrace(final String deviceId) throws java.io.IOException{
+ /*
+ // Creates a webResource with the API
+ WebResource webResource = client.resource(apiBaseUrl + POST_START_TRACE);
+ */
+ // Building the Post content
+ String jsonInput = "";
+ try {
+ jsonInput = new JSONObject()
+ .put("deviceId", deviceId)
+ .put("timestamp", getDate())
+ .toString();
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ Post async = new Post();
+ try {
+ async.execute(apiBaseUrl + POST_START_TRACE, jsonInput, "Post").get();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (ExecutionException e) {
+ e.printStackTrace();
+ }
+
+
+
+ /*
+ // POST method
+ ClientResponse response = webResource
+ .accept("application/json")
+ .type("application/json")
+ .Post(ClientResponse.class, jsonInput);
+
+ // Check response status code
+ if (response.getStatus() != OK_RESPONSE) {
+ throw new RuntimeException(
+ "Failed : HTTP error code : " + response.getStatus());
+ }
+
+ // Reads response
+ String output = response.getEntity(String.class);
+ String traceId = "";
+
+ try {
+ JSONObject result = new JSONObject(output);
+ traceId = result.getString("traceId");
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ return traceId;
+*/
+ return "";
+ }
+
+ /**
+ * @param deviceId unique device id
+ * @param traceId unique trace id
+ * @param points list of points to be add
+ * @return server response
+ * @throws RuntimeException server connection error
+ */
+ public static boolean addPoints(
+ final String deviceId,
+ final String traceId,
+ final ArrayList points)throws RuntimeException {
+
+ /*
+ // Creates a webResource with the API url to Post start a trace
+ WebResource webResource = client.resource(
+ apiBaseUrl + POST_POINTS.replaceFirst("\\{traceId\\}", traceId));
+ */
+ // Building the Post content
+
+ String url = apiBaseUrl + POST_POINTS.replaceFirst("", localtraceId);
+ String jsonInput = "";
+ try {
+
+ JSONArray jsonPointList = new JSONArray();
+ for (MapPoint point : points){
+ JSONObject pointElement = new JSONObject()
+ .put("latitude", point.getX()+"")
+ .put("longitude", point.getY()+"");
+ jsonPointList.put(pointElement);
+ }
+
+ jsonInput = new JSONObject()
+ .put("deviceId", deviceId)
+ .put("timestamp", getDate())
+ .put("points", jsonPointList)
+ .toString();
+ System.out.println(jsonInput);
+ post(url, jsonInput);
+
+ } catch (JSONException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+
+ /*
+ // POST method
+ ClientResponse response = webResource
+ .accept("application/json")
+ .type("application/json")
+ .Post(ClientResponse.class, jsonInput);
+
+ // Check response status code
+ if (response.getStatus() != OK_RESPONSE) {
+ throw new RuntimeException(
+ "Failed : HTTP error code : " + response.getStatus());
+ }
+ else{
+ return true;
+ }
+ */
+ return true;
+
+ }
+
+
+ /**
+ * @param deviceId unique device id
+ * @param traceId unique trace id
+ * @param stop stop position
+ * @return server response
+ * @throws RuntimeException server connection error
+ */
+ public static boolean addStop(
+ final String deviceId,
+ final String traceId,
+ final MapPoint stop)throws RuntimeException {
+/*
+ // Creates a webResource with the API url
+ WebResource webResource = client.resource(
+ apiBaseUrl + POST_STOP.replaceFirst("\\{traceId\\}", traceId));
+*/
+ // Building the Post content
+ String url = apiBaseUrl + POST_STOP.replaceFirst("", localtraceId);
+ String jsonInput = "";
+ try {
+
+
+ JSONObject pointElement =
+ new JSONObject()
+ .put("latitude", stop.getX()+"")
+ .put("longitude", stop.getY()+"");
+
+ jsonInput = new JSONObject()
+ .put("deviceId", deviceId)
+ .put("timestamp", getDate())
+ .put("stop", pointElement)
+ .toString();
+ System.out.println(jsonInput);
+ post(url, jsonInput);
+
+ } catch (JSONException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ /*
+ // POST method
+ ClientResponse response = webResource
+ .accept("application/json")
+ .type("application/json")
+ .Post(ClientResponse.class, jsonInput);
+
+ // Check response status code
+ if (response.getStatus() != OK_RESPONSE) {
+ throw new RuntimeException(
+ "Failed : HTTP error code : " + response.getStatus());
+ }
+ else{
+ return true;
+ }
+ */
+ return true;
+
+ }
+
+ /**
+ * @param deviceId unique device id
+ * @param traceId unique trace id
+ * @param metadata information about the trace
+ * @return server response
+ * @throws RuntimeException server connection error
+ */
+ public static boolean setMetadata(
+ final String deviceId,
+ final String traceId,
+ final Metadata metadata)throws RuntimeException {
+/*
+ // Creates a webResource with the API url
+ WebResource webResource = client.resource(
+ apiBaseUrl + PUT_METADATA.replaceFirst("\\{traceId\\}", traceId));
+*/
+ String url = apiBaseUrl + PUT_METADATA.replaceFirst("", localtraceId);
+ // Building the put content
+ String jsonInput = "";
+ try {
+
+ jsonInput = new JSONObject()
+ .put("deviceId", deviceId)
+ .put("timestamp", getDate())
+ .put("routeCode", metadata.getRouteCode())
+ .put("routeName", metadata.getRouteName())
+ .put("routePrice", metadata.getRoutePrice())
+ .toString();
+ put(url, jsonInput);
+
+ } catch (JSONException e) {
+
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ /*
+ // Put method
+ ClientResponse response = webResource
+ .accept("application/json")
+ .type("application/json")
+ .put(ClientResponse.class, jsonInput);
+
+ // Check response status code
+ if (response.getStatus() != OK_RESPONSE) {
+ throw new RuntimeException(
+ "Failed : HTTP error code : " + response.getStatus());
+ }
+ else{
+ return true;
+ }
+ */
+ return true;
+
+ }
+
+ /**
+ * @param traceId unique trace id
+ * @return server response
+ * @throws RuntimeException server connection error
+ */
+ public static boolean finished(
+ final String traceId)throws RuntimeException {
+/*
+ // Creates a webResource with the API url
+ WebResource webResource = client.resource(
+ apiBaseUrl + PUT_FINALIZE.replaceFirst("\\{traceId\\}", traceId));
+*/
+ String url = apiBaseUrl + PUT_FINALIZE.replaceFirst("", localtraceId);
+ // Building the Post content
+ String jsonInput = "";
+ try {
+
+ jsonInput = new JSONObject()
+ .put("status", "finished")
+ .toString();
+ put(url, jsonInput);
+
+ } catch (JSONException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ /*
+ // PUT method
+ ClientResponse response = webResource
+ .accept("application/json")
+ .type("application/json")
+ .put(ClientResponse.class, jsonInput);
+
+ // Check response status code
+ if (response.getStatus() != OK_RESPONSE) {
+ throw new RuntimeException(
+ "Failed : HTTP error code : " + response.getStatus());
+ }
+ else{
+ return true;
+ }
+ */
+ return true;
+
+ }
+
+ /**
+ * @param traceId unique trace id
+ * @return server response
+ * @throws RuntimeException server connection error
+ */
+ public static boolean discarded(
+ final String traceId)throws RuntimeException {
+
+ /*
+ // Creates a webResource with the API url
+ WebResource webResource = client.resource(
+ apiBaseUrl + PUT_FINALIZE.replaceFirst("\\{traceId\\}", traceId));
+*/
+ String url = apiBaseUrl + PUT_FINALIZE.replaceFirst("", localtraceId);
+ // Building the Post content
+ String jsonInput = "";
+ try {
+
+ jsonInput = new JSONObject()
+ .put("status", "discarded")
+ .toString();
+
+ put(url, jsonInput);
+
+ } catch (JSONException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ /*
+ // PUT method
+ ClientResponse response = webResource
+ .accept("application/json")
+ .type("application/json")
+ .put(ClientResponse.class, jsonInput);
+
+ // Check response status code
+ if (response.getStatus() != OK_RESPONSE) {
+ throw new RuntimeException(
+ "Failed : HTTP error code : " + response.getStatus());
+ }
+ else{
+ return true;
+ }
+ */
+ return true;
+
+ }
+
+ /**
+ * Calculates timeZone and formats date into a string.
+ * @return Date with the format of @DATE_FORMAT.
+ */
+ private static String getDate() {
+
+ Instant instant = Instant.now();
+ ZoneId zoneId = ZoneId.of( "America/Costa_Rica" );
+ ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
+ DateTimeFormatter dtfOut = DateTimeFormatter.ofPattern(DATE_FORMAT);
+ return zdt.format(dtfOut).toString();
+
+
+
+ }
+
+ public Instant now() {
+ return Instant.now();
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.KITKAT)
+
+ static String post(String url, String json) throws java.io.IOException {
+ Post async = new Post();
+ async.execute(url, json);
+ return "";
+
+
+ }
+
+ static String put(String url, String json) throws java.io.IOException {
+ Put async = new Put();
+ async.execute(url, json);
+ return "";
+
+
+ }
+
+
+}
diff --git a/trazador/app/src/main/java/org/labexp/traces/MapPoint.java b/trazador/app/src/main/java/org/labexp/traces/MapPoint.java
new file mode 100644
index 0000000..b18faf8
--- /dev/null
+++ b/trazador/app/src/main/java/org/labexp/traces/MapPoint.java
@@ -0,0 +1,68 @@
+
+package org.labexp.traces;
+
+/**
+ * @author Leo
+ *
+ */
+public class MapPoint {
+ /*
+ * Represents position over latitude.
+ */
+ private double x;
+ /*
+ * Represents position over longitude.
+ */
+ private double y;
+
+ /**
+ * New MapPoint based on latitude and longitude values.
+ * @param x Latitude.
+ * @param y Longitude.
+ */
+ public MapPoint(final double x, final double y) {
+ this.x = x;
+ this.y = y;
+ }
+ /**
+ * Get Latitude.
+ * @return latitude
+ */
+ public double getX() {
+ return x;
+ }
+
+ /**
+ * Set Latitude.
+ * @param x latitude
+ */
+ public void setX(final double x) {
+ this.x = x;
+ }
+
+ /**
+ * Get Longitude.
+ * @return longitude
+ */
+ public double getY() {
+ return y;
+ }
+
+ /**
+ * Set longitude.
+ * @param y longitude
+ */
+ public void setY(final double y) {
+ this.y = y;
+ }
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "MapPoint [latitude=" + x + ", longitude=" + y + "]";
+ }
+
+
+
+}
diff --git a/trazador/app/src/main/java/org/labexp/traces/Metadata.java b/trazador/app/src/main/java/org/labexp/traces/Metadata.java
new file mode 100644
index 0000000..c80751b
--- /dev/null
+++ b/trazador/app/src/main/java/org/labexp/traces/Metadata.java
@@ -0,0 +1,76 @@
+package org.labexp.traces;
+
+/**
+ * Used to save the metadata related to a trace
+ * @author Leo
+ *
+ */
+public class Metadata {
+ /**
+ * The code of the route.
+ */
+ private String routeCode;
+ /**
+ * The name of the route.
+ */
+ private String routeName;
+ /**
+ * The price of the route.
+ */
+ private String routePrice;
+ /**
+ * @return the route code
+ */
+ public String getRouteCode() {
+ return routeCode;
+ }
+ /**
+ * @param routeCode the route code to set
+ */
+ public void setRouteCode(final String routeCode) {
+ this.routeCode = routeCode;
+ }
+ /**
+ * @return the route name
+ */
+ public String getRouteName() {
+ return routeName;
+ }
+ /**
+ * @param routeName the route name to set
+ */
+ public void setRouteName(final String routeName) {
+ this.routeName = routeName;
+ }
+ /**
+ * @return the route price
+ */
+ public String getRoutePrice() {
+ return routePrice;
+ }
+ /**
+ * @param routePrice the route price to set
+ */
+ public void setRoutePrice(final String routePrice) {
+ this.routePrice = routePrice;
+ }
+ /**
+ * @param routeCode code
+ * @param routeName name
+ * @param routePrice price
+ */
+ public Metadata(final String routeCode, final String routeName, final String routePrice) {
+ super();
+ this.routeCode = routeCode;
+ this.routeName = routeName;
+ this.routePrice = routePrice;
+ }
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ return "Metadata [Code=" + routeCode + ", Name=" + routeName + ", Price=" + routePrice + "]";
+ }
+
+}
diff --git a/trazador/app/src/main/java/org/labexp/traces/Put.java b/trazador/app/src/main/java/org/labexp/traces/Put.java
new file mode 100644
index 0000000..236e15d
--- /dev/null
+++ b/trazador/app/src/main/java/org/labexp/traces/Put.java
@@ -0,0 +1,56 @@
+package org.labexp.traces;
+
+import android.os.AsyncTask;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+
+import static org.labexp.traces.ApiConnector.JSON;
+
+
+class Put extends AsyncTask {
+
+
+ private static OkHttpClient client;
+
+ String response;
+
+ protected String doInBackground(String... params) {
+ if (client == null){
+ client = new OkHttpClient();
+ }
+ String sb = params[1];
+ RequestBody body = RequestBody.create(JSON, sb);
+
+
+ Request request = new Request.Builder()
+ .url(params[0])
+ .put(body)
+ .build();
+
+
+ try (Response response = client.newCall( request).execute()) {
+ if (params.length >2 )
+ if (params[2].equals("Post")){
+ JSONObject jsonObj = new JSONObject(ApiConnector.localtraceId = response.body().string());
+ ApiConnector.localtraceId = jsonObj.getString("traceId");
+
+ }
+ }
+ catch (java.io.IOException x) {
+ return "null";
+
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return "";
+
+
+ }
+
+}
diff --git a/trazador/app/src/main/java/org/labexp/traces/Trace.java b/trazador/app/src/main/java/org/labexp/traces/Trace.java
new file mode 100644
index 0000000..7eb3745
--- /dev/null
+++ b/trazador/app/src/main/java/org/labexp/traces/Trace.java
@@ -0,0 +1,162 @@
+/**
+ *
+ */
+package org.labexp.traces;
+
+import java.util.ArrayList;
+
+/**
+ * @author Leo
+ *
+ */
+public class Trace {
+ /*
+ * Trace identifier (provide by the server)
+ */
+ private String traceId;
+ /*
+ * Device identifier (provide by the user)
+ */
+ private String deviceId;
+ /*
+ * The url of the Api server
+ */
+ private String apiBaseUrl;
+ /**
+ * @return the trace id
+ */
+ public final String getTraceId() {
+ return traceId;
+ }
+ /**
+ * @return the device id
+ */
+ public final String getDeviceId() {
+ return deviceId;
+ }
+
+
+ /**
+ * @return the apiBaseUrl
+ */
+ public String getApiBaseUrl() {
+ return apiBaseUrl;
+ }
+
+ /**
+ * Creates a trace using a unique device identificator.
+ * @param deviceId
+ */
+ public Trace(String deviceId) {
+ super();
+ this.deviceId = deviceId;
+ }
+
+ /**
+ * Starts the trace on the server.
+ * @param apiBaseUrl the base url of the API Server:
+ * example: "http://10.173.1.153"
+ * @return a unique trace id and this is saved on traceId
+ *
+ */
+ public void start(String apiBaseUrl) throws java.io.IOException{
+ this.apiBaseUrl = apiBaseUrl;
+ ApiConnector.createClient(apiBaseUrl);
+ this.traceId = ApiConnector.startTrace (deviceId);
+ }
+
+ /**
+ * @param routeCode code
+ * @param routeName name
+ * @param routePrice prices
+ * @return transaction success
+ */
+ public boolean setMetadata(
+ final String routeCode,
+ final String routeName,
+ final String routePrice) {
+ Metadata metadata = new Metadata(routeCode, routeName, routePrice);
+ setMetadata(metadata);
+ return true;
+ }
+
+ /**
+ * @param metadata trace metadata
+ * @return transaction success
+ */
+ public boolean setMetadata(final Metadata metadata) {
+ return ApiConnector.setMetadata(deviceId, traceId, metadata);
+
+ }
+
+ /**
+ * @param points List of points to add
+ * @return transaction success
+ */
+ public boolean addPoints(final ArrayList points) {
+ return ApiConnector.addPoints(deviceId, traceId, points);
+ }
+
+ /**
+ * @param x latitude.
+ * @param y longitude.
+ * @return transaction success
+ */
+ public boolean addPoint(final double x, final double y) {
+ MapPoint point = new MapPoint(x, y);
+ ArrayList points = new ArrayList();
+ points.add(point);
+ addPoints (points);
+ return true;
+ }
+
+ /**
+ * @param point position
+ * @return transaction success
+ */
+ public boolean addPoint(final MapPoint point) {
+ ArrayList points = new ArrayList();
+ points.add(point);
+ addPoints (points);
+ return true;
+ }
+
+ /**
+ * @param stop stop position
+ * @return transaction success
+ */
+ public boolean addStop(final MapPoint stop) {
+ return ApiConnector.addStop(deviceId, traceId, stop);
+ }
+
+ /**
+ * @param x latitude.
+ * @param y longitude.
+ * @return transaction success
+ */
+ public boolean addStop(final double x, final double y) {
+ MapPoint point = new MapPoint(x, y);
+ return addStop(point);
+ }
+
+
+
+ /**
+ * Mark trace as finished on the server
+ * @return transaction success
+ */
+ public boolean finished() {
+ ApiConnector.finished(traceId);
+ return true;
+ }
+
+ /**
+ * Mark trace as finished on the server
+ * @return transaction success
+ */
+ public boolean discarded() {
+ ApiConnector.discarded(traceId);
+ return true;
+ }
+
+}
diff --git a/trazador/app/src/main/java/org/labexp/traces/post.java b/trazador/app/src/main/java/org/labexp/traces/post.java
new file mode 100644
index 0000000..e89bb89
--- /dev/null
+++ b/trazador/app/src/main/java/org/labexp/traces/post.java
@@ -0,0 +1,56 @@
+package org.labexp.traces;
+
+import android.os.AsyncTask;
+
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.json.JSONArray;
+
+import static org.labexp.traces.ApiConnector.JSON;
+
+
+class Post extends AsyncTask {
+
+
+ private static OkHttpClient client;
+
+ String response;
+
+ protected String doInBackground(String... params) {
+ if (client == null){
+ client = new OkHttpClient();
+ }
+ String sb = params[1];
+ RequestBody body = RequestBody.create(JSON, sb);
+
+
+ Request request = new Request.Builder()
+ .url(params[0])
+ .post(body)
+ .build();
+
+
+ try (Response response = client.newCall( request).execute()) {
+ if (params.length >2 )
+ if (params[2].equals("Post")){
+ JSONObject jsonObj = new JSONObject(ApiConnector.localtraceId = response.body().string());
+ ApiConnector.localtraceId = jsonObj.getString("traceId");
+
+ }
+ }
+ catch (java.io.IOException x) {
+ return "null";
+
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ return "";
+
+
+ }
+
+}
diff --git a/trazador/app/src/main/res/drawable-hdpi/ic_action_info.png b/trazador/app/src/main/res/drawable-hdpi/ic_action_info.png
new file mode 100644
index 0000000..eef197e
Binary files /dev/null and b/trazador/app/src/main/res/drawable-hdpi/ic_action_info.png differ
diff --git a/trazador/app/src/main/res/drawable-hdpi/ic_action_stop.png b/trazador/app/src/main/res/drawable-hdpi/ic_action_stop.png
new file mode 100644
index 0000000..e373da2
Binary files /dev/null and b/trazador/app/src/main/res/drawable-hdpi/ic_action_stop.png differ
diff --git a/trazador/app/src/main/res/drawable-mdpi/ic_action_info.png b/trazador/app/src/main/res/drawable-mdpi/ic_action_info.png
new file mode 100644
index 0000000..1940892
Binary files /dev/null and b/trazador/app/src/main/res/drawable-mdpi/ic_action_info.png differ
diff --git a/trazador/app/src/main/res/drawable-mdpi/ic_action_stop.png b/trazador/app/src/main/res/drawable-mdpi/ic_action_stop.png
new file mode 100644
index 0000000..ea6a7ed
Binary files /dev/null and b/trazador/app/src/main/res/drawable-mdpi/ic_action_stop.png differ
diff --git a/trazador/app/src/main/res/drawable-xhdpi/ic_action_info.png b/trazador/app/src/main/res/drawable-xhdpi/ic_action_info.png
new file mode 100644
index 0000000..310caaa
Binary files /dev/null and b/trazador/app/src/main/res/drawable-xhdpi/ic_action_info.png differ
diff --git a/trazador/app/src/main/res/drawable-xhdpi/ic_action_stop.png b/trazador/app/src/main/res/drawable-xhdpi/ic_action_stop.png
new file mode 100644
index 0000000..8eca25a
Binary files /dev/null and b/trazador/app/src/main/res/drawable-xhdpi/ic_action_stop.png differ
diff --git a/trazador/app/src/main/res/drawable-xxhdpi/ic_action_info.png b/trazador/app/src/main/res/drawable-xxhdpi/ic_action_info.png
new file mode 100644
index 0000000..f130249
Binary files /dev/null and b/trazador/app/src/main/res/drawable-xxhdpi/ic_action_info.png differ
diff --git a/trazador/app/src/main/res/drawable-xxhdpi/ic_action_stop.png b/trazador/app/src/main/res/drawable-xxhdpi/ic_action_stop.png
new file mode 100644
index 0000000..2ad2bfc
Binary files /dev/null and b/trazador/app/src/main/res/drawable-xxhdpi/ic_action_stop.png differ
diff --git a/trazador/app/src/main/res/drawable-xxhdpi/ic_launcher.png b/trazador/app/src/main/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..de1f5ea
Binary files /dev/null and b/trazador/app/src/main/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/trazador/app/src/main/res/drawable-xxhdpi/ic_menu_mylocation.png b/trazador/app/src/main/res/drawable-xxhdpi/ic_menu_mylocation.png
new file mode 100644
index 0000000..fdbd5ca
Binary files /dev/null and b/trazador/app/src/main/res/drawable-xxhdpi/ic_menu_mylocation.png differ
diff --git a/trazador/app/src/main/res/drawable/btn_iniciar.png b/trazador/app/src/main/res/drawable/btn_iniciar.png
new file mode 100644
index 0000000..97daa64
Binary files /dev/null and b/trazador/app/src/main/res/drawable/btn_iniciar.png differ
diff --git a/trazador/app/src/main/res/drawable/btn_parada.png b/trazador/app/src/main/res/drawable/btn_parada.png
new file mode 100644
index 0000000..667b46a
Binary files /dev/null and b/trazador/app/src/main/res/drawable/btn_parada.png differ
diff --git a/trazador/app/src/main/res/drawable/ic_center_map.png b/trazador/app/src/main/res/drawable/ic_center_map.png
new file mode 100644
index 0000000..babd8ab
Binary files /dev/null and b/trazador/app/src/main/res/drawable/ic_center_map.png differ
diff --git a/trazador/app/src/main/res/drawable/ic_follow_me.png b/trazador/app/src/main/res/drawable/ic_follow_me.png
new file mode 100644
index 0000000..53b7f5a
Binary files /dev/null and b/trazador/app/src/main/res/drawable/ic_follow_me.png differ
diff --git a/trazador/app/src/main/res/drawable/ic_follow_me_on.png b/trazador/app/src/main/res/drawable/ic_follow_me_on.png
new file mode 100644
index 0000000..7df8c60
Binary files /dev/null and b/trazador/app/src/main/res/drawable/ic_follow_me_on.png differ
diff --git a/trazador/app/src/main/res/drawable/ic_info_black_24dp.xml b/trazador/app/src/main/res/drawable/ic_info_black_24dp.xml
new file mode 100644
index 0000000..34b8202
--- /dev/null
+++ b/trazador/app/src/main/res/drawable/ic_info_black_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/trazador/app/src/main/res/drawable/ic_notifications_black_24dp.xml b/trazador/app/src/main/res/drawable/ic_notifications_black_24dp.xml
new file mode 100644
index 0000000..e3400cf
--- /dev/null
+++ b/trazador/app/src/main/res/drawable/ic_notifications_black_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/trazador/app/src/main/res/drawable/ic_sync_black_24dp.xml b/trazador/app/src/main/res/drawable/ic_sync_black_24dp.xml
new file mode 100644
index 0000000..5a283aa
--- /dev/null
+++ b/trazador/app/src/main/res/drawable/ic_sync_black_24dp.xml
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/trazador/app/src/main/res/drawable/info.png b/trazador/app/src/main/res/drawable/info.png
new file mode 100644
index 0000000..c1e2a03
Binary files /dev/null and b/trazador/app/src/main/res/drawable/info.png differ
diff --git a/trazador/app/src/main/res/layout/activity_finalize.xml b/trazador/app/src/main/res/layout/activity_finalize.xml
new file mode 100644
index 0000000..4152b1d
--- /dev/null
+++ b/trazador/app/src/main/res/layout/activity_finalize.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/trazador/app/src/main/res/layout/activity_main.xml b/trazador/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..f1fdf64
--- /dev/null
+++ b/trazador/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/trazador/app/src/main/res/layout/activity_metadata.xml b/trazador/app/src/main/res/layout/activity_metadata.xml
new file mode 100644
index 0000000..e59a314
--- /dev/null
+++ b/trazador/app/src/main/res/layout/activity_metadata.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/trazador/app/src/main/res/layout/content_finalize.xml b/trazador/app/src/main/res/layout/content_finalize.xml
new file mode 100644
index 0000000..c1bf44d
--- /dev/null
+++ b/trazador/app/src/main/res/layout/content_finalize.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/trazador/app/src/main/res/layout/content_metadata.xml b/trazador/app/src/main/res/layout/content_metadata.xml
new file mode 100644
index 0000000..e87e8d7
--- /dev/null
+++ b/trazador/app/src/main/res/layout/content_metadata.xml
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/trazador/app/src/main/res/mipmap-hdpi/btn_savemetadata.png b/trazador/app/src/main/res/mipmap-hdpi/btn_savemetadata.png
new file mode 100644
index 0000000..6aaa598
Binary files /dev/null and b/trazador/app/src/main/res/mipmap-hdpi/btn_savemetadata.png differ
diff --git a/trazador/app/src/main/res/mipmap-hdpi/ic_launcher.png b/trazador/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..de1f5ea
Binary files /dev/null and b/trazador/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/trazador/app/src/main/res/mipmap-mdpi/btn_savemetadata.png b/trazador/app/src/main/res/mipmap-mdpi/btn_savemetadata.png
new file mode 100644
index 0000000..61e8969
Binary files /dev/null and b/trazador/app/src/main/res/mipmap-mdpi/btn_savemetadata.png differ
diff --git a/trazador/app/src/main/res/mipmap-mdpi/ic_launcher.png b/trazador/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..4bfcd4a
Binary files /dev/null and b/trazador/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/trazador/app/src/main/res/mipmap-xhdpi/btn_savemetadata.png b/trazador/app/src/main/res/mipmap-xhdpi/btn_savemetadata.png
new file mode 100644
index 0000000..005778d
Binary files /dev/null and b/trazador/app/src/main/res/mipmap-xhdpi/btn_savemetadata.png differ
diff --git a/trazador/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/trazador/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..2b62fb0
Binary files /dev/null and b/trazador/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/trazador/app/src/main/res/mipmap-xxhdpi/btn_savemetadata.png b/trazador/app/src/main/res/mipmap-xxhdpi/btn_savemetadata.png
new file mode 100644
index 0000000..c7b0628
Binary files /dev/null and b/trazador/app/src/main/res/mipmap-xxhdpi/btn_savemetadata.png differ
diff --git a/trazador/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/trazador/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..a129a91
Binary files /dev/null and b/trazador/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/trazador/app/src/main/res/mipmap-xxxhdpi/btn_savemetadata.png b/trazador/app/src/main/res/mipmap-xxxhdpi/btn_savemetadata.png
new file mode 100644
index 0000000..389769f
Binary files /dev/null and b/trazador/app/src/main/res/mipmap-xxxhdpi/btn_savemetadata.png differ
diff --git a/trazador/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/trazador/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..7ff522b
Binary files /dev/null and b/trazador/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/trazador/app/src/main/res/values-v21/styles.xml b/trazador/app/src/main/res/values-v21/styles.xml
new file mode 100644
index 0000000..dbbdd40
--- /dev/null
+++ b/trazador/app/src/main/res/values-v21/styles.xml
@@ -0,0 +1,9 @@
+
+
+
+
diff --git a/trazador/app/src/main/res/values-w820dp/dimens.xml b/trazador/app/src/main/res/values-w820dp/dimens.xml
new file mode 100644
index 0000000..63fc816
--- /dev/null
+++ b/trazador/app/src/main/res/values-w820dp/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 64dp
+
diff --git a/trazador/app/src/main/res/values/colors.xml b/trazador/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..3ab3e9c
--- /dev/null
+++ b/trazador/app/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+
+
+ #3F51B5
+ #303F9F
+ #FF4081
+
diff --git a/trazador/app/src/main/res/values/dimens.xml b/trazador/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..812cb7b
--- /dev/null
+++ b/trazador/app/src/main/res/values/dimens.xml
@@ -0,0 +1,6 @@
+
+
+ 16dp
+ 16dp
+ 16dp
+
diff --git a/trazador/app/src/main/res/values/strings.xml b/trazador/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..bb336f8
--- /dev/null
+++ b/trazador/app/src/main/res/values/strings.xml
@@ -0,0 +1,80 @@
+
+ trazador-v1.0
+ ok_btn
+ cancel_btn
+ metadata
+
+
+
+
+ General
+
+ Enable social recommendations
+ Recommendations for people to contact
+ based on your message history
+
+
+ Display name
+ John Smith
+
+ Add friends to messages
+
+ - Always
+ - When possible
+ - Never
+
+
+ - 1
+ - 0
+ - -1
+
+
+
+ Data & sync
+
+ Sync frequency
+
+ - 15 minutes
+ - 30 minutes
+ - 1 hour
+ - 3 hours
+ - 6 hours
+ - Never
+
+
+ - 15
+ - 30
+ - 60
+ - 180
+ - 360
+ - -1
+
+
+
+ - Entry 1
+ - Entry 2
+ - Entry 3
+
+
+
+ - 1
+ - 2
+ - 3
+
+
+
+
+ System sync settings
+
+
+ Notifications
+
+ New message notifications
+
+ Ringtone
+ Silent
+
+ Vibrate
+ Settings
+ Finalize
+
diff --git a/trazador/app/src/main/res/values/styles.xml b/trazador/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..545b9c6
--- /dev/null
+++ b/trazador/app/src/main/res/values/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/trazador/app/src/test/java/com/example/xavi/trazador_v10/ExampleUnitTest.java b/trazador/app/src/test/java/com/example/xavi/trazador_v10/ExampleUnitTest.java
new file mode 100644
index 0000000..812ce86
--- /dev/null
+++ b/trazador/app/src/test/java/com/example/xavi/trazador_v10/ExampleUnitTest.java
@@ -0,0 +1,15 @@
+package com.example.xavi.trazador_v10;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * To work on unit tests, switch the Test Artifact in the Build Variants view.
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() throws Exception {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/trazador/build.gradle b/trazador/build.gradle
new file mode 100644
index 0000000..d8b74a6
--- /dev/null
+++ b/trazador/build.gradle
@@ -0,0 +1,25 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ repositories {
+ jcenter()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:2.1.3'
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ jcenter()
+ mavenCentral()
+ maven { url "https://jitpack.io" }
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/trazador/gradle.properties b/trazador/gradle.properties
new file mode 100644
index 0000000..1d3591c
--- /dev/null
+++ b/trazador/gradle.properties
@@ -0,0 +1,18 @@
+# Project-wide Gradle settings.
+
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+# Default value: -Xmx10248m -XX:MaxPermSize=256m
+# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
+
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
\ No newline at end of file
diff --git a/trazador/gradle/wrapper/gradle-wrapper.jar b/trazador/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..13372ae
Binary files /dev/null and b/trazador/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/trazador/gradle/wrapper/gradle-wrapper.properties b/trazador/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..97ab1db
--- /dev/null
+++ b/trazador/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Wed Aug 31 19:22:43 CST 2016
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
diff --git a/trazador/gradlew b/trazador/gradlew
new file mode 100755
index 0000000..9d82f78
--- /dev/null
+++ b/trazador/gradlew
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/trazador/gradlew.bat b/trazador/gradlew.bat
new file mode 100644
index 0000000..aec9973
--- /dev/null
+++ b/trazador/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/trazador/settings.gradle b/trazador/settings.gradle
new file mode 100644
index 0000000..e7b4def
--- /dev/null
+++ b/trazador/settings.gradle
@@ -0,0 +1 @@
+include ':app'