Hola amig@s como están, hoy les traigo un nuevo tutorial, a pedido de un usuario hoy veremos :
La ves pasada vimos algunos tutoriales al respecto, vimos un tutorial de como registrar las coordenadas sin necesidad de darle clic algún botón.
como enviar la direccion y coordenadas del gps a una base de datos de forma automatica en android studio
Bueno esta vez sera algo parecido al darle clic al botón start tendrá que guardarse de forma infinita registros cada x tiempo a nuestra base de datos aunque cerremos la app, hasta que le demos clic en el botón stop sin mas rodeos empezamos con este tutorial a esto le llamamos background o en segundo plano.
Como guía básica tendremos un ejercicio anterior donde teníamos un solo botón y para que se registre los datos teníamos que hacer un clic por registro:
como guardar la direccion y coordenadas del gps a una base de datos en android studio
Por favor entra al enlace de arriba y crea la base de datos y el archivo insertar.php de la webservices. Luego vuelve aquí y podemos continuar:
Primero debe dar estos permisos en tu AndroidManifest
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Ahora les dejo el activity_main para que puedan reemplazar:
<?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="com.androfast.pc.appsegundoplanoguardargpsbd.MainActivity">
<LinearLayout
android:layout_width="368dp"
android:layout_height="495dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:orientation="vertical"
tools:layout_editor_absoluteX="8dp"
tools:layout_editor_absoluteY="8dp">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:text="MIS COORDENADAS SON:" />
<TextView
android:id="@+id/mensaje_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView" />
<TextView
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="MI DIRECCION ES:" />
<TextView
android:id="@+id/mensaje_id2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="393dp"
android:gravity="center"
android:orientation="horizontal">
<Button
android:id="@+id/btnStop"
android:layout_width="fill_parent"
android:layout_height="65dp"
android:layout_weight="1"
android:gravity="center"
android:text="STOP" />
<Button
android:id="@+id/btnGuardar"
android:layout_width="fill_parent"
android:layout_height="65dp"
android:layout_weight="1"
android:gravity="center"
android:text="START"></Button>
</LinearLayout>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
Ahora les paso a explicar la parte del código mucha atención no seas don vergas y doña vergas al menos date un minuto y con eso te quitas mil dudas:
Primero debemos crear un objeto de tipo Handler si quieres leer algo mas de la clase Handler léelo aqui
private Handler handler = new Handler();
Ahora implementaremos un objeto de la clase Runnable y dentro de ella un método publico llamado run y ahí es donde se hace toda la magia:
private Runnable runnable = new Runnable() {
@Override
public void run() {
try {
new Insertar(MainActivity.this).execute();
handler.postDelayed(runnable, 10000);
}
catch (Exception e) {
e.printStackTrace();
}
}
};
Dentro del run observan que llamamos al método Insertar y le decimos que se ejecute(execute)
y también llamamos al atributo postDelayed de la clase Handler y le estamos mandando como parámetro (runnable, 10000) ahí le indicamos que se repita cada 10 segundos osea que cada 10 segundos se enviaran las coordenadas y la dirección a nuestra base de datos.
Ahora debemos ver como funciona los botones:
Empezamos con el botón que guarda los datos:
btnGuardar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.postDelayed(runnable, 5000);
}
});
Aquí le estamos indicando que cada vez que hagamos clic en el botón guardar empezara a correr nuestro handler, pero eso lo hará después de 5 segundos y porque?? porque me dio la gana jajaj no es cierto sucede que los datos demoran en cargar del gps si le ponemos que empiece a enviar datos desde el segundo 0 enviaremos null en cambio después de 5 segundos ya habrá cargado las coordenadas y la dirección.
Ahora miremos el código del botón Stop:
btnStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.removeCallbacks(runnable);
Toast.makeText(MainActivity.this,"Finalizo", Toast.LENGTH_SHORT).show();
}
});
package com.androfast.pc.appsegundoplanoguardargpsbd;
import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.location.LocationProvider;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.provider.Settings;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class MainActivity extends AppCompatActivity {
TextView mensaje1;
TextView mensaje2;
Button btnGuardar, btnStop;
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
@Override
public void run() {
try {
new Insertar(MainActivity.this).execute();
handler.postDelayed(runnable, 10000);
}
catch (Exception e) {
e.printStackTrace();
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// handler.post(sendData);
mensaje1 = (TextView) findViewById(R.id.mensaje_id);
mensaje2 = (TextView) findViewById(R.id.mensaje_id2);
btnGuardar =(Button) findViewById(R.id.btnGuardar);
btnStop =(Button) findViewById(R.id.btnStop);
btnGuardar.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.postDelayed(runnable, 5000);
}
});
btnStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
handler.removeCallbacks(runnable);
Toast.makeText(MainActivity.this,"Finalizo", Toast.LENGTH_SHORT).show();
}
});
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();
}
}
//Insertamos los datos a nuestra webService
private boolean insertar(){
HttpClient httpClient;
List<NameValuePair> nameValuePairs;
HttpPost httpPost;
httpClient = new DefaultHttpClient();
httpPost = new HttpPost("http://192.168.8.133/gpsbd/insertar.php");//url del servidor
//empezamos añadir nuestros datos
nameValuePairs = new ArrayList<NameValuePair>(4);
nameValuePairs.add(new BasicNameValuePair("coordenadas",mensaje1.getText().toString().trim()));
nameValuePairs.add(new BasicNameValuePair("direccion",mensaje2.getText().toString().trim()));
try {
httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
httpClient.execute(httpPost);
return true;
} catch(UnsupportedEncodingException e){
e.printStackTrace();
}catch (ClientProtocolException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
return false;
}
//AsyncTask para insertar Datos
class Insertar extends AsyncTask<String,String,String> {
private Activity context;
Insertar(Activity context){
this.context=context;
}
protected String doInBackground(String... params) {
// TODO Auto-generated method stub
if(insertar())
context.runOnUiThread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
Toast.makeText(context, "Datos insertado con éxito", Toast.LENGTH_LONG).show();
mensaje1.setText("");
mensaje2.setText("");
}
});
else
context.runOnUiThread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
Toast.makeText(context, "Datos no insertado con éxito", Toast.LENGTH_LONG).show();
}
});
return null;
}
}
//Apartir de aqui empezamos a obtener la direciones y coordenadas
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);
mensaje1.setText("Localizacion agregada");
mensaje2.setText("");
}
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == 3000) {
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);
mensaje2.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 Text = "Lat = "+ loc.getLatitude() + "n Long = " + loc.getLongitude();
mensaje1.setText(Text);
this.mainActivity.setLocation(loc);
}
@Override
public void onProviderDisabled(String provider) {
// Este metodo se ejecuta cuando el GPS es desactivado
mensaje1.setText("GPS Desactivado");
}
@Override
public void onProviderEnabled(String provider) {
// Este metodo se ejecuta cuando el GPS es activado
mensaje1.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;
}
}
}
}
Y con eso hemos terminado, espero les haya gustado este pequeño tutorial hay otras formas de hacerlo como por ejemplo con la clase Service pero eso lo haremos en otra ocasión:
Igual si piensas que hablo escribo en chino te dejo el ejercicio:
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!
Hola,
La aplicación android me funciona casi correctamente. Al cerrar la aplicación se siguen enviando datos al mysql de mi servidor, pero cuando pasa un rato (sobre media hora o así), ya no inserta más datos. El icono del gps en las notificaciones de la pantalla arriba a la izquierda deja de estar presente.
¿Por que ocurre?, como consigo que se ejecute siempre el envio de datos¿?¿?
Si quieres te envío todo el código que tengo, pero vamos, solo he tocado textos del toast sin importancia.
Hola Miguel agrégale el permiso de uso de batería y se soluciona, saludos.
estoy usando la ultima version de android studio con el ejemplo y con las actualziacion y me marca este error:
04:41 AM Instant Run is not supported on devices with API levels 20 or lower.
(Don’t show again)
04:41 AM Executing tasks: [:app:assembleDebug]
04:43 AM Gradle build finished in 1m 12s 887ms
04:43 AM Session ‘app’: Error Installing APK
la verdad no tengo idea apenas estoy empezando a entender como manejar android, alguna sugerencia?
La respuesta esta en la primera linea de tu error te dice lo siguiente: La ejecución no es compatible con dispositivos con niveles de API 20 o inferiores.
Tu móvil puede ser un poco anticuado, pero para descartar, me podría decir que tipo de móvil es y que versión de Android es la que tiene instalada.
la version de android es 5.1 es un huawei cunl03
Miguel esa versión es antigua trae la Api 21 sino me equivoco, desconozco si tu huawei puede actualizarse a la versión 6 por ejemplo, en todo caso tienes dos opciones la primera es usar el android estudio 2.33 o cualquier versión que sea inferior a la 3.0 y usar la api 21 como entorno de trabajo de lo contrario la segunda opción es cambiarte a un móvil mas actualizado.
Hola hace una horas te comente en otro post, acerca de un ejemplo similar a este, sabes estoy poniendo en practica esto que pusiste, sin embargo al poco tiempo de que ejecuto la app, dejo de registrar coordenadas, arriba comentas que solo agregare el permiso de uso de batería, yo agregue este android.permission.WAKE_LOCK, pero me sucede lo mismo como a las 5 minutos el icono que aparece en la parte superior que indica la posición deja de aparecer. ¿Si esta correcto el permiso que agregue?
Buenas noches. Sabes estoy probando la app pero como a Los cinco minutos deja de registrar las coordenadas, estando la aplicación en seguridad plano o el teléfono bloqueado. Leí que faltaba algo del permiso de batería, yo utilice el siguiente, nosé si sea el correcto. .
ya solucione la parte de la instalacion de la aplicacion en el celular para probrarla ya tengo creada la base de datos, y tengo subido el archivo insertar.php en el servidor, sigo leyendo el codigo para entenderle mejor, estoy en la parte de guardar donde me dice que los datos no se guardan con exito, espero ver el problema por mi mismo
Tal vez unos minutos de este vídeo le evite muchas horas de dolor de cabeza https://www.youtube.com/watch?v=Qbkgz2ZeFHQ
listo, ya graba en la base de datos latitud y longitud, a seguir leyendo articulos para pasarle 4 parametros mas a la base de datos, % de bateria, nombre, numero de telefono y hora de la ultima conexion, de verdad que sus tutoriales son excelentes, de antemano muchas gracias por compartir conocimientos
Que bueno que le sirvió, saludos.
ya tengo casi terminado mi proyecto ya envia el nombre el telefono latitud y longitud, solo una duda, como hacer que envie datos cada x segundos, en el codigo veo que se reenvian datos cuando cambia la localizacion, como lo podria hacer como te comento, muchas gracias de antemano
Miguel quizás no esta leyendo lo que escribí, claramente dice que se envía ala BD cada 10 segundos handler.postDelayed(runnable, 10000); Saludos.
ya lo corregi muchas gracias, inclusive le aguegue como comentaste con mi tocayo el permiso de bateria, lo unico que me faltaria y que ando leyendo aqui y buscandole, es que cuando le aprieten el boton de reposo al celular, ese que hace que se «apague la pantalla» me siga transmitiendo, y de verdad me gustaria hacerles alguna contribucion de alguna manera por que la ayuda que me han brindado ha sido mucha, terminado el proyecto te lo enviare de vuelta con las modificaciones que hice por si alguien mas necesita agregarle campos vean como lo hice yo
otra pregunta que pasa cuando el telefono tiene protector de pantalla?
no entiendo su pregunta?
Usted necesita esto: https://www.androfast.com/2017/11/como-crear-un-servicio-background-en.html
leido muchas gracias, como todo casi es nuevo para mi mejor preguntar y quedar como tonto que no preguntar y quedarme con la duda,
Tranquilo nadie nace sabiendo las cosas.
ya tengo mi aplicacion creada graccias a todos tus tutoriales, hice las pruebas de cambiar aplicaciones y contestar el tel y sigue funcionando bien, pero me salto un nuevo error que no habia visto, trabaja bien, pero solo por 50 minutos, hice varias pruebas, pero exactamente a los 50 minutos de estar enviando los datos se detiene, como podria solucionar esto? alguna idea, sigo navegando a ver si encuentro alguna solucion pero no le doy
gracias
Lo felicito, como sabrá todos los dispositivos móviles de por si tienen integrado en su núcleo el sistema de ahorro de energía, entonces usted debe darle permisos de batería a su aplicación.
si se lo di creo, agregue este linea , ademas le otorgue el permiso directamente en el celular a la aplicacion para seguir trabajando en segundo plano, con esto solucione lo del protector de pantalla tambien y de cuando ponen el celular en reposo, es decir, que cuando aprietan el boton que apaga la pantalla
voy dejarle unos links se que le va ayudar ami me sirvió mucho. https://developer.android.com/reference/android/provider/Settings#ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
https://developer.android.com/training/monitoring-device-state/doze-standby?hl=es-419
ya lo implemente y esta corriendo bien, sigo agregando detalles para ir guardando datos, use tu otro tutorial de «como mostrar el porcentaje de bateria» y me funciona muy bien, y la graba bien en la base de datos, use este codigo BroadcastReceiver bateriaReciever = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
context.unregisterReceiver(this);
int currentLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL,-1);
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE,-1);
int level = -1;
if (currentLevel >=0 && scale > 0){
level= (currentLevel * 100)/scale;
}
mensaje6.setText(«»+level+»%»);
}
};
IntentFilter batteryFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
registerReceiver(bateriaReciever,batteryFilter);
y mando mensaje6 a la base de datos y todo correcto, pero tengo otra consulta, solamente me manda el primer dato, como puedo actualizarlo para que envie el ultimo dato de bateria? en este caso solo me manda el primero que toma la aplicacion al inicializarse, alguna sugerencia o algun otro tutorial para leer?
gracias
solucionado!!!!
Hola, ya ha pasado mucho tiempo, pero podría poner el código modificado.
Gracias. Lo agradecería mucho