Mostrando las entradas con la etiqueta android. Mostrar todas las entradas
Mostrando las entradas con la etiqueta android. Mostrar todas las entradas
Vamos a programar #58 - AsyncTask en java.
Hola de nuevo a todos, el día de hoy vamos a ver cómo usar la clase "AsyncTask" para proveer de un poco de multi-threading a una aplicación.
En el la aplicacion de los números de Muchhausen, vimos que empleamos una subclase llamada "UpdateList" que hereda de "AsyncTask", el nombre de la clase es bastante descriptivo, puesto que lo que hace es ejecutar una tarea de forma asíncrona.
la clase AsyncTask posee los siguientes metodos:
Para tener una idea de cómo funciona, retomemos el ejemplo de los números de Munchhausen. Para empezar, ¿qué es lo queremos hacer?, en este caso buscamos crear una lista de resultados en la que indiquemos si un número n cumple o no la conjetura. entonces para construir la clase AsyncTask de acuerdo a nuestros requerimientos, puede ser de la siguiente forma: private class UpdateList extends AsyncTask<Integer,Void,ArrayList> y cada parametro corresponde a:
Ahora veamos el siguiente código:
Los leo luego.
En el la aplicacion de los números de Muchhausen, vimos que empleamos una subclase llamada "UpdateList" que hereda de "AsyncTask", el nombre de la clase es bastante descriptivo, puesto que lo que hace es ejecutar una tarea de forma asíncrona.
la clase AsyncTask posee los siguientes metodos:
- doInBackground(Params... params).
- Este método se debe de sobrecargar para poder realizar una tarea de forma asíncrona.
- onCancelled(Result result)
- Se ejecuta en el hilo principal despúes de que cancel(boolean) es invocado o doInBackground(Object[]) ha terminado.
- onPostExecute(Result result).
- Se ejecuta cuando doInBackground(Params...) ha terminado su ejecución.
- OnPreExecute()
- Se ejecuta en el hilo principal antes que doInBackground(Params...).
- onProgressUpdate(Progress... values)
- Este método se ejecuta despúes de que publishProgress(Progress...) is invoked.
- publishProgress(Progress... values)
- Este método puede ser invocado desde doInBackground(Params...) para actualizar elementos en el hilo principal.
Para tener una idea de cómo funciona, retomemos el ejemplo de los números de Munchhausen. Para empezar, ¿qué es lo queremos hacer?, en este caso buscamos crear una lista de resultados en la que indiquemos si un número n cumple o no la conjetura. entonces para construir la clase AsyncTask de acuerdo a nuestros requerimientos, puede ser de la siguiente forma: private class UpdateList extends AsyncTask<Integer,Void,ArrayList> y cada parametro corresponde a:
- Integer, son los parametros que se usaran en doInBackground(), son del tipo integer porque son los números que vamos a usar cómo limites inferior y superior, y un tercero que se usará para indicar si se deben mostrar o no todos los números.
- Void, el segundo parametro cómo en eeste caso no mostramos ningún progreso en concreto, simplemente mostramos el dialogo de forma indeterminada, usualmente suele ser un valor Integer.
- ArrayList, debido a que todos los resultados de los calculos los guardamos en un "ArrayList", para poder usar esa lista cómo resultado de la ejecución, debemos de hacerlo del mismo tipo, si por alguna razón nuestro proceso debe de devolver un valor "boolean", "String" o etc. el tercer parametro debe de ser de ese tipo.
Ahora veamos el siguiente código:
// Original de https://developer.android.com/reference/android/os/AsyncTask
private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
protected Long doInBackground(URL... urls) {
int count = urls.length;
long totalSize = 0;
for (int i = 0; i < count; i++) {
totalSize += Downloader.downloadFile(urls[i]);
publishProgress((int) ((i / (float) count) * 100));
// Escape early if cancel() is called
if (isCancelled()) break;
}
return totalSize;
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(Long result) {
showDialog("Downloaded " + result + " bytes");
}
}
Esta clase se construye de la siguiente forma: DownloadFilesTask extends AsyncTask<URL, Integer, Long>, suponiendo que se llame a ejecutar con los siguientes parametros: "URL1", "URL2","URL3","URL4"..."URL10". El parámetro URL contendrá estos diez valores distintos entonces en "doInBackground(URL.. urls)" lo que se hace es primero asignar los parámetros a la variable "urls" y luego medir los elementos con "urls.length" y cada parámetro pasado al momento de iniciar la ejecución, estará en esta matriz. EL resultado de "doInBackground" es del tipo "Long" que usaremos en "onPostExecute" para mostrar al usuario cuantos bytes se descargaron. Cada vez que se ejecute "publishProgress()" en "doInBackGround()", se ejecutará "onProgressUpdate()", en esta parte es donde debemos de cambiar cualquier indicador de progreso. finalmente en "onPostExecute()", mostraremos un dialogo con la información de cuantos bytes se descargaron.
Y bien, por ahora es todo, en el siguiente post añadiremos una barra de progreso y entenderemos mejor cómo y cuando debemos de hacer uso de "AsyncTask".
![]() |
| En post anteriores ya hemos usado "AsyncTask" |
Y bien, por ahora es todo, en el siguiente post añadiremos una barra de progreso y entenderemos mejor cómo y cuando debemos de hacer uso de "AsyncTask".
Los leo luego.
9/02/2018 04:31:00 p.m.
android
,
AsyncTask
,
java
,
programacion
Vamos a programar #57 - Los números de Munchhausen (ver. Java android)
Hola de nuevo a todos, el día de hoy vamos a ver cómo probar los números de Munchhausen en java para usarse en dispositivos con android.
El código ha cambiado un poco, en el caso de la función "IsMunchhuasenNumber()", todo se mantiene igual, es decir; se prueba un número y si este cumple la conjetura, la funcion devuelve "true", en caso contrario se devuelve "false".
La función "TestNumbers", es la que sufrido varios cambios. Para empezar, los parámetros que está recibe, los primeros dos se mantienen del tipo "int", pero el tercer parámetro pasa a ser del tipo "boolean" al tipo "int", esto solo hace por practicidad, un poquito más adelante veremos el por qué. Otro de los cambios que sufre, es que ahora pasa a ser una función en vez de un procedimiento. El valor que regresa es un valor del tipo "ArrayList", que es la lista en la cual se van almacenado los valores de salida. Cada vez que se prueba la conjetura para un número, se regresa una cadena de texto similar a "el número n no/cumple la conjetura", en la versión de C#, directamente se usaba el delegado y la función "UpdateList()" para hacerlo pero en este y debido a cómo está estructurado, pensé que era mejor hacerlo así.
A diferencia de los muchos otros códigos que he dicho que voy a "optimizar" (y que no he hecho), este ahora si usa un "Thread" diferente para hacer los cálculos y que no se bloquee la interfaz principal, para eso hacemos uso de la Subclase "UpdateList" que hereda de la clase "AsyncTask" (no se si sea en valido decir "hereda" en java, pero creo que si o si no se entiende). En el post de la semana que viene, veremos cómo usar esta clase para poder brindar un poco de "Multithreading", pero por ahora, al crear la instancia, pasamos tres parámetros que son "<Integer, Void, ArrayList>". Para poder usar la clase "AsyncTask", debemos de sobrecargar algunos de los metodos que la componen, en este caso solo son tres (pero hay más) y son: "onPreExecute()", "doInBackground()" y "onPostExecute()". Respectivamente cada uno hace lo siguiente: Es lo que se ejecutará antes de empezar, la parte principal y que mas tiempo va a consumir y la parte donde se procesaran los resultados.
Con el código anterior podemos probar los números de Munchhausen en un dispositivo con android, en el siguiente post veremos cómo es que funciona la clase "AsyncTask" y cómo nos podra ayudar con tareas en segundo plano. El código cómo de costumbre lo pongo en mi dropbox para que lo descargues, recuerda que a partir de este post, solo ira el código del layout principal y el código java. El APK ya compilado lo puedes descargar de mi dropbox directamente o puedes visitar la seccion de descargas del blog.
Y bien, por ahora es todo, los leo luego.
El código.
Cómo ya vimos cuales son las reglas de los números de Munchhausen en el primer post, ahora pasaremos directamente al código en java para poder usarlo. El código es el siguiente:
package com.mdev.munchhausen;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
public class MainActivity extends Activity {
Button BtnDowork;
TextView TXTMin, TxtMax;
CheckBox CHKShowAll;
ListView ShowResults;
private ProgressDialog progress;
private boolean IsMunchhausenNumber(String Number)
{
int Value = 0;
int CurrentNumber = 0;
char[] Digits = Number.toCharArray();
for (int i = 0; i < Digits.length; i++)
{
CurrentNumber = Digits[i] - 48;
Value += (int)Math.pow(CurrentNumber,CurrentNumber);
}
String CurrentVal = String.valueOf(Value);
if (Number.compareTo(CurrentVal) == 0)
return true;
else
return false;
}
private ArrayList TestNumbers(int BeginNumber, int EndNumber, int ShowAll)
{
ArrayList TempList = new ArrayList();
for (int i = BeginNumber; i <= EndNumber; i++)
{
if (IsMunchhausenNumber(String.valueOf(i)))
TempList.add( "La conjetura se cumple para el número " + i);
else if (ShowAll == 1)
TempList.add( "El número " + i + " no cumple la conjetura");;
}
return TempList;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BtnDowork = (Button)findViewById(R.id.BtnDoWork);
TXTMin = (TextView)findViewById(R.id.TXTInMin);
TxtMax = (TextView)findViewById(R.id.TXTInMax);
CHKShowAll = (CheckBox)findViewById(R.id.CHKShowAll);
ShowResults = (ListView) findViewById(R.id.LVResults);
BtnDowork.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Integer ShowAll = 0;
Integer Min = Integer.valueOf(TXTMin.getText().toString());
Integer Max = Integer.valueOf(TxtMax.getText().toString());
if (CHKShowAll.isChecked())
ShowAll = 1;
else
ShowAll = 0;
new UpdateList().execute(Min,Max,ShowAll);
}
}
);
}
private class UpdateList extends AsyncTask<Integer,Void,ArrayList>
{
@Override
protected void onPreExecute()
{
progress = ProgressDialog.show(MainActivity.this, "Espera...", "Espera...!!!");
}
@Override
protected ArrayList doInBackground(Integer... Limits)
{
ArrayList Lista = new ArrayList();
Lista = TestNumbers(Limits[0],Limits[1],Limits[2]);
return Lista;
}
@Override
protected void onPostExecute(ArrayList result)
{
super.onPostExecute(result);
final ArrayAdapter adapter = new ArrayAdapter(MainActivity.this,android.R.layout.simple_list_item_1, result);
ShowResults.setAdapter(adapter);
progress.dismiss();
}
}
}
El código ha cambiado un poco, en el caso de la función "IsMunchhuasenNumber()", todo se mantiene igual, es decir; se prueba un número y si este cumple la conjetura, la funcion devuelve "true", en caso contrario se devuelve "false".
La función "TestNumbers", es la que sufrido varios cambios. Para empezar, los parámetros que está recibe, los primeros dos se mantienen del tipo "int", pero el tercer parámetro pasa a ser del tipo "boolean" al tipo "int", esto solo hace por practicidad, un poquito más adelante veremos el por qué. Otro de los cambios que sufre, es que ahora pasa a ser una función en vez de un procedimiento. El valor que regresa es un valor del tipo "ArrayList", que es la lista en la cual se van almacenado los valores de salida. Cada vez que se prueba la conjetura para un número, se regresa una cadena de texto similar a "el número n no/cumple la conjetura", en la versión de C#, directamente se usaba el delegado y la función "UpdateList()" para hacerlo pero en este y debido a cómo está estructurado, pensé que era mejor hacerlo así.
A diferencia de los muchos otros códigos que he dicho que voy a "optimizar" (y que no he hecho), este ahora si usa un "Thread" diferente para hacer los cálculos y que no se bloquee la interfaz principal, para eso hacemos uso de la Subclase "UpdateList" que hereda de la clase "AsyncTask" (no se si sea en valido decir "hereda" en java, pero creo que si o si no se entiende). En el post de la semana que viene, veremos cómo usar esta clase para poder brindar un poco de "Multithreading", pero por ahora, al crear la instancia, pasamos tres parámetros que son "<Integer, Void, ArrayList>". Para poder usar la clase "AsyncTask", debemos de sobrecargar algunos de los metodos que la componen, en este caso solo son tres (pero hay más) y son: "onPreExecute()", "doInBackground()" y "onPostExecute()". Respectivamente cada uno hace lo siguiente: Es lo que se ejecutará antes de empezar, la parte principal y que mas tiempo va a consumir y la parte donde se procesaran los resultados.
Con el código anterior podemos probar los números de Munchhausen en un dispositivo con android, en el siguiente post veremos cómo es que funciona la clase "AsyncTask" y cómo nos podra ayudar con tareas en segundo plano. El código cómo de costumbre lo pongo en mi dropbox para que lo descargues, recuerda que a partir de este post, solo ira el código del layout principal y el código java. El APK ya compilado lo puedes descargar de mi dropbox directamente o puedes visitar la seccion de descargas del blog.
Y bien, por ahora es todo, los leo luego.
8/19/2018 01:51:00 p.m.
android
,
AsyncTask
,
java
,
munchhausen
,
programacion
Learning Machine #9 - Conociendo a los archivos GPX.
Hola a todos, el día de hoy vamos a ver cómo es que funcionan los archivos GPX.
Hace poco tiempo, cansado de no hacer nada por la mañana, decidí que sería buena idea volver a hacer un poco de ejercicio. Correr no es una opcion por ahora, estoy tan fuera de forma que probablemente muera de un infarto al primer kilometro, pero no dejare que eso sea un impedimento, así que opte por hacer un recorrido en bicicleta.
Yo soy de esas persona a las que le gusta tener cuantificado todo, asi que si por ejemplo, decidiera correr, necesitaria algo para medir los pasos y en el caso de la bicicleta, algo para medir la distancia.
Una de las maneras más sencillas para hacerlo, es usar mi telefono, al disponer de tantos sensores, debia de haber uno que me ayudara en lo que queria hacer. El GPS que tiene integrado, ayuda a obtener las coordenadas del trayecto.
Actualmente existen muchas aplicaciones que sirven para medir la distancia, velocidad y altitud de un trayecto, la mayoria de las aplicaciones que probé, guardaban toda la informacion en un archivo de extension *.GPX.
Que tendrá cómo resultado algo cómo lo de la imagen siguiente:
No todos las etiquetas son necesarias para que el archivo funcione, pero por default la aplicación que use crea todas las etiquetas anteriores. Cómo eso se me hace un desperdicio, en el siguiente post, vamos ver cómo hacer uso del GPS en un dispositivo android (con GPS, obviamente) y crear nuestros propios archivos GPX para poder llevar un registro de los recorridos en bicicleta que haga.
Por ahora es todo, los leo luego.
Hace poco tiempo, cansado de no hacer nada por la mañana, decidí que sería buena idea volver a hacer un poco de ejercicio. Correr no es una opcion por ahora, estoy tan fuera de forma que probablemente muera de un infarto al primer kilometro, pero no dejare que eso sea un impedimento, así que opte por hacer un recorrido en bicicleta.
Yo soy de esas persona a las que le gusta tener cuantificado todo, asi que si por ejemplo, decidiera correr, necesitaria algo para medir los pasos y en el caso de la bicicleta, algo para medir la distancia.
Una de las maneras más sencillas para hacerlo, es usar mi telefono, al disponer de tantos sensores, debia de haber uno que me ayudara en lo que queria hacer. El GPS que tiene integrado, ayuda a obtener las coordenadas del trayecto.
Actualmente existen muchas aplicaciones que sirven para medir la distancia, velocidad y altitud de un trayecto, la mayoria de las aplicaciones que probé, guardaban toda la informacion en un archivo de extension *.GPX.
Los archivos GPX.
GPX, o GPS eXchange Format (Formato de Intercambio GPS) es un esquema XML pensado para transferir datos GPS entre aplicaciones. Se puede usar para describir puntos (waypoints), recorridos (tracks), y rutas (routes). (Wikipedia/GPX)En resumidas cuentas, un archivo GPX es solamente un archivo XML en el cual se guardan los datos que se obtienen del GPS (u otras fuentes), pero ¿cómo saber que etiquetas se deben de usar? Bueno, las mas importantes (y que usaremos en futuros proyectos) son las siguientes:
- <gpx> Indica el inicio del archivo, aqui se definen los esquemas a utilizar
- <metadata> Indica el inicio de los meta datos.
- <createtime> Fecha de creación.
- <starttime> Fecha y hora de inicio del registro.
- <endtime> Fecha y hora del final del registro.
- <distance> Distancia (en metros).
- <duration> Duración del registro.
- <maxspeed> Velocidad máxima (Km/h).
- <avgspeed> Velocidad promedio (Km/h).
- <vehicle> Tipo de vehículo.
- <description> Descripción.
- <trk> Indica el inicio de una pista.
- <trkseg> Indica el inicio de un segmento de la pista.
- <trkpt lat="00.0000000" lon="-00.0000000"> Un punto de la pista, cómo atributos se usa "lat" para almacenar la latitud y "lon" para almacenar la longitud.
- <ele> Indica la elevación en este punto.
- <speed> Indica la velocidad en este punto.
- <currentdistance> Indica la distancia total actual.
- <timeelapsed> Indica el tiempo transcurrido en este punto.
- <time> Fecha y hora en la que se registro este punto.
<?xml version="1.0" encoding="UTF-8"?> <gpx xmlns="http://www.topografix.com/GPX/1/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1" creator="Speed View GPS" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"> <metadata> <createtime>2017-10-13T09:07:03Z</createtime> <starttime>2017-10-13 08:32:23</starttime> <endtime>2017-10-13 09:07:02</endtime> <distance>7081.146</distance> <duration>00:34:38</duration> <maxspeed>7.91</maxspeed> <avgspeed>3.406369</avgspeed> <vehicle>car</vehicle> <description>oct. 13, 2017 8:32:23</description> </metadata> <trk> <trkseg> <trkpt lat="19.2873547" lon="-98.9054489"> <ele>2229.5</ele> <speed>4.17</speed> <currentdistance>4890.514</currentdistance> <timeelapsed>00:17:36</timeelapsed> <time>2017-10-13T08:49:59Z</time> </trkpt> <trkpt lat="19.2873004" lon="-98.9052929"> <ele>2229.6</ele> <speed>4.68</speed> <currentdistance>4908.041</currentdistance> <timeelapsed>00:17:40</timeelapsed> <time>2017-10-13T08:50:03Z</time> </trkpt> <trkpt lat="19.2872414" lon="-98.9051528"> <ele>2229.2</ele> <speed>5.6099997</speed> <currentdistance>4924.208</currentdistance> <timeelapsed>00:17:43</timeelapsed> <time>2017-10-13T08:50:06Z</time> </trkpt> <trkpt lat="19.2871614" lon="-98.9049907"> <ele>2228.5</ele> <speed>6.16</speed> <currentdistance>4943.435</currentdistance> <timeelapsed>00:17:46</timeelapsed> <time>2017-10-13T08:50:09Z</time> </trkpt> <trkpt lat="19.2871065" lon="-98.9048134"> <ele>2227.8</ele> <speed>6.6099997</speed> <currentdistance>4963.037</currentdistance> <timeelapsed>00:17:49</timeelapsed> <time>2017-10-13T08:50:12Z</time> </trkpt> <trkpt lat="19.2870293" lon="-98.9046317"> <ele>2228.4</ele> <speed>6.8599997</speed> <currentdistance>4983.9917</currentdistance> <timeelapsed>00:17:52</timeelapsed> <time>2017-10-13T08:50:15Z</time> </trkpt> <trkpt lat="19.2869668" lon="-98.9044324"> <ele>2229.5</ele> <speed>7.0699997</speed> <currentdistance>5006.054</currentdistance> <timeelapsed>00:17:55</timeelapsed> <time>2017-10-13T08:50:18Z</time> </trkpt> <trkpt lat="19.2868996" lon="-98.9042383"> <ele>2229.0</ele> <speed>6.22</speed> <currentdistance>5027.7915</currentdistance> <timeelapsed>00:17:58</timeelapsed> <time>2017-10-13T08:50:21Z</time> </trkpt> <trkpt lat="19.2868314" lon="-98.9040744"> <ele>2229.4</ele> <speed>5.42</speed> <currentdistance>5046.6025</currentdistance> <timeelapsed>00:18:01</timeelapsed> <time>2017-10-13T08:50:24Z</time> </trkpt> <trkpt lat="19.2867868" lon="-98.9039388"> <ele>2229.3</ele> <speed>5.17</speed> <currentdistance>5061.6934</currentdistance> <timeelapsed>00:18:04</timeelapsed> <time>2017-10-13T08:50:27Z</time> </trkpt> <trkpt lat="19.2867203" lon="-98.9037992"> <ele>2229.0</ele> <speed>5.42</speed> <currentdistance>5078.158</currentdistance> <timeelapsed>00:18:07</timeelapsed> <time>2017-10-13T08:50:30Z</time> </trkpt> <trkpt lat="19.2866701" lon="-98.9036398"> <ele>2229.2</ele> <speed>5.75</speed> <currentdistance>5095.8345</currentdistance> <timeelapsed>00:18:10</timeelapsed> <time>2017-10-13T08:50:33Z</time> </trkpt> <trkpt lat="19.2866279" lon="-98.9035024"> <ele>2229.4</ele> <speed>4.94</speed> <currentdistance>5111.036</currentdistance> <timeelapsed>00:18:13</timeelapsed> <time>2017-10-13T08:50:36Z</time> </trkpt> <trkpt lat="19.2865573" lon="-98.903338"> <ele>2230.8</ele> <speed>5.35</speed> <currentdistance>5130.0107</currentdistance> <timeelapsed>00:18:17</timeelapsed> <time>2017-10-13T08:50:40Z</time> </trkpt> <trkpt lat="19.2865119" lon="-98.9031719"> <ele>2232.1</ele> <speed>5.7</speed> <currentdistance>5148.191</currentdistance> <timeelapsed>00:18:20</timeelapsed> <time>2017-10-13T08:50:43Z</time> </trkpt> <trkpt lat="19.2864684" lon="-98.9030063"> <ele>2231.6</ele> <speed>5.2999997</speed> <currentdistance>5166.3203</currentdistance> <timeelapsed>00:18:23</timeelapsed> <time>2017-10-13T08:50:46Z</time> </trkpt> <trkpt lat="19.2864122" lon="-98.9028658"> <ele>2231.3</ele> <speed>4.96</speed> <currentdistance>5182.3594</currentdistance> <timeelapsed>00:18:26</timeelapsed> <time>2017-10-13T08:50:49Z</time> </trkpt> <trkpt lat="19.2863534" lon="-98.9026856"> <ele>2231.1</ele> <speed>5.0899997</speed> <currentdistance>5202.404</currentdistance> <timeelapsed>00:18:30</timeelapsed> <time>2017-10-13T08:50:53Z</time> </trkpt> <trkpt lat="19.286309" lon="-98.9025323"> <ele>2230.1</ele> <speed>5.73</speed> <currentdistance>5219.2666</currentdistance> <timeelapsed>00:18:33</timeelapsed> <time>2017-10-13T08:50:56Z</time> </trkpt> <trkpt lat="19.2862376" lon="-98.9023771"> <ele>2230.8</ele> <speed>5.62</speed> <currentdistance>5237.3994</currentdistance> <timeelapsed>00:18:36</timeelapsed> <time>2017-10-13T08:50:59Z</time> </trkpt> <trkpt lat="19.286167" lon="-98.902229"> <ele>2230.1</ele> <speed>5.7999997</speed> <currentdistance>5254.8184</currentdistance> <timeelapsed>00:18:39</timeelapsed> <time>2017-10-13T08:51:02Z</time> </trkpt> <trkpt lat="19.2861174" lon="-98.9020688"> <ele>2229.7</ele> <speed>5.19</speed> <currentdistance>5272.635</currentdistance> <timeelapsed>00:18:42</timeelapsed> <time>2017-10-13T08:51:05Z</time> </trkpt> <trkpt lat="19.2860754" lon="-98.9019254"> <ele>2229.5</ele> <speed>5.14</speed> <currentdistance>5288.4106</currentdistance> <timeelapsed>00:18:45</timeelapsed> <time>2017-10-13T08:51:08Z</time> </trkpt> <trkpt lat="19.2860339" lon="-98.9017654"> <ele>2228.9</ele> <speed>4.89</speed> <currentdistance>5306.137</currentdistance> <timeelapsed>00:18:48</timeelapsed> <time>2017-10-13T08:51:11Z</time> </trkpt> <trkpt lat="19.2859513" lon="-98.9016034"> <ele>2227.7</ele> <speed>4.52</speed> <currentdistance>5325.536</currentdistance> <timeelapsed>00:18:52</timeelapsed> <time>2017-10-13T08:51:15Z</time> </trkpt> <trkpt lat="19.285881" lon="-98.901449"> <ele>2227.4</ele> <speed>4.81</speed> <currentdistance>5343.5986</currentdistance> <timeelapsed>00:18:56</timeelapsed> <time>2017-10-13T08:51:19Z</time> </trkpt> <trkpt lat="19.2858317" lon="-98.9013101"> <ele>2228.0</ele> <speed>4.54</speed> <currentdistance>5359.328</currentdistance> <timeelapsed>00:18:59</timeelapsed> <time>2017-10-13T08:51:22Z</time> </trkpt> <trkpt lat="19.2857715" lon="-98.9011595"> <ele>2228.3</ele> <speed>4.48</speed> <currentdistance>5376.5923</currentdistance> <timeelapsed>00:19:03</timeelapsed> <time>2017-10-13T08:51:26Z</time> </trkpt> <trkpt lat="19.2857089" lon="-98.9010114"> <ele>2228.3</ele> <speed>4.35</speed> <currentdistance>5393.6396</currentdistance> <timeelapsed>00:19:07</timeelapsed> <time>2017-10-13T08:51:30Z</time> </trkpt> <trkpt lat="19.2856641" lon="-98.9008596"> <ele>2228.6</ele> <speed>3.6799998</speed> <currentdistance>5410.394</currentdistance> <timeelapsed>00:19:11</timeelapsed> <time>2017-10-13T08:51:34Z</time> </trkpt> <trkpt lat="19.2855949" lon="-98.9006918"> <ele>2228.4</ele> <speed>4.63</speed> <currentdistance>5429.6284</currentdistance> <timeelapsed>00:19:15</timeelapsed> <time>2017-10-13T08:51:38Z</time> </trkpt> <trkpt lat="19.2855428" lon="-98.9005373"> <ele>2228.0</ele> <speed>4.48</speed> <currentdistance>5446.902</currentdistance> <timeelapsed>00:19:19</timeelapsed> <time>2017-10-13T08:51:42Z</time> </trkpt> <trkpt lat="19.2855065" lon="-98.9003938"> <ele>2227.8</ele> <speed>5.7</speed> <currentdistance>5462.5405</currentdistance> <timeelapsed>00:19:22</timeelapsed> <time>2017-10-13T08:51:45Z</time> </trkpt> <trkpt lat="19.2854442" lon="-98.9002132"> <ele>2227.5</ele> <speed>6.69</speed> <currentdistance>5482.7666</currentdistance> <timeelapsed>00:19:25</timeelapsed> <time>2017-10-13T08:51:48Z</time> </trkpt> <trkpt lat="19.2853641" lon="-98.9000407"> <ele>2227.6</ele> <speed>6.8399997</speed> <currentdistance>5502.969</currentdistance> <timeelapsed>00:19:28</timeelapsed> <time>2017-10-13T08:51:51Z</time> </trkpt> <trkpt lat="19.2853049" lon="-98.8998464"> <ele>2228.1</ele> <speed>6.7999997</speed> <currentdistance>5524.433</currentdistance> <timeelapsed>00:19:31</timeelapsed> <time>2017-10-13T08:51:54Z</time> </trkpt> <trkpt lat="19.2852443" lon="-98.8996762"> <ele>2228.1</ele> <speed>6.25</speed> <currentdistance>5543.546</currentdistance> <timeelapsed>00:19:34</timeelapsed> <time>2017-10-13T08:51:57Z</time> </trkpt> <trkpt lat="19.2851887" lon="-98.8994991"> <ele>2229.2</ele> <speed>6.6</speed> <currentdistance>5563.195</currentdistance> <timeelapsed>00:19:37</timeelapsed> <time>2017-10-13T08:52:00Z</time> </trkpt> <trkpt lat="19.2851245" lon="-98.8993265"> <ele>2229.4</ele> <speed>6.25</speed> <currentdistance>5582.688</currentdistance> <timeelapsed>00:19:40</timeelapsed> <time>2017-10-13T08:52:03Z</time> </trkpt> <trkpt lat="19.2850556" lon="-98.8991673"> <ele>2230.2</ele> <speed>6.44</speed> <currentdistance>5601.079</currentdistance> <timeelapsed>00:19:43</timeelapsed> <time>2017-10-13T08:52:06Z</time> </trkpt> <trkpt lat="19.2850039" lon="-98.8989882"> <ele>2231.2</ele> <speed>6.43</speed> <currentdistance>5620.7734</currentdistance> <timeelapsed>00:19:46</timeelapsed> <time>2017-10-13T08:52:09Z</time> </trkpt> <trkpt lat="19.284942" lon="-98.8988195"> <ele>2230.0</ele> <speed>6.42</speed> <currentdistance>5639.808</currentdistance> <timeelapsed>00:19:49</timeelapsed> <time>2017-10-13T08:52:12Z</time> </trkpt> <trkpt lat="19.2848768" lon="-98.8986502"> <ele>2229.3</ele> <speed>6.33</speed> <currentdistance>5659.0356</currentdistance> <timeelapsed>00:19:52</timeelapsed> <time>2017-10-13T08:52:15Z</time> </trkpt> <trkpt lat="19.2848074" lon="-98.8984819"> <ele>2228.3</ele> <speed>6.2999997</speed> <currentdistance>5678.3735</currentdistance> <timeelapsed>00:19:55</timeelapsed> <time>2017-10-13T08:52:18Z</time> </trkpt> <trkpt lat="19.2847355" lon="-98.8983052"> <ele>2227.7</ele> <speed>6.24</speed> <currentdistance>5698.695</currentdistance> <timeelapsed>00:19:58</timeelapsed> <time>2017-10-13T08:52:21Z</time> </trkpt> <trkpt lat="19.2846779" lon="-98.8981337"> <ele>2227.4</ele> <speed>6.24</speed> <currentdistance>5717.8203</currentdistance> <timeelapsed>00:20:01</timeelapsed> <time>2017-10-13T08:52:24Z</time> </trkpt> <trkpt lat="19.2846228" lon="-98.8979652"> <ele>2227.3</ele> <speed>6.0899997</speed> <currentdistance>5736.634</currentdistance> <timeelapsed>00:20:04</timeelapsed> <time>2017-10-13T08:52:27Z</time> </trkpt> <trkpt lat="19.2845703" lon="-98.8978222"> <ele>2228.1</ele> <speed>5.62</speed> <currentdistance>5752.7866</currentdistance> <timeelapsed>00:20:07</timeelapsed> <time>2017-10-13T08:52:30Z</time> </trkpt> <trkpt lat="19.2845295" lon="-98.8976665"> <ele>2228.6</ele> <speed>5.0299997</speed> <currentdistance>5769.9194</currentdistance> <timeelapsed>00:20:10</timeelapsed> <time>2017-10-13T08:52:33Z</time> </trkpt> <trkpt lat="19.2844665" lon="-98.8974973"> <ele>2228.4</ele> <speed>5.3199997</speed> <currentdistance>5789.093</currentdistance> <timeelapsed>00:20:14</timeelapsed> <time>2017-10-13T08:52:37Z</time> </trkpt> <trkpt lat="19.2844181" lon="-98.8973579"> <ele>2228.4</ele> <speed>5.3199997</speed> <currentdistance>5804.718</currentdistance> <timeelapsed>00:20:17</timeelapsed> <time>2017-10-13T08:52:40Z</time> </trkpt> <trkpt lat="19.284345" lon="-98.8971953"> <ele>2228.7</ele> <speed>5.46</speed> <currentdistance>5823.6953</currentdistance> <timeelapsed>00:20:20</timeelapsed> <time>2017-10-13T08:52:43Z</time> </trkpt> <trkpt lat="19.2843003" lon="-98.8970488"> <ele>2228.7</ele> <speed>5.6099997</speed> <currentdistance>5839.8765</currentdistance> <timeelapsed>00:20:23</timeelapsed> <time>2017-10-13T08:52:46Z</time> </trkpt> <trkpt lat="19.2842265" lon="-98.8968865"> <ele>2230.9</ele> <speed>5.7599998</speed> <currentdistance>5858.798</currentdistance> <timeelapsed>00:20:26</timeelapsed> <time>2017-10-13T08:52:49Z</time> </trkpt> <trkpt lat="19.2841685" lon="-98.8967161"> <ele>2229.8</ele> <speed>5.7599998</speed> <currentdistance>5877.8633</currentdistance> <timeelapsed>00:20:29</timeelapsed> <time>2017-10-13T08:52:52Z</time> </trkpt> <trkpt lat="19.2840928" lon="-98.8965554"> <ele>2230.3</ele> <speed>5.52</speed> <currentdistance>5896.795</currentdistance> <timeelapsed>00:20:32</timeelapsed> <time>2017-10-13T08:52:55Z</time> </trkpt> <trkpt lat="19.2840414" lon="-98.8964041"> <ele>2230.1</ele> <speed>5.83</speed> <currentdistance>5913.686</currentdistance> <timeelapsed>00:20:35</timeelapsed> <time>2017-10-13T08:52:58Z</time> </trkpt> <trkpt lat="19.2839835" lon="-98.8962396"> <ele>2230.4</ele> <speed>6.31</speed> <currentdistance>5932.1357</currentdistance> <timeelapsed>00:20:38</timeelapsed> <time>2017-10-13T08:53:01Z</time> </trkpt> <trkpt lat="19.2839417" lon="-98.8960511"> <ele>2230.1</ele> <speed>5.81</speed> <currentdistance>5952.5576</currentdistance> <timeelapsed>00:20:41</timeelapsed> <time>2017-10-13T08:53:04Z</time> </trkpt> <trkpt lat="19.2838761" lon="-98.8958997"> <ele>2230.2</ele> <speed>5.79</speed> <currentdistance>5970.072</currentdistance> <timeelapsed>00:20:44</timeelapsed> <time>2017-10-13T08:53:07Z</time> </trkpt> <trkpt lat="19.283805" lon="-98.8957721"> <ele>2229.7</ele> <speed>5.31</speed> <currentdistance>5985.7344</currentdistance> <timeelapsed>00:20:47</timeelapsed> <time>2017-10-13T08:53:10Z</time> </trkpt> <trkpt lat="19.2837329" lon="-98.8956155"> <ele>2228.8</ele> <speed>4.69</speed> <currentdistance>6004.08</currentdistance> <timeelapsed>00:20:51</timeelapsed> <time>2017-10-13T08:53:14Z</time> </trkpt> <trkpt lat="19.2836277" lon="-98.8955173"> <ele>2229.0</ele> <speed>5.2599998</speed> <currentdistance>6019.7734</currentdistance> <timeelapsed>00:20:54</timeelapsed> <time>2017-10-13T08:53:17Z</time> </trkpt> <trkpt lat="19.2835321" lon="-98.8953833"> <ele>2229.3</ele> <speed>5.47</speed> <currentdistance>6037.611</currentdistance> <timeelapsed>00:20:57</timeelapsed> <time>2017-10-13T08:53:20Z</time> </trkpt> <trkpt lat="19.2834933" lon="-98.8952368"> <ele>2229.5</ele> <speed>5.35</speed> <currentdistance>6053.6636</currentdistance> <timeelapsed>00:21:00</timeelapsed> <time>2017-10-13T08:53:23Z</time> </trkpt> <trkpt lat="19.2834481" lon="-98.8950919"> <ele>2228.7</ele> <speed>5.22</speed> <currentdistance>6069.696</currentdistance> <timeelapsed>00:21:03</timeelapsed> <time>2017-10-13T08:53:26Z</time> </trkpt> <trkpt lat="19.283385" lon="-98.8949165"> <ele>2228.7</ele> <speed>4.7799997</speed> <currentdistance>6089.425</currentdistance> <timeelapsed>00:21:07</timeelapsed> <time>2017-10-13T08:53:30Z</time> </trkpt> <trkpt lat="19.2833551" lon="-98.8947334"> <ele>2229.2</ele> <speed>4.8399997</speed> <currentdistance>6108.9653</currentdistance> <timeelapsed>00:21:11</timeelapsed> <time>2017-10-13T08:53:34Z</time> </trkpt> </trkseg> </trk> </gpx>
Que tendrá cómo resultado algo cómo lo de la imagen siguiente:
![]() |
| Puedes ver el archivo GPX en http://maplorer.com/ |
Por ahora es todo, los leo luego.
11/12/2017 03:52:00 p.m.
android
,
Android studio
,
aprende
,
GPX
,
programacion
Vamos a programar #41 - Números palindrómicos (ver. Java for android)
Hola de nuevo a todos, el día de hoy y despúes de unas largas y mal merecidas "vacaciones", vamos a continuar con más temas de programación.
La última vez que vimos un post sobre programación, vimos la conjetura de los números palíndrómicos e hicimos un programa en C# para windows. Hoy y cómo en ocasiones anteriores, vamos a ver cómo hacer una versión para android.
El código.
El código en java que hace funcionar las cosas es el siguiente:
package com.mdev.numerospalindromos;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import java.lang.String;
import java.math.BigInteger;
import android.widget.ArrayAdapter;
import java.util.ArrayList;
public class MainActivity extends Activity {
Button BtnCalculate;
TextView TxtNumberIn;
TextView TxtIterations;
ListView LVResultados;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BtnCalculate = (Button)findViewById(R.id.BtnCalculate);
TxtNumberIn = (TextView)findViewById(R.id.TXTNumberIn);
TxtIterations = (TextView)findViewById(R.id.TxtIterations);
LVResultados = (ListView)findViewById(R.id.LVResults);
BtnCalculate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
GetNumber(TxtNumberIn.getText().toString(), Integer.parseInt(TxtIterations.getText().toString()));
}
});
}
private boolean IsPalindrome(String Number)
{
String Value = ReverseNumber(Number);
if (Number.equals(Value))
return true;
else
return false;
}
private String ReverseNumber(String NumberIn)
{
char[] charArray = NumberIn.toCharArray();
char[] OutArray = new char[charArray.length];
for (int i = charArray.length-1; i >= 0 ; i--){
OutArray[charArray.length - 1 - i] = charArray[i];
}
return new String(OutArray);
}
private void GetNumber(String Number1, Integer MaxIterations)
{
ArrayList Items = new ArrayList();
int Iterator = 1;
if (IsPalindrome(Number1))
{
Items.add("0 iteraciones " + Number1 + " cumple la conjetura");
}
else
{
BigInteger Result = new BigInteger(Number1);
while (!IsPalindrome(Result.toString()))
{
BigInteger NewNumber = new BigInteger(ReverseNumber(Result.toString()));
Result = Result.add(NewNumber);
if (Iterator >= MaxIterations)
{
break;
}
Iterator += 1;
Items.add(Iterator + " iteraciones " + Result);
}
if (IsPalindrome(Result.toString()))
Items.add("La conjetura se cumple");
else
Items.add("La conjetura no se cumple.");
}
final ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1,Items);
LVResultados.setAdapter(adapter);
}
}
El código consta de 3 funciones. La primera de ellas en orden de aparición, es: IsPalindrome y aunque su nombre lo diga o lo haga parecer, esta función no es la encargada de hacer los cálculos. La función simplemente comprueba que el valor que se pasa cómo parámetro, cumpla con la condición: "es igual si se lee al derecho que al revés", usando la función "ReverseNumber". Si la condición se cumple, la función regresa un valor booleano "true" en caso contrario regresa "false".
La función "ReverseNumber", sirve para invertir el orden de los dígitos de un número, es decir; el primer número pasa a ser el último y viceversa. hay que recordar que la conjetura nos dice que se debe de obtener un palíndromo si se suma un número que sea el mismo número pero invertido. Esta función recibe un parámetro del tipo "String" que representa el número que queremos invertir. La función usa dos "Arrays" que contienen los dígitos almacenados como caracteres, por lo que "2" es algo totalmente diferente a 2, el parámetro de entrada, es el primero en separarse, con eso obtenemos el tamaño que tendrá el otro "Array" y lo asignamos al momento de crearlo. Para formar el valor de salida, simplemente recorremos en orden inverso el "Array" que contiene los digitos del valor de entrada. La función regresa un valor del tipo "String" que representa el parámetro de entrada en orden inverso.
Finalmente el procedimiento que se encarga de comprobar la conjetura es "GetNumber". Este procedimiento hace todos los pasos. El procedimiento recibe dos parámetros, el primero del tipo "String", es el número al cual le queremos aplica la conjetura, el segundo, es in valor del tipo "Integer" que contiene el valor máximo de la iteraciones. Antes de si quiera empezar con los cálculos, comprobamos que el valor que se ingresa cumpla la conjetura, si lo hace, simplemente informamos que el número es palíndromo y terminamos el procedimiento. En caso contrario, empezamos convirtiendo el valor de "String " a "BigInteger". Luego iniciamos un bucle "while" en el cual haremos uso de la función "IsPalindrome" mientras está sea falsa o mientras el valor de la variable "Iterator" sea menor que el parámetro "MaxIterations". Cuando cualquiera de las condiciones es verdadera, salimos del bucle; si salimos debido a que la función "IsPalindrome" resulta verdadera, mostramos un mensaje indicando que el número cumplió con la conjetura; pero si la salida del bucle se debe a que el número de iteraciones alcanzo el máximo indicado por el usuario, mostramos un mensaje que la conjetura no se cumplió. En este caso, que un número no cumpla la conjetura en X numero de iteraciones, no quieres decir que por ello este exento, algunas veces bastará con aumentar el número de iteraciones.
Y bien, por ahora es todo, al igual que las otra aplicaciones, el código fuente pronto la publicaré en la sección de descargas, el APK ya compilado, lo puedes descargar de mi dropbox.
La función "ReverseNumber", sirve para invertir el orden de los dígitos de un número, es decir; el primer número pasa a ser el último y viceversa. hay que recordar que la conjetura nos dice que se debe de obtener un palíndromo si se suma un número que sea el mismo número pero invertido. Esta función recibe un parámetro del tipo "String" que representa el número que queremos invertir. La función usa dos "Arrays" que contienen los dígitos almacenados como caracteres, por lo que "2" es algo totalmente diferente a 2, el parámetro de entrada, es el primero en separarse, con eso obtenemos el tamaño que tendrá el otro "Array" y lo asignamos al momento de crearlo. Para formar el valor de salida, simplemente recorremos en orden inverso el "Array" que contiene los digitos del valor de entrada. La función regresa un valor del tipo "String" que representa el parámetro de entrada en orden inverso.
Finalmente el procedimiento que se encarga de comprobar la conjetura es "GetNumber". Este procedimiento hace todos los pasos. El procedimiento recibe dos parámetros, el primero del tipo "String", es el número al cual le queremos aplica la conjetura, el segundo, es in valor del tipo "Integer" que contiene el valor máximo de la iteraciones. Antes de si quiera empezar con los cálculos, comprobamos que el valor que se ingresa cumpla la conjetura, si lo hace, simplemente informamos que el número es palíndromo y terminamos el procedimiento. En caso contrario, empezamos convirtiendo el valor de "String " a "BigInteger". Luego iniciamos un bucle "while" en el cual haremos uso de la función "IsPalindrome" mientras está sea falsa o mientras el valor de la variable "Iterator" sea menor que el parámetro "MaxIterations". Cuando cualquiera de las condiciones es verdadera, salimos del bucle; si salimos debido a que la función "IsPalindrome" resulta verdadera, mostramos un mensaje indicando que el número cumplió con la conjetura; pero si la salida del bucle se debe a que el número de iteraciones alcanzo el máximo indicado por el usuario, mostramos un mensaje que la conjetura no se cumplió. En este caso, que un número no cumpla la conjetura en X numero de iteraciones, no quieres decir que por ello este exento, algunas veces bastará con aumentar el número de iteraciones.
Y bien, por ahora es todo, al igual que las otra aplicaciones, el código fuente pronto la publicaré en la sección de descargas, el APK ya compilado, lo puedes descargar de mi dropbox.
Antes de terminar, debo aclarar que la aplicación aun no es a prueba de errores, y peor aun, no es a prueba de si misma. Todo es meramente ilustrativo, porque la aplicación va a hacer lo que el usuario le diga y por el momento no es recomendable pasar de las 1000 iteraciones; aunque la mayoría de los numero comprendidos entre 1 y 1000 la cumplen en unos cuantos pasos, puede pasar que haya un número que ni con 20000 iteraciones la cumpla, al hacer 20000 pasos la aplicación demandará memoria y capacidad de procesamiento por lo que las cosas se pueden volver inestables, además como todas las comprobaciones se hacen en el hilo principal, la aplicación se bloqueará hasta que termine (cualquiera de los dos casos, si se cumple o si se llego al limite establecido), en los siguiente post veremos cómo usar "threads" (C# y Java) y cómo manejarlas un poco, para; si por ejemplo; comenzamos un proceso largo, lo podamos detener en cualquier momento (si aun así quieres probar los alcances de tu dispositivo, puedes probar el número 196 con el límite que más gustes, pero quedas advertido que ni con 24000 iteraciones se cumple la conjetura).
Por ahora es todo. Los leo luego.
10/20/2017 07:49:00 p.m.
android
,
Android studio
,
BigInteger
,
palíndromo
,
programacion
Vamos a programar #39 - La conjetura de Collatz (Números maravillosos) Versión Android.
Hola de nuevo a todos, el día de hoy vamos a continuar con la conjetura de Collatz.
En el post anterior de "Vamos a programar", hicimos la versión de C#, cosa que resulto realmente fácil ya que en C# se puede hacer uso del tipo "BigInteger". En java para android, también existe el tipo "BigInteger" y en esta ocasión veremos un poco de cómo usarlo.
Para empezar crearemos los controles que vamos a necesitar, está aplicación consta únicamente de 4 controles (5 en realidad, puedes revisarlo en el código completo).
Para tratar de simplificar un poco el código, hice lo traté de hacer lo mismo que en c#. Primero, iba a pedir un numero en formato de texto, luego crear una funcion que calcule la conjetura de Collatz y mostrar cada paso que se dio en un "ListView".
La cosa es sencilla, y podemos repetir lo que ya habíamos hecho, pero en java, a diferencia de c#, el tipo BigInteger no es tan simple de manejar.
En Java, el tipo BigInteger dispone de sus operaciones por separado, las comparaciones se deben de hacer desde los métodos contenidos en el tipo BigInteger. Eso quiere decir que si queremos comparar el número "1" con el valor BigInteger "1", no podemos realizarlo porque a diferencia de C#, aquí no se hace una conversión implícita; nosotros debemos de hacerla de forma explicita haciendo uso de los métodos contenidos en el tipo "BigInteger".
Retomando nuestro código, primero veremos la función "IsEven". la función "IsEven" recibe un parámetro del tipo "BigInteger", este, es el numero de cual queremos determinar si es par o no. Para hacerlo, hacemos uso de dos variables; la primera, llamada "Result" del tipo "BigInteger", se crea y se le asigna el valor que resulta del uso del método del parámetro de entrada "Number", el método que se usa es ".remainder()", este método lo que hace, es devolver el residuo de la división entre el numero "Number" y el parámetro que se le asigne; para este caso, debemos de dividir entre dos, pero cómo no se puede usar directamente "2", usamos otro procedimiento del tipo "BigInteger". el método que usamos es "BigInteger.valueOf()", este procedimiento lo que hace, es crear una versión del número que se pasa cómo parámetro en tipo "BigInteger".
Lo anterior se hace para determinar si un número es par o no (hay que recordar que los número pares, son aquellos que al ser divididos entre dos, dan un número entero). El resultado que obtenemos es 1 o 0 (cualquiera de los dos del tipo BigInteger).
Solo nos queda hacer la comparación, si el resultado es "0" entonces el número es par, para hacer la comparación, usamos otro procedimiento más del tipo "BigInteger". Hacemos uso de la función ".compareTo", lo hacemos en la variable resultado y le pasamos cómo parámetro una constante llamada "BigInteger.ZERO"; la constante vale 0. la función regresa un valor del tipo int con cualquiera de los 3 valores posibles:
Si el valor de la variable "result" es "0", la función IsEven devuelve "true", en caso contrario, "false".
El procedimiento "CalculateCollatz", es el encargado de hacer los cálculos, para eso, primero creamos la variable del tipo "BigIntger" llamada "MyNumber". Al usar el constructor del tipo "BigInteger", le podemos pasar un valor del tipo "String", en este caso le asignamos el parámetro "Number", con eso creamos un valor del tipo "BigInteger" con valor del "String" del parámetro.
Después creamos un bucle "while" con la condición "Number" sea mayor que "BigInteger.ONE". Con la función "IsEven", podemos replicar lo que hicimos en c# y dentro del bucle, verificamos si el número es par o no y dependiendo del caso, hacer los cálculos.
Para multiplicar un valor "BigInteger", debemos de hacer uso del método "BigInteger.multiply", este recibe cómo parámetro un "BigInteger" que será el multiplicador y el resultado, sera un valor BigInteger con el valor de la multiplicación. Para dividir un valor "BigInteger", debemos de hacer uso del método "BigInteger.divide", este recibe cómo parámetro un "BigInteger" que será el divisor y el resultado, sera un valor "BigInteger" con el valor de la división. lo mismo para la suma, debemos de hacer uso de "BigInteger.add".
Finalmente creamos un "ArrayAdapter" al que agregaremos todos los pasos que se hicieron y este se asina al control "ListView".
El resultado. Puedes descargar la APK con la aplicación ya compilada, el código completo lo subiré en breve, agregare threads para que la interfaz no se bloquee (aunque así como esta funciona bien), aunque con el código anterior, se cubre toda la parte lógica de la aplicación.
Bien, por ahora es todo.
Los leo luego
En el post anterior de "Vamos a programar", hicimos la versión de C#, cosa que resulto realmente fácil ya que en C# se puede hacer uso del tipo "BigInteger". En java para android, también existe el tipo "BigInteger" y en esta ocasión veremos un poco de cómo usarlo.
El código.
El código que hace funcionar la aplicación de la conjetura de Collatz en java para android es el siguiente:package com.mdev.collatz;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import java.math.BigInteger;
import java.util.ArrayList;
import static android.R.attr.button;
public class MainActivity extends AppCompatActivity {
Button BtnCalculate;
TextView TxtNumberIn;
ListView LVResultados;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BtnCalculate = (Button) findViewById(R.id.BtnCalculate);
TxtNumberIn = (TextView) findViewById(R.id.TXTNumberIn);
LVResultados = (ListView) findViewById(R.id.LVResults);
BtnCalculate.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view) {
CalculateCollatz(TxtNumberIn.getText().toString());
}
});
}
private void CalculateCollatz(String Number)
{
ArrayList Items = new ArrayList();
BigInteger MyNumber = new BigInteger(Number);
while (MyNumber.compareTo(BigInteger.ONE) > 0)
{
if (IsEven(MyNumber)) {
MyNumber = MyNumber.divide(BigInteger.valueOf(2));
Items.add(MyNumber.toString());
}else{
MyNumber = MyNumber.multiply(BigInteger.valueOf(3));
MyNumber = MyNumber.add(BigInteger.valueOf(1));
Items.add(MyNumber.toString());
}
}
final ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1,Items);
LVResultados.setAdapter(adapter);
}
private boolean IsEven(BigInteger Number){
BigInteger Result = Number.remainder(BigInteger.valueOf(2));
int CompareResult = Result.compareTo(BigInteger.ZERO);
if(CompareResult == 0)
{
return true;
}else{
return false;
}
}
}
Para empezar crearemos los controles que vamos a necesitar, está aplicación consta únicamente de 4 controles (5 en realidad, puedes revisarlo en el código completo).
- 1 Textview.
- 1 EditText
- 1 Button
- 1 Listview
Para tratar de simplificar un poco el código, hice lo traté de hacer lo mismo que en c#. Primero, iba a pedir un numero en formato de texto, luego crear una funcion que calcule la conjetura de Collatz y mostrar cada paso que se dio en un "ListView".
La cosa es sencilla, y podemos repetir lo que ya habíamos hecho, pero en java, a diferencia de c#, el tipo BigInteger no es tan simple de manejar.
En Java, el tipo BigInteger dispone de sus operaciones por separado, las comparaciones se deben de hacer desde los métodos contenidos en el tipo BigInteger. Eso quiere decir que si queremos comparar el número "1" con el valor BigInteger "1", no podemos realizarlo porque a diferencia de C#, aquí no se hace una conversión implícita; nosotros debemos de hacerla de forma explicita haciendo uso de los métodos contenidos en el tipo "BigInteger".
Retomando nuestro código, primero veremos la función "IsEven". la función "IsEven" recibe un parámetro del tipo "BigInteger", este, es el numero de cual queremos determinar si es par o no. Para hacerlo, hacemos uso de dos variables; la primera, llamada "Result" del tipo "BigInteger", se crea y se le asigna el valor que resulta del uso del método del parámetro de entrada "Number", el método que se usa es ".remainder()", este método lo que hace, es devolver el residuo de la división entre el numero "Number" y el parámetro que se le asigne; para este caso, debemos de dividir entre dos, pero cómo no se puede usar directamente "2", usamos otro procedimiento del tipo "BigInteger". el método que usamos es "BigInteger.valueOf()", este procedimiento lo que hace, es crear una versión del número que se pasa cómo parámetro en tipo "BigInteger".
Lo anterior se hace para determinar si un número es par o no (hay que recordar que los número pares, son aquellos que al ser divididos entre dos, dan un número entero). El resultado que obtenemos es 1 o 0 (cualquiera de los dos del tipo BigInteger).
Solo nos queda hacer la comparación, si el resultado es "0" entonces el número es par, para hacer la comparación, usamos otro procedimiento más del tipo "BigInteger". Hacemos uso de la función ".compareTo", lo hacemos en la variable resultado y le pasamos cómo parámetro una constante llamada "BigInteger.ZERO"; la constante vale 0. la función regresa un valor del tipo int con cualquiera de los 3 valores posibles:
- -1 si el valor es menor que el BigInteger desde el cual se llama.
- 0 si el valor es igual que el BigInteger desde el cual se llama.
- 1 si el valor es mayor que el BigInteger desde el cual se llama.
Si el valor de la variable "result" es "0", la función IsEven devuelve "true", en caso contrario, "false".
El procedimiento "CalculateCollatz", es el encargado de hacer los cálculos, para eso, primero creamos la variable del tipo "BigIntger" llamada "MyNumber". Al usar el constructor del tipo "BigInteger", le podemos pasar un valor del tipo "String", en este caso le asignamos el parámetro "Number", con eso creamos un valor del tipo "BigInteger" con valor del "String" del parámetro.
Después creamos un bucle "while" con la condición "Number" sea mayor que "BigInteger.ONE". Con la función "IsEven", podemos replicar lo que hicimos en c# y dentro del bucle, verificamos si el número es par o no y dependiendo del caso, hacer los cálculos.
Para multiplicar un valor "BigInteger", debemos de hacer uso del método "BigInteger.multiply", este recibe cómo parámetro un "BigInteger" que será el multiplicador y el resultado, sera un valor BigInteger con el valor de la multiplicación. Para dividir un valor "BigInteger", debemos de hacer uso del método "BigInteger.divide", este recibe cómo parámetro un "BigInteger" que será el divisor y el resultado, sera un valor "BigInteger" con el valor de la división. lo mismo para la suma, debemos de hacer uso de "BigInteger.add".
Finalmente creamos un "ArrayAdapter" al que agregaremos todos los pasos que se hicieron y este se asina al control "ListView".
El resultado. Puedes descargar la APK con la aplicación ya compilada, el código completo lo subiré en breve, agregare threads para que la interfaz no se bloquee (aunque así como esta funciona bien), aunque con el código anterior, se cubre toda la parte lógica de la aplicación.
Bien, por ahora es todo.
Los leo luego
8/12/2017 08:43:00 p.m.
android
,
Android studio
,
aprende
,
BigInteger
,
conjetura de collatz
,
programacion
Vamos a programar #37 - DecToAny, Versión java (Android).
Hola a todos, el día de hoy vamos a ver una tercera entrega de la aplicación DecToAny, en los últimos dos post, vimos cómo crear una versión para Windows (hecha en C#), una versión para la web (hecha en javascript) y finalmente el día de hoy vamos a ver una versión para Android (hecha en Java).
Con esto, tendremos todos los controles necesarios para que el usuario interactue con la aplicación, ahora solo queda implementar el código que hace funcionar las cosas.
Creando la interfaz.
La interfaz principal está compuesta por 4 componentes:
- 1 TextView.
- 1 EditText (Numérico).
- 1 Button.
- 1 ListView.
<?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.mdev.com.dectoany.MainActivity"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" tools:layout_editor_absoluteX="8dp" tools:layout_editor_absoluteY="8dp"> <TextView android:id="@+id/lblNumberIn" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Número a convertir" /> <EditText android:id="@+id/TXTNumberIn" android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" android:inputType="number" /> <Button android:id="@+id/BtnConvert" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Convertir" /> <ListView android:id="@+id/LVResults" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> </android.support.constraint.ConstraintLayout>
Con esto, tendremos todos los controles necesarios para que el usuario interactue con la aplicación, ahora solo queda implementar el código que hace funcionar las cosas.
El Código que hace funcionar las cosas.
El código es muy parecido al que usamos para la versión de C#. Solo que en este caso, vamos a usar el control ListView para mostrar los resultados de las conversiones.
El código java de DecToAny es el siguiente:
package com.mdev.com.dectoany;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MainActivity extends Activity {
Button BtnConvert;
ListView LVResults;
TextView TxtNumberIn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BtnConvert = (Button) findViewById(R.id.BtnConvert);
TxtNumberIn = (TextView) findViewById(R.id.TXTNumberIn);
LVResults = (ListView) findViewById(R.id.LVResults);
BtnConvert.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
DoConvert();
}
});
}
private void DoConvert(){
ArrayList Items = new ArrayList();
String CurrentNumber = TxtNumberIn.getText().toString();
int MyNumber = Integer.parseInt(CurrentNumber);
for (int I = 2; I < 30; I++){
Items.add(ListToString(NumbersList(MyNumber, I))+"\n"+"Base "+ I);
}
final ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1,Items);
LVResults.setAdapter(adapter);
}
private String ListToString(List<Integer> Numbers)
{
Collections.reverse(Numbers);
String Result = "";
for (int i = 0; i < Numbers.size(); i++){
int CurrentNumber = Numbers.get(i);
if (CurrentNumber < 10)
Result += CurrentNumber;
else
Result += NumberToChar(Numbers.get(i));
}
return Result;
}
private char NumberToChar(int Number){
return (char)(Number + 55);
}
private List<Integer> NumbersList(Integer InNumber, int Base) {
Integer LastNumber = InNumber;
Integer Garbage;
List<Integer> result = new ArrayList<Integer>();
if (LastNumber < Base) {
result.add(LastNumber);
}
else {
if (LastNumber >= Base) {
do {
Garbage = LastNumber % Base;
LastNumber = LastNumber / Base;
if (LastNumber < Base) {
result.add(Garbage);
result.add(LastNumber);
} else {
result.add(Garbage);
}
} while (LastNumber >= Base);
}
}
return result;
}
}
Para esta aplicación vamos usar 4 funciones, la primera de ellas en orden de uso (no de aparicion) es "NumberList", esta es la función que va a realizar los cálculos; cómo parámetros de entrada, recibirá un parámetro del tipo "Integer" llamado "InNumber" que es el número decimal que queremos convertir; seguido de una valor del tipo "int" llamado "Base", este; cómo su nombre lo indica; es la base de destino a la cual queremos convertir nuestro número decimal. La función regresa una lista del tipo "List<Integer>" con los valores de los dígitos para formar el número, pero en orden inverso.
Después tenemos la función "ListToString" que será la encargada de formar un número y devolverlo en forma de "String". Esta función recibe cómo parámetro un lista del tipo "List<Integer>". Esta función se encarga primero; en invertir el orden de la lista que se ingresa cómo parámetro. Después comprueba si el valor es menor a 10 (decimal), si es así, simplemente agrega al string "Result" (variable interna de la función) el valor actual, en caso contrario, manda a llamar a la función "NumberToChar" que se encargara de asignar una letra de la A a la Z a los valores mayores a 10. Finalmente devuelve un "string" que contiene la representación de los resultados de la función "NumberToList" en el formato adecuado para que cualquier persona lo pueda entender.
La función "NumberToChar" simplemente devuelve el numero que se ingresa cómo parámetro + 55.
Para la aplicación de Android también usamos un procedimiento llamado "DoConvert"; en el cual se manda a llamar a las otras funciones dentro de un bucle que va del 2 al 29. En este procedimiento se crea un "ArrayAdapter" que se llenará con los valores que se crean en el ciclo "for" y finalmente se asignan al "ListView".
Con esto podemos obtener de forma fácil el valor de un numero decimal en 27 bases diferentes. En todas las aplicaciones (Android, Windows, Web)no he revisado los errores que puedan haber, no porque sea perezoso o algo similar), pero un error critico existe en la version Web, en esta al poder escoger cual es la base a la que queremos convertir nuestro numero, podemos introducir base 1, pero esta base es imposible de usar, ya que solo disponemos del numero 0, entonces al hacer las divisiones, entramos al bucle "while", pero nunca podremos salir de el, y en algún momento la memoria se acabará hasta que finalmente el navegador en el cual se usa falle. Aunque el sentido común dice que no se debe de hacer lo antes descrito, nunca falta aquel que lo haga solo para saber que pasa. Para evitarlo basta con comprobar las base de destino, si es menor a 2, simplemente hay que informarle al usuario y terminar la ejecución.
Y bien, por ahora es todo, la aplicación compilada la puedes descargar de mi dropbox, el código lo subiré un poco después, primero voy a corregir un error minusculo en el proyecto. (Debería de ser com.mdev.dectoany, en su lugar puse com.mdev.com.dectoany ).
Los leo luego
Después tenemos la función "ListToString" que será la encargada de formar un número y devolverlo en forma de "String". Esta función recibe cómo parámetro un lista del tipo "List<Integer>". Esta función se encarga primero; en invertir el orden de la lista que se ingresa cómo parámetro. Después comprueba si el valor es menor a 10 (decimal), si es así, simplemente agrega al string "Result" (variable interna de la función) el valor actual, en caso contrario, manda a llamar a la función "NumberToChar" que se encargara de asignar una letra de la A a la Z a los valores mayores a 10. Finalmente devuelve un "string" que contiene la representación de los resultados de la función "NumberToList" en el formato adecuado para que cualquier persona lo pueda entender.
La función "NumberToChar" simplemente devuelve el numero que se ingresa cómo parámetro + 55.
Para la aplicación de Android también usamos un procedimiento llamado "DoConvert"; en el cual se manda a llamar a las otras funciones dentro de un bucle que va del 2 al 29. En este procedimiento se crea un "ArrayAdapter" que se llenará con los valores que se crean en el ciclo "for" y finalmente se asignan al "ListView".
Con esto podemos obtener de forma fácil el valor de un numero decimal en 27 bases diferentes. En todas las aplicaciones (Android, Windows, Web)no he revisado los errores que puedan haber, no porque sea perezoso o algo similar), pero un error critico existe en la version Web, en esta al poder escoger cual es la base a la que queremos convertir nuestro numero, podemos introducir base 1, pero esta base es imposible de usar, ya que solo disponemos del numero 0, entonces al hacer las divisiones, entramos al bucle "while", pero nunca podremos salir de el, y en algún momento la memoria se acabará hasta que finalmente el navegador en el cual se usa falle. Aunque el sentido común dice que no se debe de hacer lo antes descrito, nunca falta aquel que lo haga solo para saber que pasa. Para evitarlo basta con comprobar las base de destino, si es menor a 2, simplemente hay que informarle al usuario y terminar la ejecución.
Y bien, por ahora es todo, la aplicación compilada la puedes descargar de mi dropbox, el código lo subiré un poco después, primero voy a corregir un error minusculo en el proyecto. (Debería de ser com.mdev.dectoany, en su lugar puse com.mdev.com.dectoany ).
Los leo luego
5/18/2017 02:13:00 p.m.
android
,
Android studio
,
binario
,
Convertidor de bases
,
decimal
,
hexadecimal
,
how to
,
java
,
octal
,
programacion
Vamos a programar #29 - Inútil Apps #2 - Creando un socket bluetooth (arduino y android)
Hola a todos, el día de hoy vamos a continuar con Clock View. Ahora con todo el hardware listo y con la parte de software de arduino también listo, solo queda crear una forma de interactuar con el hardware de Clock View. Al carecer de botones solo nos queda la opción de usar el modulo Bluetooth, para comunicarnos por medio de este, podemos usar aplicaciones que ya estan disponibles en la Playstore (S2 Terminal for bluetooth por ejemplo), pero esa no es la idea del blog, en la mediada de lo posible trataremos de usar nuestro propio software para hacer las cosas.
El dia de hoy les quiero presentar Clock View para android, una aplicación que tiene cómo unica función; conectar con el modulo bluetooth HC-05 o HC-06 y cambiar los ajustes de Clock View.
La aplicacion dispone de 6 botones y una barra de "seek". Para usarla, primero debes de asegurarte de que todo el hardware está listo, despues debes de iniciar la conexion con el boton "Conectar con clock view", cuando aparace un mensaje diciendo que la conexion se llevo a cabo, puedes modificar los ajustes.
Hoy solo veremos el código, en el siguiente post, explicaré un poco acerca de cómo se realiza el intercambio de datos entre arduino y android.
Cómo todo el código requiere una explicacion detallada (o si no quieres meterte en programacion), por ahora solo dejo el APK ya compilado,
Los leo luego.
El dia de hoy les quiero presentar Clock View para android, una aplicación que tiene cómo unica función; conectar con el modulo bluetooth HC-05 o HC-06 y cambiar los ajustes de Clock View.
La aplicacion dispone de 6 botones y una barra de "seek". Para usarla, primero debes de asegurarte de que todo el hardware está listo, despues debes de iniciar la conexion con el boton "Conectar con clock view", cuando aparace un mensaje diciendo que la conexion se llevo a cabo, puedes modificar los ajustes.
Hoy solo veremos el código, en el siguiente post, explicaré un poco acerca de cómo se realiza el intercambio de datos entre arduino y android.
El código.
El siguiente es el código en java que se encarga de hacer funcionar las cosas, los estilos y demás "layouts", irán en la descarga completa al final del post.
package com.mdev.clockview;
import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.os.Build;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Handler;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import java.lang.reflect.Method;
import java.util.Set;
import java.util.Calendar;
import static com.mdev.clockview.R.layout.paired_devices_list;
public class MainActivity extends Activity {
BluetoothAdapter myBluetoothAdapter = null;
Button BtnConnect, BtnOnOff, BtnSecondsShow, BtnSyncHour, BtnChangeFormat,BtnDisconnect;
SeekBar SkBright;
TextView TxtArduinoRec, TxtBrigthValue;
String address = null;
private ProgressDialog progress;
BluetoothSocket btSocket = null;
private boolean isBtConnected = false;
private static final UUID myUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
final int RECEIVE_MESSAGE = 1;
private StringBuilder sb = new StringBuilder();
private ConnectedThread mConnectedThread;
Handler h;
private Set<BluetoothDevice> pairedDevices;
ListView myListView;
ArrayAdapter BTArrayAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
BtnConnect = (Button)findViewById(R.id.BtnConnect);
myListView = (ListView)findViewById(R.id.BTList);
TxtArduinoRec = (TextView)findViewById(R.id.TxtArduinoReturn);
BtnOnOff = (Button)findViewById(R.id.BtnOn);
BtnSecondsShow = (Button)findViewById(R.id.BtnShowS);
BtnSyncHour = (Button)findViewById(R.id.BtnSync);
BtnChangeFormat = (Button)findViewById(R.id.BtnFormat);
BtnDisconnect = (Button)findViewById(R.id.BtnDisconnect);
SkBright = (SeekBar)findViewById(R.id.SKBrillo);
TxtBrigthValue = (TextView)findViewById(R.id.txtSeekValue);
myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (myBluetoothAdapter == null) {
msg("El bluetooth no es soportado por este dispositivo");
}
else {
msg("Esperando la conexion");
}
SkBright.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
TxtBrigthValue.setText(String.valueOf(progress));
if (isBtConnected)
{
String result = String.format(">SETB%1$02d", progress);
mConnectedThread.write(result);
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
BtnConnect.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!myBluetoothAdapter.isEnabled()) {
Intent turnOnIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(turnOnIntent, 1);
}else{
showBTDialog();
}
}
});
BtnOnOff.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view){
if (isBtConnected)
{
mConnectedThread.write(">SCRA");
}
}
});
BtnSecondsShow.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view){
if (isBtConnected)
{
mConnectedThread.write(">DISS");
}
}
});
BtnSyncHour.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view){
if (isBtConnected)
{
mConnectedThread.write(BuildHourToArduino());
}
}
});
BtnChangeFormat.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view){
if (isBtConnected)
{
mConnectedThread.write(">SETF");
}
}
});
BtnDisconnect.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View view){
if (isBtConnected)
{
Disconnect();
}
}
});
//encargado de procesar los mensajes.
h = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what)
{
case RECEIVE_MESSAGE:
byte[] readBuf = (byte[]) msg.obj;
String strIncom = new String(readBuf, 0, msg.arg1);
sb.append(strIncom);
int endOfLineIndex = sb.indexOf("\r\n");
if (endOfLineIndex > 0)
{
String sbprint = sb.substring(0, endOfLineIndex);
sb.delete(0, sb.length());
TxtArduinoRec.setText("Data from Arduino: " + sbprint);
}
break;
}
};
};
}
private void msg(String s)
{
Toast.makeText(getApplicationContext(),s,Toast.LENGTH_LONG).show();
}
private String BuildHourToArduino(){
//>SETH2016122119001004
//>SETHAAAAMMDDHHMMSSWW
Calendar c = Calendar.getInstance();
int DiaSemana = c.get(Calendar.DAY_OF_WEEK);
int Anio = c.get(Calendar.YEAR);
int Mes = c.get(Calendar.MONTH);
int Dia = c.get(Calendar.DAY_OF_MONTH);
int Horas = c.get(Calendar.HOUR_OF_DAY);
int Minutos = c.get(Calendar.MINUTE);
int Segundos = c.get(Calendar.SECOND);
String DateForArduino = String.format(">SETH%1$04d%2$02d%3$02d%4$02d%5$02d%6$02d%7$02d",
Anio, Mes + 1, Dia, Horas, Minutos,Segundos, DiaSemana);
msg(DateForArduino);
return DateForArduino;
}
private void Disconnect()
{
if (btSocket!=null)
{
try
{
btSocket.close();
isBtConnected = false;
}
catch (IOException e)
{ msg("Error");}
}
}
private AdapterView.OnItemClickListener myListClickListener = new AdapterView.OnItemClickListener()
{
public void onItemClick (AdapterView<?> av, View v, int arg2, long arg3) {
if (myBluetoothAdapter.isEnabled()) {
String info = ((TextView) v).getText().toString();
address = info.substring(info.length() - 17);
msg(address);
} else {
msg("El Bluetooth debe de estar encendido.");
}
}
};
public void showBTDialog() {
final AlertDialog.Builder popDialog = new AlertDialog.Builder(this);
final LayoutInflater inflater = (LayoutInflater) this.getSystemService(LAYOUT_INFLATER_SERVICE);
final View Viewlayout = inflater.inflate(paired_devices_list, (ViewGroup) findViewById(R.id.bt_list));
popDialog.setTitle("Dispositivos Bluetooth:");
popDialog.setView(Viewlayout);
myListView = (ListView) Viewlayout.findViewById(R.id.BTList);
BTArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);
myListView.setAdapter(BTArrayAdapter);
pairedDevices = myBluetoothAdapter.getBondedDevices();
for(BluetoothDevice device : pairedDevices)
BTArrayAdapter.add(device.getName()+ "\n" + device.getAddress());
myListView.setOnItemClickListener(myListClickListener);
// Button OK
popDialog.setPositiveButton("Conectar",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
if (address != null)
{
new ConnectBT().execute();
}
dialog.dismiss();
}
});
popDialog.create();
popDialog.show();
}
private class ConnectedThread extends Thread {
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[256];
int bytes;
while (true) {
try {
bytes = mmInStream.read(buffer);
h.obtainMessage(RECEIVE_MESSAGE, bytes, -1, buffer).sendToTarget();
} catch (IOException e) {
break;
}
}
}
public void write(String message) {
byte[] msgBuffer = message.getBytes();
try {
mmOutStream.write(msgBuffer);
} catch (IOException e) {
msg("Error al enviar: " + e.getMessage());
}
}
}
private class ConnectBT extends AsyncTask<Void, Void, Void>
{
private boolean ConnectSuccess = true;
@Override
protected void onPreExecute()
{
progress = ProgressDialog.show(MainActivity.this, "Conectando...", "Espera...!!!");
}
@Override
protected Void doInBackground(Void... devices)
{
try
{
if (btSocket == null || !isBtConnected)
{
myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothAdapter.getDefaultAdapter().cancelDiscovery();
BluetoothDevice dispositivo = myBluetoothAdapter.getRemoteDevice(address);
btSocket = createBluetoothSocket(dispositivo);
btSocket.connect();
}
}
catch (IOException e)
{
ConnectSuccess = false;
}
return null;
}
private BluetoothSocket createBluetoothSocket(BluetoothDevice device) throws IOException {
if(Build.VERSION.SDK_INT >= 10){
try {
final Method m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class });
return (BluetoothSocket) m.invoke(device, myUUID);
} catch (Exception e) {
msg("No se pudo crear la conexion");
}
}
return device.createRfcommSocketToServiceRecord(myUUID);
}
@Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
if (!ConnectSuccess)
{
msg("La conexion falló, intentelo de nuevo");
isBtConnected = false;
}
else
{
msg("Conectado.");
isBtConnected = true;
mConnectedThread = new ConnectedThread(btSocket);
mConnectedThread.start();
}
progress.dismiss();
}
}
}
Cómo todo el código requiere una explicacion detallada (o si no quieres meterte en programacion), por ahora solo dejo el APK ya compilado,
Los leo luego.
1/26/2017 06:02:00 p.m.
android
,
bluetooth
,
capacitores
,
clock view
,
ds1302
,
electronica basica
,
how to
,
java
,
LED
,
matriz led
,
max7219
,
programacion
,
Resistencias
,
rfcomm
,
socket bluetooth
Vamos a programar #21 - Formateando código para HTML.
Hola de nuevo a todos. El día de hoy traigo una aplicación muy corta. Cómo todos sabrán, la mayor parte de este blog trata sobre cosas de programación, por lo que es muy común que publique código fuente en variedad de lenguajes.
Pero al momento de publicar algo, surge un pequeño problema, al copiar el código del editor al blog, este pierde todo el formato. Actualmente uso unos scripts que permiten darle color a la sintaxis, pero cosas como la indentación, se pierden. En lo personal, siempre me gusta ver código que este visiblemente bien, es decir; que se distinga en "donde estás". Un indicador muy claro, es la sangría. Si vez que todo está a la misma distancia, resulta fácil ver que todo es parte de un "if" o parte de un "while".
Para solucionar todo esto y poder formatear el código de una forma más rapida, decidí hacer una aplicación que se encargue del trabajo sucio.
La aplicación es realmente simple, de hecho solo son 10 lineas de código, es una versión beta, y lo único que hace es convertir todos los caracteres que no están admitidos en el html (como "< o >" ).
Dentro las funciones que nos proporciona el api de .NET existe a siguiente función:
Está función se encuentra en el espacio System.Net; y hace exactamente lo que queremos, formatear todo el código para que lo podamos usar en el lenguaje HTML. Pero bueno si solo quisiera hacer eso no sería una solución a la indentación, de hecho si revisamos el siguiente código (que viene de este blog)
Pero eso no es lo que quiero, si nos damos cuenta todas las tabulaciones han sido reemplazadas por espacios que visualmente son más pequeños.
En cambio cuan usamos el código producido por el programa; lucirá de la siguiente forma:
Por ahora el código solo hace eso, pero si por ejemplo el código tiene espacios en blanco, no obtendremos un resultado diferente al del primer caso.
En la siguiente versión vamos implementar funciones que se encarguen de hacer todo de forma automatica. Si lo que quieres es publicar código, lo ,mejor es que luzca, que al momento de echar un vistazo rápido, puedas ver que al menos está bien estructurado.
Además lo dejo así porque ando un poco corto de tiempo, pero espero ya no estarlo para la próxima semana. Como siempre, el programa lo puedes bajar de dropbox, en cuanto lo actualice haré el siguiente Post.
Por ahora es todo. Los leo luego.
Pero al momento de publicar algo, surge un pequeño problema, al copiar el código del editor al blog, este pierde todo el formato. Actualmente uso unos scripts que permiten darle color a la sintaxis, pero cosas como la indentación, se pierden. En lo personal, siempre me gusta ver código que este visiblemente bien, es decir; que se distinga en "donde estás". Un indicador muy claro, es la sangría. Si vez que todo está a la misma distancia, resulta fácil ver que todo es parte de un "if" o parte de un "while".
Para solucionar todo esto y poder formatear el código de una forma más rapida, decidí hacer una aplicación que se encargue del trabajo sucio.
La aplicación es realmente simple, de hecho solo son 10 lineas de código, es una versión beta, y lo único que hace es convertir todos los caracteres que no están admitidos en el html (como "< o >" ).
Dentro las funciones que nos proporciona el api de .NET existe a siguiente función:
RtBResultCode.Text = WebUtility.HtmlEncode(RTBInputCode.Text);
Está función se encuentra en el espacio System.Net; y hace exactamente lo que queremos, formatear todo el código para que lo podamos usar en el lenguaje HTML. Pero bueno si solo quisiera hacer eso no sería una solución a la indentación, de hecho si revisamos el siguiente código (que viene de este blog)
<resources> <string name="app_name">Calculador de resistencias</string> <string-array name="Colores1"> <item>Negro</item> <item>cafe</item> <item>Rojo</item> <item>Naranja</item> <item>Amarillo</item> <item>Verde</item> <item>Azul</item> <item>Violeta</item> <item>Gris</item> <item>Blanco</item> </string-array> <string-array name="Colores2"> <item>Dorado</item> <item>Plata</item> </string-array> </resources>
Pero eso no es lo que quiero, si nos damos cuenta todas las tabulaciones han sido reemplazadas por espacios que visualmente son más pequeños.
En cambio cuan usamos el código producido por el programa; lucirá de la siguiente forma:
<resources> <string name="app_name">Calculador de resistencias</string> <string-array name="Colores1"> <item>Negro</item> <item>cafe</item> <item>Rojo</item> <item>Naranja</item> <item>Amarillo</item> <item>Verde</item> <item>Azul</item> <item>Violeta</item> <item>Gris</item> <item>Blanco</item> </string-array> <string-array name="Colores2"> <item>Dorado</item> <item>Plata</item> </string-array> </resources>
Por ahora el código solo hace eso, pero si por ejemplo el código tiene espacios en blanco, no obtendremos un resultado diferente al del primer caso.
En la siguiente versión vamos implementar funciones que se encarguen de hacer todo de forma automatica. Si lo que quieres es publicar código, lo ,mejor es que luzca, que al momento de echar un vistazo rápido, puedas ver que al menos está bien estructurado.
Además lo dejo así porque ando un poco corto de tiempo, pero espero ya no estarlo para la próxima semana. Como siempre, el programa lo puedes bajar de dropbox, en cuanto lo actualice haré el siguiente Post.
Por ahora es todo. Los leo luego.
11/10/2016 08:51:00 p.m.
android
,
basic html
,
csharp
,
CSS
,
estilos css
,
how to
,
HTML
,
Javascript
,
MatLab
,
programacion
Vamos a programar #5 - Calculadora de resistencias para android.
Terminando lo anterior
El dia de hoy vamos a terminar de hacer una aplicacion para android que nos ayudara a obtener el valor de una resistencia basado en los colores que está posea.
En el post anterior vimos como implementar la interfaz.
Asi que ahora nos vamos a ocupar del código que hace funcionar las cosas.
Terminando la interfaz.
Para los datos que van a tener los controles Spinner, decidí cargarlos desde los recursos, Para eso en el panel "Project" buscaremos la siguiente ruta: app>res>values>strings.xml lo abriremos agregaremos entre las etiquetas <resources></resources> el siguiente codigo:
Ahora solo queda implementar el codigo en java. lo puedes copiar asi como está en app>java
com.mdev.claculadoraderesistencia>mainactivity.java, se incluyen los comentarios pertinentes para poder implementarlo
<resources> <string name="app_name">Calculador de resistencias</string> <string-array name="Colores1"> <item>Negro</item> <item>cafe</item> <item>Rojo</item> <item>Naranja</item> <item>Amarillo</item> <item>Verde</item> <item>Azul</item> <item>Violeta</item> <item>Gris</item> <item>Blanco</item> </string-array> <string-array name="Colores2"> <item>Dorado</item> <item>Plata</item> </string-array> </resources>
Ahora solo queda implementar el codigo en java. lo puedes copiar asi como está en app>java
com.mdev.claculadoraderesistencia>mainactivity.java, se incluyen los comentarios pertinentes para poder implementarlo
package com.mdev.rcalc.calculadoraderesistencias;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;
import static java.lang.Math.pow;
public class MainActivity extends AppCompatActivity {
//Spinners
Spinner SpnC1,SpnC2,SpnC3,SpnC4;
//Boton
Button BtnCallIt;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BtnCallIt = (Button)findViewById(R.id.BtnCalculateIt);
//En esta seccion llenamos los Spinners con los datos de los recursos.
//Asociamos los controles del layput a nustras variables de control (spinner)
SpnC1 = (Spinner)findViewById(R.id.SpnColor1);
SpnC2 = (Spinner)findViewById(R.id.SpnColor2);
SpnC3 = (Spinner)findViewById(R.id.SpnColor3);
//Usamos el mismo adaptador para los primeros 3 ya que contienen los mismos datos.
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.Colores1, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
//Asignamos el contenido del adaptador a nuestros controles
SpnC1.setAdapter(adapter);
SpnC2.setAdapter(adapter);
SpnC3.setAdapter(adapter);
//Hacemos lo mismo para el cuarto, pero aqui usamos el recurso "Colores2" que contiene los
//datos para la cuarta franja, solo en este caso.
SpnC4 = (Spinner)findViewById(R.id.SpnColor4);
ArrayAdapter<CharSequence> adapter2 = ArrayAdapter.createFromResource(this,
R.array.Colores2, android.R.layout.simple_spinner_item);
adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
SpnC4.setAdapter(adapter2);
//Creamos el handler para el evento click
BtnCallIt.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view)
{
//Usamos la funcion ShowDialog para mostrar el resultado
ShowDialog("El Resultado es:",BuildNumber(SpnC1.getSelectedItemPosition(),SpnC2.getSelectedItemPosition(),
SpnC3.getSelectedItemPosition())+" "+GetTolerance(SpnC4.getSelectedItemPosition()));
}
});
}
//Mostrar dialog de manera sencilla
private void ShowDialog(String Title, String Caption)
{
new AlertDialog.Builder(this)
.setTitle(Title)
.setMessage(Caption)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// algo
}
})
.setIcon(android.R.drawable.ic_menu_info_details)
.show();
}
//Funcion para obtener la toleranacia de la resistencia
private String GetTolerance(int Value)
{
if (Value == 0)
return "+5% de tolerancia";
else
return "+10% de tolerancia";
}
//Funcion para generar el valor de la resistencia basado en sus colores
private String BuildNumber(int Value1, int Value2, int Value3)
{
String Significant;
//Los manejo en string para solo concatenarlos obtener el valor
Significant = Integer.toString(Value1) + Integer.toString(Value2);
//Convertimos el valor a uno numerico y lo multiplicamos a la potencia de 10
double Resultado = Integer.parseInt(Significant)*pow(10,Value3);
//Para regresar el valor en KΩ
if (Resultado/1000 >= 1 && Resultado/1e3 < 1000 )
{
return (String.valueOf(Resultado / 1e3) + "KΩ");
}
//Para regresar el valor en MΩ
if (Resultado/1e6 >= 1)
{
return (String.valueOf(Resultado / 1e6) + "MΩ");
}else{
//Regresamos el valor en Ω
return (String.valueOf(Resultado)+"Ω");
}
}
}
Al implementar la aplicacion y correrla se obtiene lo anterior, como lo dije esto solo es ilustrativo, no es para aprender a prgramar, pero si tienes dudas no dudes en preguntar.
Por sí se ofrece, el proyecto entero lo puedes descargar aquí, lo puedes importar completo para ver como funciona.
Los leo luego
7/08/2016 05:00:00 a.m.
android
,
Android studio
,
aprende
,
codigo de colores para resistencias
,
DIY
,
electronica basica
,
how to
,
programacion
,
Resistencias
Suscribirse a:
Entradas
(
Atom
)















