
Hoy veremos como guardar las coordenadas en postgresql usando la librería volley. Ya hace buen tiempo hicimos un tutorial de como guardar las coordenadas en mysql con la librería apache, pero como sabrán esta librería ya esta en desuso, luego vimos como guardarlos con volley y retrofit con mysql , entonces hoy decidimos crear este pequeño curso en android. Si eres nuevo con la librería volley y tienes mas dudas o simplemente quieres dominarla te aconsejo que ingreses a este enlace: curso básico de volley este curso consta de tres partes, donde veras temas como listar, agregar, iniciar sesión de un usuario etc. En pocas horas puedes dominarla, inclusive los enlaces cuentas con vídeos que ayudaran a la comprensión, sin mas que decir empezamos de una vez con el curso.
Guardar coordenadas en una base de datos en Postgresql con volley
Contenidos
BASE DE DATOS
Para este ejemplo usaremos el gestor de base de datos pgAdmin, empezamos creando una base de datos en mi caso le llamare gpsbd y luego crearemos una tabla llamada gps donde tendremos cuatro campos como se ven en la imagen y código que le estoy dejando lineas mas abajo:
Si te fijas desde las linea 1-8 estamos definiendo el nombre de nuestra tabla y sus cuatro atributos, luego desde la linea 10-11 estamos creando una secuencia para que nuestro id de la tabla sea secuencial y a la hora de agregar, permita tener un id auto incremental.
CREATE TABLE public.gps ( id integer NOT NULL, direccion character varying(100) NOT NULL, lat double precision NOT NULL, lon double precision NOT NULL, CONSTRAINT pk_id PRIMARY KEY (id) ); CREATE SEQUENCE gps_id_seq; ALTER TABLE gps ALTER id SET DEFAULT NEXTVAL('gps_id_seq');
WEBSERVICES
En este caso ya saben que siempre utilizo el modelo por capas como hemos visto en los ejercicios propuestos en mysql, osea diferente parte de código dentro de carpetas diferentes para mejorar el orden de la programación, en este sentido creare tres carpetas y deben ser las siguientes como se muestra en la imagen:
Carpeta datos
En esta carpeta ingresaremos un archivo php llamado Conexión.clase.php que nos servirá para hacer la conexión entre nuestra base de datos y la webservices. Recuerda cambiar tus datos en la linea 6,7 y 8 con los de tu servidor o hosting.
Conexion.clase.php
<?php class Conexion { protected $dblink; function __construct() { $servidor = "pgsql:host=localhost;port=5432;dbname=gpsbd"; $usuario = "postgres"; $clave = "12345"; $this->dblink = new PDO($servidor, $usuario, $clave); $this->dblink->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $this->dblink->exec("SET CLIENT_ENCODING TO 'UTF8'"); } } ?>
Carpeta negocio
En esta carpeta ingresaremos nuestra clase php llamada Gps.clase.php que nos servirá para utilizar los atributos que emplearemos en este caso las coordenadas como se ve en las lineas 4,5,6,7 y también la función agregar en la linea 50 que nos permitirá agregar las coordenadas en nuestra tabla gps:
Gps.clase.php
<?php require_once '../datos/Conexion.clase.php'; class Gps extends Conexion{ private $codigo; private $direccion; private $lat; private $lon; public function getCodigo() { return $this->codigo; } public function setCodigo($codigo) { $this->codigo = $codigo; return $this; } public function getDireccion() { return $this->direccion; } public function setDireccion($direccion) { $this->direccion = $direccion; return $this; } public function getLat() { return $this->lat; } public function setLat($lat) { $this->lat = $lat; return $this; } public function getLon() { return $this->lon; } public function setLon($lon) { $this->lon = $lon; return $this; } public function agregar() { $sql = "insert into gps( direccion, lat, lon) values(:dir, :lat, :lon);"; $sentencia = $this->dblink->prepare($sql); $direccion = $this->getDireccion(); $lat = $this->getLat(); $lon = $this->getLon(); $sentencia->bindParam(":dir", $direccion); $sentencia->bindParam(":lat", $lat); $sentencia->bindParam(":lon", $lon ); $resultado = $sentencia->execute(); if ($resultado != 1){ //ocurrio un error al insertar return FALSE; } //Insertó correctamente return TRUE; } }
Carpeta web-services
En esta carpeta tendremos un archivo php llamado registrar-gps.php este archivo nos servirá para consumir nuestra api webservices y podremos registrar los datos que son enviados desde la app hacia la base de datos:
registrar-gps.php
<?php if ( ( !isset( $_POST["direccion"] ) ) || ( !isset( $_POST["lat"] ) ) || ( !isset( $_POST["lon"] ) ) ) { $respuesta = array( "estado"=>"error" ); echo json_encode($respuesta); exit(); } $direccion = $_POST["direccion"]; $lat = $_POST["lat"]; $lon = $_POST["lon"]; require_once '../negocio/Gps.clase.php'; $objGps = new Gps(); $objGps->setDireccion($direccion); $objGps->setLat($lat); $objGps->setLon($lon); if ($objGps->agregar()==TRUE){ $respuesta = array( "estado"=>"exito" ); }else{ $respuesta = array( "estado"=>"error", "datos"=>"" ); } //echo json_encode($respuesta); echo json_encode($respuesta); ?>
CONSTRUYENDO LA APP
Damos permisos en el AndroidManifest
Aquí debemos dar permiso tanto para el gps como para el acceso del internet, como se observa en las lineas 4,5,6.
AndroidManifest
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.androfast.server.appgpsbdvolley"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Agregando librería volley
Debemos agregar la librería volley dentro de nuestro archivo build.gradle, para ser mas exacto dentro de dependencies como se muestra a continuación en la linea 8:
build.gradle
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.1' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' implementation 'com.android.volley:volley:1.0.0' }
Agregando el modo gráfico
Para este ejemplo solo usaremos tres textview y un botón como se muestra en la siguiente imagen
activity_main
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <ImageView android:id="@+id/imageView" android:layout_width="209dp" android:layout_height="150dp" android:layout_marginEnd="8dp" android:layout_marginStart="8dp" android:layout_marginTop="8dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.503" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:srcCompat="@drawable/kotlin" /> <TextView android:id="@+id/txtDireccion" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginStart="8dp" android:layout_marginTop="176dp" android:text="TextView" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.527" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/txtLat" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginStart="8dp" android:layout_marginTop="16dp" android:text="TextView" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.548" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/txtDireccion" /> <TextView android:id="@+id/txtLon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginTop="16dp" android:text="TextView" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="@+id/txtLat" app:layout_constraintTop_toBottomOf="@+id/txtLat" /> <Button android:id="@+id/btnGuardar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginEnd="8dp" android:layout_marginStart="8dp" android:layout_marginTop="72dp" android:text="GUARDAR" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.539" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/txtLat" /> </android.support.constraint.ConstraintLayout>
Agregando las clases
Trabajaremos con dos clases una llamada Http que nos servirá para conectarnos a la webservices y la otra sera nuestra clase por defecto MainActivity donde obtendremos y guardaremos las coordenadas:
Http
recuerda cambiar la dirección de tu webservices
public class Http { public static final String URL_WEB_SERVICE = "http://192.168.8.156/gpsbd/web-services/"; }
MainActivity
public class MainActivity extends AppCompatActivity { TextView direccion, lat,lon; Button guardar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); direccion=(TextView)findViewById(R.id.txtDireccion); lat=(TextView)findViewById(R.id.txtLat); lon=(TextView)findViewById(R.id.txtLon); guardar=(Button)findViewById(R.id.btnGuardar); if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION,}, 1000); } else { locationStart(); } guardar.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { guardarGps(); } }); } private void locationStart() { LocationManager mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); Localizacion Local = new Localizacion(); Local.setMainActivity(this); final boolean gpsEnabled = mlocManager.isProviderEnabled(LocationManager.GPS_PROVIDER); if (!gpsEnabled) { Intent settingsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); startActivity(settingsIntent); } if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION,}, 1000); return; } mlocManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, (LocationListener) Local); mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, (LocationListener) Local); lat.setText("Localización agregada"); direccion.setText(""); } public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == 1000) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { locationStart(); return; } } } public void setLocation(Location loc) { //Obtener la direccion de la calle a partir de la latitud y la longitud if (loc.getLatitude() != 0.0 && loc.getLongitude() != 0.0) { try { Geocoder geocoder = new Geocoder(this, Locale.getDefault()); List<Address> list = geocoder.getFromLocation( loc.getLatitude(), loc.getLongitude(), 1); if (!list.isEmpty()) { Address DirCalle = list.get(0); direccion.setText(DirCalle.getAddressLine(0)); } } catch (IOException e) { e.printStackTrace(); } } } /* Aqui empieza la Clase Localizacion */ public class Localizacion implements LocationListener { MainActivity mainActivity; public MainActivity getMainActivity() { return mainActivity; } public void setMainActivity(MainActivity mainActivity) { this.mainActivity = mainActivity; } @Override public void onLocationChanged(Location loc) { // Este metodo se ejecuta cada vez que el GPS recibe nuevas coordenadas // debido a la deteccion de un cambio de ubicacion loc.getLatitude(); loc.getLongitude(); String Text1 = String.valueOf(loc.getLatitude()); String Text2 = String.valueOf(loc.getLongitude()); lat.setText(Text1); lon.setText(Text2); this.mainActivity.setLocation(loc); } @Override public void onProviderDisabled(String provider) { // Este metodo se ejecuta cuando el GPS es desactivado lat.setText("GPS Desactivado"); } @Override public void onProviderEnabled(String provider) { // Este metodo se ejecuta cuando el GPS es activado lat.setText("GPS Activado"); } @Override public void onStatusChanged(String provider, int status, Bundle extras) { switch (status) { case LocationProvider.AVAILABLE: Log.d("debug", "LocationProvider.AVAILABLE"); break; case LocationProvider.OUT_OF_SERVICE: Log.d("debug", "LocationProvider.OUT_OF_SERVICE"); break; case LocationProvider.TEMPORARILY_UNAVAILABLE: Log.d("debug", "LocationProvider.TEMPORARILY_UNAVAILABLE"); break; } } } public void guardarGps(){ RequestQueue queue = Volley.newRequestQueue(MainActivity.this); StringRequest stringRequest = new StringRequest(Request.Method.POST, Http.URL_WEB_SERVICE + "registrar-gps.php", new Response.Listener<String>() { @Override public void onResponse(String response) { try { JSONObject objResultado = new JSONObject(response); String estadox = objResultado.get("estado").toString(); if(!estadox.contains("exito")){ // if(!response.equalsIgnoreCase("exito")){ Toast.makeText(MainActivity.this, "Hubo un error", Toast.LENGTH_LONG).show(); }else{ Toast.makeText(MainActivity.this, "Coordenadas Registradas", Toast.LENGTH_LONG).show(); } } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Toast.makeText(MainActivity.this, "Invalid conexion", Toast.LENGTH_LONG).show(); } }) { @Override protected Map<String, String> getParams() throws AuthFailureError { Map<String, String> params = new HashMap<>(); params.put("direccion", direccion.getText().toString().trim()); params.put("lat",lat.getText().toString().trim()); params.put("lon",lon.getText().toString().trim()); return params; } }; queue.add(stringRequest); } }
De todas formas te dejo la aplicación si requieres descargarla:
Hola soy Alex Céspedes fundador de ANDROFAST, programo algunas cosas por diversión, me gusta aprender cosas nuevas y estoy pendiente de todo lo que tenga que ver con tecnología. Este blog lo cree para todas las personas que tengan dificultades en la programación, para ser sincero nunca fui bueno y reprobé algunos cursos de programación, pero mis ganas de aprender pudieron más. SI YO PUEDO TU PUEDES ANIMO!