Partendo da un esempio ripreso da qui e' stato possibile sviluppare un programma che evita il problema del post precedente, ovvero viene sviluppato un calcolo molto lungo senza che Android generi un errore.
Il sistema si basa sull'utilizzo dei task asincroni.
Il programma che calcola il valore di Pi Greco mediante il metodo di Montecarlo
Il task asincrono viene lanciato dall'evento EventTouch..per evitare che pressioni multiple possano generare piu' task asincroni viene settata la variaible booleana corre quando il primo task asincrono parte e non viene rilasciata fino al suo termine
-------------------------------------------------------------------------------
package com.async;
import java.util.Random;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.TextView;
public class AsyncActivity extends Activity {
//queste variabili sono visibili sia dal Main che dal TaskAsync
boolean corre;
double q = 0;
private TextView pi;
//*********** Task Asincrono per il calcolo
public class BackgroundAsyncTask extends AsyncTask<Void, Boolean, Void> {
private ProgressDialog pDialog;
@Override
protected Void doInBackground(Void... params) {
//calcolo di PiGreco
double s = 0;
int max_cicli = 10000;
Random generator = new Random();
for (int t=0;t<max_cicli;t++)
{
Log.d("task",Double.toString(t));
double x = (2*generator.nextDouble())-1;
double y = (2*generator.nextDouble())-1;
double a = (x*x)+(y*y);
if (a<=1)
{
s++;
}
}
q = (4*s/max_cicli);
return null;
}
@Override
protected void onPostExecute(Void result) {
//evento generato al termine del task
corre = false;
pDialog.dismiss();
pi.setText(Double.toString(q));
}
@Override
protected void onPreExecute() {
//evento generato all'inizio del task
corre = true;
pDialog = ProgressDialog.show(AsyncActivity.this,"Prego attendere...", "Calcolo in corso ...", true);
}
@Override
protected void onProgressUpdate(Boolean... values) {
}
}
//******** MAIN
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
pi = (TextView) findViewById(R.id.pigreco);
}
public boolean onTouchEvent(MotionEvent event)
{
if (!corre) new BackgroundAsyncTask().execute();
return false;
}
}
martedì 17 aprile 2012
lunedì 16 aprile 2012
ANR su Android
tentando di modificare il codice di Mandelbrot per aggiungere uno zoom basato sull'evento touch mi sono imbattuto nel seguente errore
Reacting to signal 3 Wrote stack traces to '/data/anr/traces.txt'
indagando un po' meglio ho capito di essermi imbattuto in un errore di ANR (Application Not Responding) che viene segnalato quando l'applicazione non risponde ad un evento di input entro 5 secondi (questo il mio caso) oppure un task non e' finito entro 10 secondi
Fino a quando l'insieme di Mandelbrot viene gestito nella procedura principale la procedura termina correttamente mentre quando il comando calcola() viene lanciato dall'evento TouchEvent il programma si blocca.
di seguito il codice per riprodurre l'errore
package com.mandelbrot.explorer;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Bitmap.Config;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.widget.ImageView;
public class MandelbrotExplorerActivity extends Activity {
private static double re_min = -2.5;
private static double re_max = 1.0;
private static double im_min = -1.0;
private static double im_max = 1.0;
private static int iterazioni = 100;
private double y;
private double x;
private double ynew;
private double xnew;
private int test;
private double re_factor;
private double im_factor;
public boolean zoom;
public Bitmap bitmap;
public Paint paint;
public Canvas canvas;
private int width;
private int height;
private double b;
private double a;
public ImageView view;
/** Called when the activity is first created. */
private void calcola(double re_min1, double re_max1, double im_min1, double im_max1)
{
zoom = false;
re_factor = (re_max1 - re_min1);
im_factor = (im_max1 - im_min1);
// recupera le informazioni sulle dimensioni dello schermo
for (int i=0;i<width;i++)
{
for (int j=0;j<height;j++)
{
b = im_min + i * im_factor / width;
a = re_min + j * re_factor / height;
x = 0.0;
y = 0.0;
test = 0;
for (int k=0;k<iterazioni;k++)
{
xnew = x * x - y * y + a;
ynew = 2 * x * y + b;
if (((xnew*xnew)+(ynew*ynew))>4)
{
test = k;
k = iterazioni;
}
x = xnew;
y = ynew;
}
if (test%2 == 1)
{
//punto bianco
canvas.drawPoint(i, j, paint);
}
}
}
zoom = true;
}
public void onCreate(Bundle savedInstanceState) {
//StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().penaltyDeath().build());
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
view = (ImageView) findViewById(R.id.imageView1);
Display display = getWindowManager().getDefaultDisplay();
width = display.getWidth(); //240
height = display.getHeight();//320
bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
paint = new Paint();
paint.setColor(Color.WHITE);
canvas = new Canvas(bitmap);
canvas.drawColor(Color.BLACK);
view.setImageBitmap(bitmap);
calcola(re_min,re_max,im_min,im_max);
}
public boolean onTouchEvent(MotionEvent event) {
int x = (int)event.getX();
int y = (int)event.getY();
Log.d("pos_x",Double.toString(x));
Log.d("pos_y",Double.toString(y));
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
}
calcola(-1.0,0.5,-1.0,0.5);
return false;
}
}
Reacting to signal 3 Wrote stack traces to '/data/anr/traces.txt'
indagando un po' meglio ho capito di essermi imbattuto in un errore di ANR (Application Not Responding) che viene segnalato quando l'applicazione non risponde ad un evento di input entro 5 secondi (questo il mio caso) oppure un task non e' finito entro 10 secondi
Fino a quando l'insieme di Mandelbrot viene gestito nella procedura principale la procedura termina correttamente mentre quando il comando calcola() viene lanciato dall'evento TouchEvent il programma si blocca.
di seguito il codice per riprodurre l'errore
package com.mandelbrot.explorer;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Bitmap.Config;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.widget.ImageView;
public class MandelbrotExplorerActivity extends Activity {
private static double re_min = -2.5;
private static double re_max = 1.0;
private static double im_min = -1.0;
private static double im_max = 1.0;
private static int iterazioni = 100;
private double y;
private double x;
private double ynew;
private double xnew;
private int test;
private double re_factor;
private double im_factor;
public boolean zoom;
public Bitmap bitmap;
public Paint paint;
public Canvas canvas;
private int width;
private int height;
private double b;
private double a;
public ImageView view;
/** Called when the activity is first created. */
private void calcola(double re_min1, double re_max1, double im_min1, double im_max1)
{
zoom = false;
re_factor = (re_max1 - re_min1);
im_factor = (im_max1 - im_min1);
// recupera le informazioni sulle dimensioni dello schermo
for (int i=0;i<width;i++)
{
for (int j=0;j<height;j++)
{
b = im_min + i * im_factor / width;
a = re_min + j * re_factor / height;
x = 0.0;
y = 0.0;
test = 0;
for (int k=0;k<iterazioni;k++)
{
xnew = x * x - y * y + a;
ynew = 2 * x * y + b;
if (((xnew*xnew)+(ynew*ynew))>4)
{
test = k;
k = iterazioni;
}
x = xnew;
y = ynew;
}
if (test%2 == 1)
{
//punto bianco
canvas.drawPoint(i, j, paint);
}
}
}
zoom = true;
}
public void onCreate(Bundle savedInstanceState) {
//StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().penaltyDeath().build());
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
view = (ImageView) findViewById(R.id.imageView1);
Display display = getWindowManager().getDefaultDisplay();
width = display.getWidth(); //240
height = display.getHeight();//320
bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
paint = new Paint();
paint.setColor(Color.WHITE);
canvas = new Canvas(bitmap);
canvas.drawColor(Color.BLACK);
view.setImageBitmap(bitmap);
calcola(re_min,re_max,im_min,im_max);
}
public boolean onTouchEvent(MotionEvent event) {
int x = (int)event.getX();
int y = (int)event.getY();
Log.d("pos_x",Double.toString(x));
Log.d("pos_y",Double.toString(y));
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
}
calcola(-1.0,0.5,-1.0,0.5);
return false;
}
}
venerdì 13 aprile 2012
Swipe gesture
import android.app.Activity;
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.widget.TextView;
public class FlingActivity extends Activity {
private TextView gestureEvent;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
gestureEvent = (TextView)findViewById(R.id.test);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
return gestureDetector.onTouchEvent(event);
}
SimpleOnGestureListener simpleOnGestureListener
= new SimpleOnGestureListener(){
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
String swipe = "";
float sensitvity = 50;
// TODO Auto-generated method stub
if((e1.getX() - e2.getX()) > sensitvity){
swipe += "Swipe Left\n";
}else if((e2.getX() - e1.getX()) > sensitvity){
swipe += "Swipe Right\n";
}else{
swipe += "\n";
}
if((e1.getY() - e2.getY()) > sensitvity){
swipe += "Swipe Up\n";
}else if((e2.getY() - e1.getY()) > sensitvity){
swipe += "Swipe Down\n";
}else{
swipe += "\n";
}
gestureEvent.setText(swipe);
return super.onFling(e1, e2, velocityX, velocityY);
}
};
GestureDetector gestureDetector
= new GestureDetector(simpleOnGestureListener);
}
import android.os.Bundle;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.widget.TextView;
public class FlingActivity extends Activity {
private TextView gestureEvent;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
gestureEvent = (TextView)findViewById(R.id.test);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
return gestureDetector.onTouchEvent(event);
}
SimpleOnGestureListener simpleOnGestureListener
= new SimpleOnGestureListener(){
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
String swipe = "";
float sensitvity = 50;
// TODO Auto-generated method stub
if((e1.getX() - e2.getX()) > sensitvity){
swipe += "Swipe Left\n";
}else if((e2.getX() - e1.getX()) > sensitvity){
swipe += "Swipe Right\n";
}else{
swipe += "\n";
}
if((e1.getY() - e2.getY()) > sensitvity){
swipe += "Swipe Up\n";
}else if((e2.getY() - e1.getY()) > sensitvity){
swipe += "Swipe Down\n";
}else{
swipe += "\n";
}
gestureEvent.setText(swipe);
return super.onFling(e1, e2, velocityX, velocityY);
}
};
GestureDetector gestureDetector
= new GestureDetector(simpleOnGestureListener);
}
giovedì 12 aprile 2012
Semplice Insieme Julia
non poteva mancare il fedele compagno dell'insieme di Mandelbrot ovvero l'insieme di Julia
In pratica esiste una corrispondenza tra le coordinate nel piano complesso dell'insieme di Mandelbrot ed il corrispettivo insieme di Julia
L'esempio sopra riportato e' corrispondente al punto-0.125;0.75 dell'insieme di Mandelbrot
Il codice e' estremamente simile a quello del precedente post
package com.julia;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.Display;
import android.widget.ImageView;
public class JuliaIntActivity extends Activity {
/** Called when the activity is first created. */
private static final double re_min = -2;
private static final double re_max = 2.0;
private static final double im_min = -2.0;
private static final double im_max = 2.0;
private static int iterazioni = 100;
private double ynew;
private double xnew;
private double a;
private double b;
private int test;
private double re_factor;
private double im_factor;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView view = (ImageView) findViewById(R.id.imageView1);
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth(); //240
int height = display.getHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.BLACK);
view.setImageBitmap(bitmap);
re_factor = (re_max - re_min);
im_factor = (im_max - im_min);
a = -0.125;
b = 0.75;
// recupera le informazioni sulle dimensioni dello schermo
for (int i=0;i<width;i++)
{
for (int j=0;j<height;j++)
{
double x = im_min + i * im_factor / width;
double y = re_min + j * re_factor / height;
test = 0;
for (int k=0;k<iterazioni;k++)
{
xnew = x * x - y * y + a;
ynew = 2 * x * y + b;
if (((xnew*xnew)+(ynew*ynew))>4)
{
test = k;
k = iterazioni;
}
x = xnew;
y = ynew;
}
if (test%2 == 1)
{
//punto bianco
canvas.drawPoint(i, j, paint);
}
}
}
}
}
In pratica esiste una corrispondenza tra le coordinate nel piano complesso dell'insieme di Mandelbrot ed il corrispettivo insieme di Julia
L'esempio sopra riportato e' corrispondente al punto-0.125;0.75 dell'insieme di Mandelbrot
Il codice e' estremamente simile a quello del precedente post
package com.julia;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.Display;
import android.widget.ImageView;
public class JuliaIntActivity extends Activity {
/** Called when the activity is first created. */
private static final double re_min = -2;
private static final double re_max = 2.0;
private static final double im_min = -2.0;
private static final double im_max = 2.0;
private static int iterazioni = 100;
private double ynew;
private double xnew;
private double a;
private double b;
private int test;
private double re_factor;
private double im_factor;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView view = (ImageView) findViewById(R.id.imageView1);
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth(); //240
int height = display.getHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.BLACK);
view.setImageBitmap(bitmap);
re_factor = (re_max - re_min);
im_factor = (im_max - im_min);
a = -0.125;
b = 0.75;
// recupera le informazioni sulle dimensioni dello schermo
for (int i=0;i<width;i++)
{
for (int j=0;j<height;j++)
{
double x = im_min + i * im_factor / width;
double y = re_min + j * re_factor / height;
test = 0;
for (int k=0;k<iterazioni;k++)
{
xnew = x * x - y * y + a;
ynew = 2 * x * y + b;
if (((xnew*xnew)+(ynew*ynew))>4)
{
test = k;
k = iterazioni;
}
x = xnew;
y = ynew;
}
if (test%2 == 1)
{
//punto bianco
canvas.drawPoint(i, j, paint);
}
}
}
}
}
mercoledì 11 aprile 2012
Semplice Mandelbrot
un esempio di uso della grafica su Android per generare l'insieme di Mandelbrot
Per la cronaca sul mio telefono vengono impiegati circa 12,5 secondi per generare l'immagine con i parametri impostati nel programma sottostante (255 iterazioni per ciclo full screen)
----------------------------------------------------------------------------------------
package com.mandelbrot;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.os.Bundle;
import android.view.Display;
import android.view.View;
import android.widget.ImageView;
public class MandelbrotIntActivity extends Activity {
/** Called when the activity is first created. */
private static final double re_min = -2.5;
private static final double re_max = 1.0;
private static final double im_min = -1.0;
private static final double im_max = 1.0;
private static int iterazioni = 255;
private double y;
private double x;
private double ynew;
private double xnew;
private double a;
private double b;
private int test;
private double re_factor;
private double im_factor;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView view = (ImageView) findViewById(R.id.imageView1);
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth(); //240
int height = display.getHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.BLACK);
view.setImageBitmap(bitmap);
re_factor = (re_max - re_min);
im_factor = (im_max - im_min);
// recupera le informazioni sulle dimensioni dello schermo
for (int i=0;i<width;i++)
{
for (int j=0;j<height;j++)
{
double b = im_min + i * im_factor / width;
double a = re_min + j * re_factor / height;
x = 0.0;
y = 0.0;
test = 0;
for (int k=0;k<iterazioni;k++)
{
xnew = x * x - y * y + a;
ynew = 2 * x * y + b;
if (((xnew*xnew)+(ynew*ynew))>4)
{
test = k;
k = iterazioni;
}
x = xnew;
y = ynew;
}
if (test%2 == 1)
{
//punto bianco
canvas.drawPoint(i, j, paint);
}
}
}
}
}
----------------------------------------------------------------------------------------
Sempre giusto per la cronaca nel 1988 facevo piu' o meno la stessa cosa con la stessa risoluzione grafica ma con un Commodore 64 (lascio perdere i tempi di calcolo che erano della grandezza delle ore e non certo dei secondi)
Per la cronaca sul mio telefono vengono impiegati circa 12,5 secondi per generare l'immagine con i parametri impostati nel programma sottostante (255 iterazioni per ciclo full screen)
----------------------------------------------------------------------------------------
package com.mandelbrot;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.os.Bundle;
import android.view.Display;
import android.view.View;
import android.widget.ImageView;
public class MandelbrotIntActivity extends Activity {
/** Called when the activity is first created. */
private static final double re_min = -2.5;
private static final double re_max = 1.0;
private static final double im_min = -1.0;
private static final double im_max = 1.0;
private static int iterazioni = 255;
private double y;
private double x;
private double ynew;
private double xnew;
private double a;
private double b;
private int test;
private double re_factor;
private double im_factor;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView view = (ImageView) findViewById(R.id.imageView1);
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth(); //240
int height = display.getHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
Paint paint = new Paint();
paint.setColor(Color.WHITE);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.BLACK);
view.setImageBitmap(bitmap);
re_factor = (re_max - re_min);
im_factor = (im_max - im_min);
// recupera le informazioni sulle dimensioni dello schermo
for (int i=0;i<width;i++)
{
for (int j=0;j<height;j++)
{
double b = im_min + i * im_factor / width;
double a = re_min + j * re_factor / height;
x = 0.0;
y = 0.0;
test = 0;
for (int k=0;k<iterazioni;k++)
{
xnew = x * x - y * y + a;
ynew = 2 * x * y + b;
if (((xnew*xnew)+(ynew*ynew))>4)
{
test = k;
k = iterazioni;
}
x = xnew;
y = ynew;
}
if (test%2 == 1)
{
//punto bianco
canvas.drawPoint(i, j, paint);
}
}
}
}
}
----------------------------------------------------------------------------------------
Sempre giusto per la cronaca nel 1988 facevo piu' o meno la stessa cosa con la stessa risoluzione grafica ma con un Commodore 64 (lascio perdere i tempi di calcolo che erano della grandezza delle ore e non certo dei secondi)
Sistema di riferimento per la grafica
Il sistema di riferimento delle coordinate per la grafica e' con l'origine 0,0 in alto a sinistra, con l'asse X orizzontale e l'asse Y verticale (per quanto possa avere senso dire orizzontale e verticale in qualcosa che puoi rigirare come vuoi...) comunque l'immagine spiega meglio di mille parole
Semplice grafica in Android
seguendo l'esempio trovato qui si puo' scrivere una mappa di pixel a schermo.
Prima di copiare il codice nel Layout deve essere trascintata una ImageView
Il risultato e' un punto rosso a coordinate 10,10 su sfondo nero
----------------------------------------------------------------------------------
ImageView view = (ImageView) findViewById(R.id.imageView1);
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
Paint paint = new Paint();
paint.setColor(Color.RED);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.BLACK);
canvas.drawPoint(10, 10, paint);
view.setImageBitmap(bitmap);
Prima di copiare il codice nel Layout deve essere trascintata una ImageView
Il risultato e' un punto rosso a coordinate 10,10 su sfondo nero
----------------------------------------------------------------------------------
ImageView view = (ImageView) findViewById(R.id.imageView1);
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
Bitmap bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
Paint paint = new Paint();
paint.setColor(Color.RED);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.BLACK);
canvas.drawPoint(10, 10, paint);
view.setImageBitmap(bitmap);
giovedì 5 aprile 2012
Problemi con aggiornamento ADT da 16 a 17
Giusto ieri ho effettuato l'aggiornamento da ADT 16 a 17 a causa del concomitante aggiornamento dell'SDK di Android. Il problema e' che improvvisamente alcuni programmi a cui stavo lavorando hanno deciso di non compilarsi piu' con un imperscrutabile errore
fortunatamente sono capitato qui dove viene spiegato che
error Binary XML file line #7. Error inflating class org.osmdroid.views.MapView
fortunatamente sono capitato qui dove viene spiegato che
- i file jar delle librerie esterne DEVONO risiedere nella directory libs
- non e' piu' necessario aggiungere alla Build Path le librerie esterne (le Android Depedencies vengono aggiornate da sole)
Semplice gestione touch
Per avere una semplice gestione (non multitouch o gesture) della pressione sullo schermo si puo' aggiungere all'Activity il metodo OnTouchEvent
public boolean onTouchEvent(MotionEvent event)
{ int x = (int)event.getX();
int y = (int)event.getY();
Log.d("s",Integer.toString(x));
Log.d("s",Integer.toString(y));
}
public boolean onTouchEvent(MotionEvent event)
{ int x = (int)event.getX();
int y = (int)event.getY();
Log.d("s",Integer.toString(x));
Log.d("s",Integer.toString(y));
}
martedì 3 aprile 2012
Vestizione OpenStreetMap
Nel tentativo di trovare la migliore cartografia gratuita per la mia applicazione Roadbook ha fatto qualche prova con MOBAC. Alla versione 1.9.6 sono disponibili tre vestizioni di Openstreetmap (l'unica cartografia gratuita) tra cui e' comparsa 4umaps.eu che riporta le isoipse...l'ideale per un programma di navigazione nel bosco
4umaps.eu |
Mapquest |
Mapnik |
lunedì 2 aprile 2012
Connettersi a MySql da Android
Android ha varie possibilita' di salvare dati persistenti ma non c'e' una via semplice per connettersi a database esterni in particolare MySql
Usando JDBC ho avuto diversi problemi (il sorgente si compila bene ma non riesce a connettersi) per cui un sistema alternativo e' quello di passare per un intermediario dato da uno script in PHP
per prima cosa si deve impostare il permesso
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
il server e' 192.168.0.1 e lo script si trova in http://192.168.0.1/zenith/insert.php
vengono passate due variabili (piatto e tavolo) popolate
-------------------------------------------------------------------------------------------
InputStream is;
String piatto = spin.getSelectedItem().toString();
//String tavolo = tav_txt.getText().toString();
String tavolo = spin_tav.getSelectedItem().toString();
ArrayList <NameValuePair> nameValuePairs = new ArrayList <NameValuePair>();
nameValuePairs.add(new BasicNameValuePair("piatto",piatto));
nameValuePairs.add(new BasicNameValuePair("tavolo",tavolo));
try{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://192.168.0.1/zenith/insert.php");
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
is = entity.getContent();
Log.d("Zenith","Dato salvato");
Toast.makeText( getApplicationContext(),R.string.riuscito,Toast.LENGTH_SHORT ).show();
// suona per conferma
Uri notification = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
Ringtone r = RingtoneManager.getRingtone(getApplicationContext(), notification);
r.play();
}
catch(Exception e)
{
Toast.makeText( getApplicationContext(),R.string.non_riuscito,Toast.LENGTH_SHORT ).show();
Log.e("Zenith", "Error in http connection"+e.toString());
}
-------------------------------------------------------------------------------------------
la struttura del database Mysql e' data dal codice
-------------------------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS `comande` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`tavolo` int(11) NOT NULL,
`piatto` text NOT NULL,
`data` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=22 ;
-------------------------------------------------------------------------------------------
lo script Php insert.php invece risulta essere
-------------------------------------------------------------------------------------------
<?
$hostname_localhost ="localhost";
$database_localhost ="zenith";
$username_localhost ="xxxxxxxxx";
$password_localhost ="xxxxxxxxxxx";
var_dump($_REQUEST);
$localhost = mysql_connect($hostname_localhost,$username_localhost,$password_localhost)
or
trigger_error(mysql_error(),E_USER_ERROR);
mysql_select_db("zenith");
$sql_string = "INSERT INTO comande (id,tavolo,piatto,data) VALUES (NULL,'".$_REQUEST['tavolo']."','".$_REQUEST['piatto']."',CURRENT_TIMESTAMP)";
$sql=mysql_query($sql_string);
mysql_close();
?>
Stili in Android
Per definire gli stili di un elemento grafico in Android si puo' utilizzare il file styles.xml
Questo file non viene creato insieme al progetto Eclipse e deve essere generato inserendo nella directory /res/values un nuovo file Android XML Values File e nominandolo come style.xml
All'interno, un po' come fosse un Css in html, si crea uno stile con un determinato nome (in questo caso latlon)
-----------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="latlon">
<item name="android:textColor">#000000</item>
<item name="android:textStyle">bold</item>
<item name="android:textSize">16sp</item>
</style>
</resources>
---------------------------------------------------------------------------------------
per fare in modo che un elemento grafico usi lo style si puo' inserire nella definizione dell'oggetto. Per esempio
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="@string/latlon"
android:textAppearance="@style/latlon"
/>
Questo file non viene creato insieme al progetto Eclipse e deve essere generato inserendo nella directory /res/values un nuovo file Android XML Values File e nominandolo come style.xml
All'interno, un po' come fosse un Css in html, si crea uno stile con un determinato nome (in questo caso latlon)
-----------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="latlon">
<item name="android:textColor">#000000</item>
<item name="android:textStyle">bold</item>
<item name="android:textSize">16sp</item>
</style>
</resources>
---------------------------------------------------------------------------------------
per fare in modo che un elemento grafico usi lo style si puo' inserire nella definizione dell'oggetto. Per esempio
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="@string/latlon"
android:textAppearance="@style/latlon"
/>
RelativeLayout vs. LinearLayout
Normalmente i progetti di Android/Eclipse partono tutti con il LinearLayout, il modo piu' semplice (e meno potente) di disporre gli elementi grafici sullo schermo.
Impostando invece il RelativeLayout si ha il vantaggio di poter bloccare gli elementi grafici ad aree particolari dello schermo usando direttamente la composizione grafica del layout
Leggere file GPX in Android
Un esempio di come usare la classe java scaricabile qui per leggere i file gpx su Android
package com.gpx;
import android.app.Activity;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
class GpxReader
{
private static final SimpleDateFormat gpxDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
public static List<Location> getPoints(File gpxFile)
{
List<Location> points = null;
try
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
FileInputStream fis = new FileInputStream(gpxFile);
Document dom = builder.parse(fis);
Element root = dom.getDocumentElement();
NodeList items = root.getElementsByTagName("trkpt");
points = new ArrayList<Location>();
for(int j = 0; j < items.getLength(); j++)
{
Node item = items.item(j);
NamedNodeMap attrs = item.getAttributes();
NodeList props = item.getChildNodes();
Location pt = new Location("test");
pt.setLatitude(Double.parseDouble(attrs.getNamedItem("lat").getTextContent()));
pt.setLongitude(Double.parseDouble(attrs.getNamedItem("lon").getTextContent()));
for(int k = 0; k<props.getLength(); k++)
{
Node item2 = props.item(k);
String name = item2.getNodeName();
if(!name.equalsIgnoreCase("time")) continue;
try
{
pt.setTime((getDateFormatter().parse(item2.getFirstChild().getNodeValue())).getTime());
}
catch(ParseException ex)
{
ex.printStackTrace();
}
}
for(int y = 0; y<props.getLength(); y++)
{
Node item3 = props.item(y);
String name = item3.getNodeName();
if(!name.equalsIgnoreCase("ele")) continue;
pt.setAltitude(Double.parseDouble(item3.getFirstChild().getNodeValue()));
}
points.add(pt);
}
fis.close();
}
catch(FileNotFoundException e)
{
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch(ParserConfigurationException ex)
{
}
catch (SAXException ex) {
}
return points;
}
public static SimpleDateFormat getDateFormatter()
{
return (SimpleDateFormat)gpxDate.clone();
}
}
public class GpxActivity extends Activity {
private List<Location> t;
private double lat;
private double lon;
private double alt;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
File gpx = new File("/mnt/sdcard/malandrino.gpx");
t = GpxReader.getPoints(gpx);
Iterator<Location> it = t.iterator();
while (it.hasNext())
{
Location value = it.next();
lat = value.getLatitude();
lon = value.getLongitude();
alt = value.getAltitude();
Log.d("gpx",Double.toString(lat));
Log.d("gpx",Double.toString(lon));
Log.d("gpx",Double.toString(alt));
}
}
}
Visibilita' di un oggetto
Per settare se un oggetto e' visibile o meno a schermo si deve impostare la seguente proprieta'
per esempio se si vuole nascondere una immagine con nome imgview
imgview.setVisibility(View.INVISIBLE);
ed il suo ovvio opposto
per esempio se si vuole nascondere una immagine con nome imgview
imgview.setVisibility(View.INVISIBLE);
ed il suo ovvio opposto
Iscriviti a:
Post (Atom)
Debugger integrato ESP32S3
Aggiornamento In realta' il Jtag USB funziona anche sui moduli cinesi Il problema risiede nell'ID USB della porta Jtag. Nel modulo...
-
In questo post viene indicato come creare uno scatterplot dinamico basato da dati ripresi da un file csv (nel dettaglio il file csv e' c...
-
La scheda ESP32-2432S028R monta un Esp Dev Module con uno schermo TFT a driver ILI9341 di 320x240 pixels 16 bit colore.Il sito di riferiment...
-
Questo post e' a seguito di quanto gia' visto nella precedente prova Lo scopo e' sempre il solito: creare un sistema che permet...