giovedì 29 novembre 2012

Utilizzo SQLite con C

Per terminare la carrellata dell'utilizzo di SQLite (gia' visto qui e qui) si vede l'utilizzo con C sia su Linux che su Windows (mediante Dev-C++ con il DevPack SQLite). Verrano ripetute le operazioni (piu' o meno) gia' eseguite con gli altri linguaggi

Nel progetto Dev-C++ si devono impostare l'utlizzo della libreria SQLite come indicato nella figura sottostante


per utilizzare il programma mediante Dev-C++ e' necessario che la libreria libsqlite3-0.dll sia accessibile (nella stessa directory dove viene ubicato l'eseguibile oppure in una directory di sistema di Windows...attenzione che dal sito di SQLite si scarica una dll nominata sqlite3.dll che non funziona all'interno di Dev-C++..si deve impiegare quella inserita nel DevPack)

Altrimenti dentro Linux il file puo' essere compilato con la seguente riga di comando
gcc -o sqlite_test sqlite_test.c  -Wall -O3 -lsqlite3

di seguito viene riportato il codice sorgente che e' sostanzialmente autoesplicativo in quanto effettua delle exec di comandi SQL
------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>


int main(int argc, char **argv){
sqlite3 *db;
char *zErrMsg = 0;
int rc;

rc = sqlite3_open("utenti.db", &db);
if (rc == SQLITE_OK)
{
rc = sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS users  (Id INTEGER PRIMARY KEY,username TEXT, password TEXT, email TEXT)", NULL, 0, &zErrMsg);
if (rc != SQLITE_OK) fprintf(stderr, "SQL error: %s\n", zErrMsg);

rc = sqlite3_exec(db, "INSERT INTO users VALUES (NULL,\"luca\",\"password\",\"lucainnoc@gmail.com\")", NULL, 0, &zErrMsg);
if (rc != SQLITE_OK) fprintf(stderr, "SQL error: %s\n", zErrMsg);
rc = sqlite3_exec(db, "INSERT INTO users VALUES (NULL,\"chiara\",\"password\",\"chiara@gmail.com\")", NULL, 0, &zErrMsg);
if (rc != SQLITE_OK) fprintf(stderr, "SQL error: %s\n", zErrMsg);

sqlite3_stmt *stmt;
rc = sqlite3_prepare_v2(db, "SELECT * FROM users", -1, &stmt, 0);
if (rc == SQLITE_OK) {
int nCols = sqlite3_column_count(stmt);
if (nCols)
{
for (int nCol = 0; nCol < nCols; nCol++)
printf("%s\t", sqlite3_column_name(stmt, nCol));
printf("\n");
while ((rc = sqlite3_step(stmt)) == SQLITE_ROW)
for (int nCol = 0; nCol < nCols; nCol++)
printf("%s\t", sqlite3_column_text(stmt, nCol));
printf("\n");
}
sqlite3_finalize(stmt);
}

rc = sqlite3_exec(db, "DELETE FROM users", NULL, 0, &zErrMsg);
if (rc != SQLITE_OK) fprintf(stderr, "SQL error: %s\n", zErrMsg);

sqlite3_close(db);
} else {
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
return 1;
}
return 0;

}

mercoledì 28 novembre 2012

Utilizzo di SQLite con Android

Riprendendo il precedente post qui verra' mostrato come usare SQLite all'interno di Android partendo da questo esempio

Per prima cosa si deve scrivere una classe di helper in cui sono identificate la struttura del Db e le operazioni da eseguire...per semplicita' viene utilizzata la struttura gia' vista nello script Python

-----------------------------------------------------------------------

package com.example.sqlite;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

public class database {
SQLiteDatabase mDb;
     DbHelper mDbHelper;
     Context mContext;
     private static final String DB_NAME="users";//nome del db
     private static final int DB_VERSION=1; //numero del db
     
     public database(Context ctx){
             mContext=ctx;
             mDbHelper=new DbHelper(ctx, DB_NAME, null, DB_VERSION);        
     }
     
     public void open(){  
             mDb=mDbHelper.getWritableDatabase();
             
     }
     
     public void close(){ 
             mDb.close();
     }
     
     public void insertUtente(String name,String password, String email){ // genera l'INSERT
             ContentValues cv=new ContentValues();
             cv.put(UsersMetaData.USERNAME_KEY, name);
             cv.put(UsersMetaData.PASSWORD_KEY, password);
             cv.put(UsersMetaData.EMAIL_KEY,email);
             mDb.insert(UsersMetaData.USERS_TABLE, null, cv);
     }
     
     public void deleteUtente(String id) {
         mDb.delete(UsersMetaData.USERS_TABLE, UsersMetaData.ID + "=" + id, null);
     }

    
     public Cursor fetchUtenti(){ //genera la SELECT
             return mDb.query(UsersMetaData.USERS_TABLE, null,null,null,null,null,null);               
     }

     public class UsersMetaData {  // variabili
             static final String USERS_TABLE = "users";
             static final String ID = "_id";
             static final String USERNAME_KEY = "username";
             static final String PASSWORD_KEY = "password";
             static final String EMAIL_KEY = "email";
     }

     private static final String USERS_TABLE_CREATE = "CREATE TABLE IF NOT EXISTS "  //CREATE TABLE
                     + UsersMetaData.USERS_TABLE + " (" 
                     + UsersMetaData.ID+ " integer primary key autoincrement, "
                     + UsersMetaData.USERNAME_KEY + " text not null, "
                     + UsersMetaData.PASSWORD_KEY + " text not null, "
                     + UsersMetaData.EMAIL_KEY + " text not null);";

     private class DbHelper extends SQLiteOpenHelper { //helper

             public DbHelper(Context context, String name, CursorFactory factory,int version) {
                     super(context, name, factory, version);
             }

             public void onCreate(SQLiteDatabase _db) { //solo quando il db viene creato, creiamo la tabella
                     _db.execSQL(USERS_TABLE_CREATE);
             }

             public void onUpgrade(SQLiteDatabase _db, int oldVersion, int newVersion) {

             }

     }
}
---------------------------------------------------------

a questo punto si puo' procedere utilizzando la classe helper 
il codice e' sostanzialmente autoesplicativo
----------------------------------------------------------
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
database utenti =new database(getApplicationContext());
utenti.open();
utenti.insertUtente("luca", "password", "lucainnoc@gmail.com");
utenti.insertUtente("chiara", "password", "chiara@gmail.com");
        
Cursor c=utenti.fetchUtenti(); // query
        
int usernameCol=c.getColumnIndex(UsersMetaData.USERNAME_KEY);  //indici delle colonne
int passwordCol=c.getColumnIndex(UsersMetaData.PASSWORD_KEY);
int mailCol=c.getColumnIndex(UsersMetaData.EMAIL_KEY);
        
       if(c.moveToFirst()){  
            do {
                Log.d("select",c.getString(usernameCol)+" "+c.getString(passwordCol)+" "+c.getString(mailCol));                    
                    } while (c.moveToNext());//iteriamo al prossimo elemento
        }
    
utenti.deleteUtente("1");
        
if(c.moveToFirst()){  
        do {
            Log.d("select",c.getString(usernameCol)+" "+c.getString(passwordCol)+" "+c.getString(mailCol));                    
             } while (c.moveToNext());//iteriamo al prossimo elemento
    }
utenti.close();
        

Utilizzo di base di Sqlite con Python

Sqlite e' un database basato su un unico file che ha bindings in numerosi linguaggi; l'aspetto piu' interessanto dell'impiego con Python e' quello di essere inserito all'interno del linguaggio (per lo meno dalla versione 2.5 e superiori) e per questo motivo non e' necessario utilizzare librerie esterne per il suo impiego

Di seguito un esempio delle operazioni base effettuate impiegando Python...attenzione al commit finale (Sqlite ammette le transazioni atomiche)
-----------------------------------------------------------------

from sqlite3 import dbapi2 as sqlite
con = sqlite.connect('utenti.db')
cur = con.cursor()

#crea una tabella con un indice ad autoincremento
cur.execute('CREATE TABLE users (Id INTEGER PRIMARY KEY,username TEXT, password TEXT, email TEXT)')

#effettua alcuni inserimenti
# NULL serve per l'indice ad autoincremento
cur.execute('INSERT INTO users VALUES (NULL,"luca","password","lucainnoc@gmail.com")')
cur.execute('INSERT INTO users VALUES (NULL,"chiara","password","chiara@gmail.com")')
print "-----------------------"

#estrae tutte le righe
cur.execute('SELECT * FROM users')
for row in cur:
    print row
    print row[0]
    print row[1]
    print row[2]
    print "-----------------------"

#estrae solo una riga
nome = "luca"
cur.execute("SELECT * FROM users WHERE username=:username",  {"username": nome})
for row in cur:
    print row
print "-----------------------"

#cancella una riga
cur.execute("DELETE FROM users WHERE username=:username",  {"username": nome})

cur.execute('SELECT * FROM users')
for row in cur:
    print row
print "-----------------------"

#cancella la tabella
cur.execute('DROP TABLE users')
con.commit()
cur.close()

lunedì 26 novembre 2012

Ottenere l'Ip del telefono Android

Questa soluzione e' stata ripresa da questo post per poter ottenere l'indirizzo Ip del proprio terminale Android
Si devono per prima cosa impostare i permessi

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />


--------------------------------------------------------

package com.example.ip;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

private TextView ip_t;

public String getLocalIpAddress()
 {
         try {
             for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
                 NetworkInterface intf = en.nextElement();
                 for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                     InetAddress inetAddress = enumIpAddr.nextElement();
                     if (!inetAddress.isLoopbackAddress()) {
                         return inetAddress.getHostAddress().toString();
                     }
                 }
             }
         } catch (Exception ex) {
             Log.e("IP Address", ex.toString());
         }
         return null;
     }

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


        ip_t = (TextView) findViewById(R.id.ip);
        String ip = getLocalIpAddress();
        ip_t.setText(ip);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}

}
--------------------------------------------------------
Se si esegue il programma sull'emulatore Android l'indirizzo IP mostrato e' 10.0.2.15 che tradisce chiaramente il fatto che l'emulatore stesso discenda direttamente da QEmu


Codici a barre in Android

Implementare un lettore di codici a barre all'interno della propria applicazione e' piuttosto semplice ma usa un approccio piuttosto differente alla norma....al posto di inserire una libreria all'interno della propria applicazione si richiama l'app esterna BarCodeScanner appartenente al progetto ZXing




Tramite una chiamata Intent il controllo viene mandato al BarCodeScanner che risponde il risultato all'interno delle variabili contents e format.
----------------------------------------------------------------------------
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_racecontrol);
Intent intent = new Intent("com.google.zxing.client.android.SCAN");
intent.putExtra("SCAN_MODE", "QR_CODE_MODE");
startActivityForResult(intent, 0);
}
});
    }
    
  public void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == 0) {
if (resultCode == RESULT_OK) {
String contents = intent.getStringExtra("SCAN_RESULT");
String format = intent.getStringExtra("SCAN_RESULT_FORMAT");

} else if (resultCode == RESULT_CANCELED) {
// Handle cancel
}
}

domenica 25 novembre 2012

Inviare SMS in Android


Inviare SMS via programma in Android e' particolarmente semplice (2 linee) indicando solo il numero di cellulare ed il testo



------------------------------------------------------------------
SmsManager sms = SmsManager.getDefault();
sms.sendTextMessage(nr_cellulare, null, testo_sms, null, null);

venerdì 23 novembre 2012

Comunicazione UDP tra PC e Android

In questo post viene descritta la possibilita' di stabilire una connessione UDP tra il telefono Android in funzione Server ed un PC mediante script Python

per il lato server (Android) si deve creare un programma che inserisca tra i permessi di AndroidManifest.xml la seguente riga

<uses-permission android:name="android.permission.INTERNET" />

sulla funzione OnCreate si puo' creare il server UDP come riportato nell'esempio seguente (porta di connessione 12345 e lunghezza massima del pacchetto 1024 bytes
------------------------------------------------------------

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
   String lText;
   byte[] lMsg = new byte[1024];
   DatagramPacket dp = new DatagramPacket(lMsg, lMsg.length);
   DatagramSocket ds = null;
   while (true)
   {
   try {
       ds = new DatagramSocket(12345); //porta del server UDP 12345

//riceve il pacchetto


       ds.receive(dp);
       lText = new String(lMsg, 0, dp.getLength());
       Log.i("Richiesta", lText);
        //manda la risposta

        byte[] b = "Risposta".getBytes();
        DatagramPacket sendPacket = new DatagramPacket(b, b.length, dp.getAddress(), dp.getPort());
        ds.send(sendPacket);      
        
   } catch (SocketException e) {
       e.printStackTrace();
   } catch (IOException e) {
       e.printStackTrace();
   } finally {
       if (ds != null) {
           ds.close();
       }
   }
   }
}

------------------------------------------------------------

creato il server si passa al lato client in Python da mettere sul PC Desktop
il programma manda un pacchetto al server ed il server lo mette nel file di log
--------------------------------------------------
from socket import socket, AF_INET, SOCK_DGRAM
data = 'Richiesta'
port = 12345
hostname = 'localhost'
udp = socket(AF_INET,SOCK_DGRAM)
#manda la richiesta
udp.sendto(data, (hostname, port))
#aspetta e stampa la risposta

data, server = udp.recvfrom(1024)
print data
--------------------------------------------------

per poter effettuare le prove con l'emulatore di Android ci si collega via telnet alla shell dell'emulatore(telnet localhost 5554) e si digita 
redir add udp:12345:12345

che reindirizza le chiamate alla porta localhost:12345 del Desktop alla porta 12345 dell'emulatore dove gira il server

Leggere SMS in Android



Per leggere  gli SMS contenuti nel telefono e' sufficiente inserire la regola in AndroidManifest.xml


<uses-permission android:name="android.permission.READ_SMS"/>

e poi usare il codice seguente 

-----------------------------------------------------------------------

Uri uriSms = Uri.parse("content://sms/inbox");
Cursor cursor = getContentResolver().query(uriSms, new String[]{"_id", "address", "date", "body"},null,null,null);
cursor.moveToFirst();
while  (cursor.moveToNext())
{
        String id = cursor.getString(0);
         String address = cursor.getString(1);
         String body = cursor.getString(3);
         Log.d("testo",id + " "+address + " "+body);
}

giovedì 22 novembre 2012

Convertire stringhe in datetime in Python

per lavoro ho avuto la necessita' di leggere in input un file testo con una serie di stringhe rappresentanti delle letture effettuate nel tempo e dover capire quale fosse la differenza di tempo tra le acquisizioni

Il metodo piu' semplice e' quindi convertire le stringhe in un formate datetime e poi effettuare le operazioni

In Python la cosa si risolve cosi

---------------------------------------------
from datetime import datetime

data1 = datetime.strptime('Jun 27 2012  7:14PM', '%b %d %Y %I:%M%p')

data2 = datetime.strptime('Jun 27 2012  7:16PM', '%b %d %Y %I:%M%p')
diff = data2 - data1
print diff
print diff.seconds 
---------------------------------------------
che riporta come risulta 0:02:00 ovvero l'attesa differenza di 2 minuti e la differenza espressa in secondi (120)

mercoledì 14 novembre 2012

Snail Mail da Google

E' troppo curioso ricevere una lettera di carta da Google per non pubblicarlo


fra parentesi e' un pubblicita' per AdWords




martedì 13 novembre 2012

Slax

Sempre alla ricerca di creare un sistema Linux da portarmi a giro come Live Cd mi sono imbattuto in SLAX una derivata da Slackware


Boot di Slax

la caratteristica piu' interessante e' quella di non fornire una ISO prestabilita ma di poter creare la propria Linux Box con la funzione Slax Build

In estrema sintesi si puo' partire da un sistema di base ed aggiungere i vari moduli di interesse (io mi sono creato un sistema per la programmazione) fino ad scaricare un file .iso con tutto montato
Il sistema non e' perfetto e le dipendenze devono essere in qualche caso corrette a mano ma in fin dei conti e' poca cosa

Il modulo CodeBlocks aggiunto alla ISO
Interessante e' anche la possibilita' di salvare la configurazione dei moduli su un file per poterlo correggere o riprendere la selezione in un secondo tempo

Creare una Live-Cd partendo da una installazione funzionante

Una delle cose che ho sempre desiderato e' quella di potermi portare dietro i programmi e le impostazioni che mi servono anche se non ho dietro il portatile

Ho cosi' provato un po' di soluzioni per poi decidere il sistema riportato da Remastersys

Non volendo sacrificare il portatile mi sono creato una macchina virtuale minimale partendo da una installazione standard di Ubuntu Server 12.04 (Remastersys non gestisce Debian Testing e quindi ho escluso di provare su Debian) per poi aggiungere openbox

apt-get install openbox obconf obmenu openbox-themes startx xterm

in questo modo si ha un ambiente grafico minimale
E' giunto il momento di creare una iso del nuovo sistema prima aggiungendo ad apt la chiave del repository di Remastersys

wget -O - http://www.remastersys.com/ubuntu/remastersys.gpg.key | apt-key add -

dopo si modifica il file /etc/apt/sources.list aggiungendo la riga
deb http://www.remastersys.com/ubuntu precise main

seguito dall'aggiornamento di apt
apt-get update
e
apt-get install remastersys

e' giunto il momento di creare il file iso includendo anche i file personali (e non solo quelli di sistema)
remastersys backup nome_file.iso

il file viene generato nella directory /home/remastersys

dopo un (bel) po' viene creato il file iso che puo' essere masterizzato o messo su chiavetta USB e distribuito
Al riavvio si presenta questo menu


e tutto funziona magnificamente

lunedì 12 novembre 2012

Wget dietro proxy server

Per utilizzare il comando wget in una rete schermata da un proxy server non e' sufficiente impostare la variabile bash http_proxy con il comando

export http_proxy=http://myproxy:8080

perche' il programma di fatto non legge questa impostazione

la soluzione piu' semplice e' creare un file .wgetrc inserendo la stringa
http_proxy=http://myproxy:8080

sabato 10 novembre 2012

Installa Ruby on Rails su Debian per Passbook Server



per questa installazione si e' partiti da una Debian Testing netinstall perche' la versione Stable ha come pacchetti Ruby 1.8 mentre a me serve la versione piu' recente di Ruby (la 1.9) accoppiata al piu' recente Rails (3)

Esiste un Live Cd di TurnKey che propone un ambiente Ruby On Rails gia' configurato ma essendo un derivato da Debian Stable anche in questo caso si trovano pacchetti datati

Lo scopo finale e' quello di settare un ambiente di sviluppo/test per i Passbook di Apple

una volta installato il sistema in modalita' server (quindi niente ambiente desktop) si procede con
apt-get update
apt-get upgrade
apt-get install build-essential apache2 libapache2-mod-passenger
apt-get install rdoc ruby1.9.1-full
apt-get install ruby1.9.1-dev libopenssl-ruby rubygems1.8
gem install fastthread
apt-get install ruby-rails-3.2
gem install coffee-rails uglifier
con queste impostazioni si ha un ambiente di svliluppo generico che permette di usare gli esempi riportati a questo link

a questo punto si inizia a settare le dipendenze per il Passbook Server
gem install sinatra sequel sqlite3 rubyzip rack json terminal-table

si scompattano gli esempi Passbook che si trovano su Apple Developer e ci si posiziona nella directory ServerReference/pass_server e si lancia
gem install lib/sign_pass-1.0.0.gem
chmod 755 lib/pass_server_ctl 
lib/pass_server_ctl -s







martedì 6 novembre 2012

Menuet Os

Un progetto interessante ma sostanzialmente inutile....un sistema operativo scritto interamente in Assembler con Fasm

Menuet OS si scarica da qui e l'immagine e' grande quanto un disco da 1.44 Mb
Per utilizzarla con QEmu si usa la seguente stringa

qemu -localtime -m 768 -fda M32-085B.IMG -L . -net user -net nic

la prima schermata e' per settare alcuni parametri della scheda video


e dopo si ha il desktop con alcune utility (a dire il vero molto scarne)


lunedì 5 novembre 2012

Primi passi in Assembler su Linux


piu' che altro per divertimento ho provato a riscrivere qualcosa in assembler..era dai tempi del DOS e di Int 21h che non usavo piu' l'assembler
E' curioso ritrovare che anche Linux come Dos usa un interrupt (80h) per la gestione del sistema ed e' anche curioso di come si possano usare le chiamate alle funzioni C (in questo caso printf) dall'Assembler (di solito e' il linguaggio di piu' alto livello che sfrutta quello di livello piu' basso)

Tutti gli esempi sono compilati con nasm

Il primo esempio stampa una scritta a video usando l'Int 80h
Per la compilazione si devono dare i seguenti comandi
nasm -f elf32 scrivi.asm
ld -o scrivi scrivi.o

scrivi.asm
-------------------------------------------------------
global _start

section .text
_start:
    mov eax,4
    mov ebx,1
    mov ecx,messaggio
    mov  edx,lunghezza
    int 80h

    mov eax,1
    mov ebx,0
    int 80h

section .data
    messaggio: db 'Hello ',0x0a
    lunghezza: equ $-messaggio


-------------------------------------------------------
come output si ha
Hello

Per il secondo esempio si usa invece la chiamata esterna printf per stampare il valore di una variabile

In questo caso la catena di compilazione e' differente per venire incontro alla chiamata esterna che e' risolta da gcc
nasm -f elf32 -l scrivi2.lst scrivi2.asm
gcc -o scrivi2 scrivi2.o

scrivi2.asm
-------------------------------------------------------
 extern printf

section .text

    global main
main:
    push ebp
    mov ebp,esp


    push dword [a]
    push dword formato
    call printf

    add esp,12

    mov esp,ebp
    pop ebp

    mov eax,0
    ret

section .data
    a: dd 5
    formato: db "a=%d",10,
0

-------------------------------------------------------
come output si ha
a=5

Molto simile al precedente il terzo esempio mostra un ciclo

nasm -f elf32 -l scrivi3.lst scrivi3.asm
gcc -o scrivi3 scrivi3.o

scrivi3.asm
-------------------------------------------------------
 extern printf

section .text

    global main
main:
    push ebp
    mov ebp,esp

    mov ebx,10
gira:
    push ebx
    push dword formato
    call printf
    dec ebx
    jnz gira
  

    mov esp,ebp
    pop ebp

    mov eax,0
    ret

section .data
    formato: db "ciclo=%d",10,0

-------------------------------------------------------

produce come output
ciclo=10
ciclo=9
ciclo=8
ciclo=7
ciclo=6
ciclo=5
ciclo=4
ciclo=3
ciclo=2
ciclo=1





Array a dimensione variabile in Android

Uno degli aspetti piu' divertenti dei linguaggi di programmazionee evoluti e' la possibilita' di gestire degli array a dimensione non predefinita (a partire dalla STL di C++)

In Java ed Android vi sono ben due possibilita' date dal formato Vector ed ArrayList

Nei due esempi gli array vengono popolati con i valori della funzione Seno.
Dal punto di vista operativo le differenze sono veramente minime.
  1. i metodi del Vector sono sincroni mentre gli ArrayList non sono sincroni
  2. i Vector sono thread-safe ma sono piu' lenti nell'aumentare le dimensioni
  3. ad ogni add Vector raddoppia le dimensioni disponibili mentre ArrayList aumenta le dimensioni di meta' della propria dimensione

Vettore
-------------------------------------------------------
v = new Vector<Float>();
for (int t=0;t<360;t++)
        {
            v.add((float) Math.sin(Math.toRadians(t)));
        }
int length = v.size();
Log.d("lenght_t", Integer.toString(length));

-------------------------------------------------------
ArrayList
-------------------------------------------------------
al = new ArrayList<Float>();
for (int s=0;s<360;s++)
        {
            al.add((float) Math.sin(Math.toRadians(s)));
        }
length_s = al.size();
Log.d("length_s", Integer.toString(length_s));
Iterator<Float> it = al.iterator();
    while (it.hasNext()) {
            System.out.println("Data is "+ it.next());
    }

-------------------------------------------------------

domenica 4 novembre 2012

Personalizzare Nautilus

Una delle cose che non mi e' mai piaciuta di Nautilis e' l'interfaccia stile Explorer di Windows con la lista di una sola directory per ogni finestra...considero decisamente piu' funzionale l'interfaccia tipo Norton



In realta' con la 'sola pressione del tasto F3 si riesce ad avere una visione a due finestre affiancate 



mentre con il tasto F9 si fa apparire e scomparire la colonna delle directory predefinite di destra (alla colonna delle directory predefinite si possono aggiungere elementi tramite il drag and drop)



venerdì 2 novembre 2012

Creare grafici con AChartEngine in Android

Un altro metodo per creare grafici con Android e' quello di impiegare la libreria AChartEngine

Il problema con questa libreria e' che sostanzialmente priva di esempi e non e' cosi' immediato usarla
Si possono trovare dei video tipo questo


ma se si prova a seguire l'esempio il programma genera sempre un'eccezione

il trucco e' che in modo preliminare si devono modificare project.properties e Manifest.xml cosi' come evidenziato in giallo

project.properties
------------------------------------------------
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system edit
# "ant.properties", and override values to adapt the script to your
# project structure.
#
# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt

# Project target.
target=android-15
manifestmerger.enabled=true 

------------------------------------------------


Manifest.xml
------------------------------------------------
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.test.graph2"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="org.achartengine.GraphicalActivity" />
    </application>

</manifest>

------------------------------------------------
Dopo di cio' si puo' iniziare a scrivere il codice
Di fatto il grafico vive in una sua finestra per cui va lanciato mediante Intent

MainActivity
------------------------------------------------
package com.test.graph2;


import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends Activity {
    /** Called when the activity is first created. */
   
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
   
    public void lineGraphHandler (View view)
    {
        LineGraph line = new LineGraph();
        Intent lineIntent = line.getIntent(this);
        startActivity(lineIntent);
    }

}

------------------------------------------------
Per il resto il codice per generazione del grafico e' piuttosto autoesplicativa

LineGraph.java
------------------------------------------------
package com.test.graph2;

import org.achartengine.ChartFactory;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.TimeSeries;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;

import android.content.Context;
import android.content.Intent;
import android.graphics.Color;

public class LineGraph {
public Intent getIntent(Context context) {
       
        // Our first data
        int[] x = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // x values!
        int[] y =  { 30, 34, 45, 57, 77, 89, 100, 111 ,123 ,145 }; // y values!
        TimeSeries series = new TimeSeries("Line1");
        for( int i = 0; i < x.length; i++)
        {
            series.add(x[i], y[i]);
        }
       
        // Our second data
        int[] x2 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; // x values!
        int[] y2 =  { 145, 123, 111, 100, 89, 77, 57, 45, 34, 30}; // y values!
        TimeSeries series2 = new TimeSeries("Line2");
        for( int i = 0; i < x2.length; i++)
        {
            series2.add(x2[i], y2[i]);
        }
       
        XYMultipleSeriesDataset dataset = new XYMultipleSeriesDataset();
        dataset.addSeries(series);
        dataset.addSeries(series2);
       
        XYMultipleSeriesRenderer mRenderer = new XYMultipleSeriesRenderer(); // Holds a collection of XYSeriesRenderer and customizes the graph
        XYSeriesRenderer renderer = new XYSeriesRenderer(); // This will be used to customize line 1
        XYSeriesRenderer renderer2 = new XYSeriesRenderer(); // This will be used to customize line 2
        mRenderer.addSeriesRenderer(renderer);
        mRenderer.addSeriesRenderer(renderer2);
       
        // Customization time for line 1!
        renderer.setColor(Color.WHITE);
        renderer.setPointStyle(PointStyle.SQUARE);
        renderer.setFillPoints(true);
        // Customization time for line 2!
        renderer2.setColor(Color.YELLOW);
        renderer2.setPointStyle(PointStyle.DIAMOND);
        renderer2.setFillPoints(true);
       
        Intent intent = ChartFactory.getLineChartIntent(context, dataset, mRenderer, "Line Graph Title");
        return intent;
       
    }
}
 

------------------------------------------------

Plugin Android per Eclipse

Al momento attuale esistono diversi plugin per Android o meglio diversi pacchetti

Scaricando il Google Plugin si ha oltre al necessario per sviluppare Android in Eclipse anche la possibilita' di scaricare l'SDK di Android e GWT ed AppEngine

Invece a questo link si trova il solo pacchetto ADT in cui e' presente il solo plugin Android per Eclipse. L'SDK dovra' essere scaricato a parte