JavascriptProva

lunedì 30 aprile 2018

Esercizi con le variabili php

Bene. Ripartiamo dalle variabili.

Scrivere una variabile con un valore numerico, una con un valore stringa e una booleana e farle apparire sulla pagina.

<?php
$numerico=23;
$stringa="vaffanculo";
$booleana=true;
echo $numerico;
echo $stringa;
echo $booleana;
?>
23vaffanculo1
Bene. Il true viene reso con 1. E scommetto che il false viene reso con 0.
6lt;?php
$numerico=23;
$stringa="vaffanculo";
$booleana=false;
echo $numerico;
echo $stringa;
echo $booleana;
?>
23vaffanculo

C'è qualcosa che non va...

Vediamo di approfondire...

Sembra che la mia sintassi sia corretta...

Vedremo poi nelle istruzioni condizionali.

Le variabili numeriche in realtà si distinguono in integer e float.
<?php
$integer=23;
$float=2.4;
echo $integer;
echo "<br>";
echo $float;
?>
23
2.4

Perfetto.
Dunque finora abbiamo visto le variabili di tipo:
  1. stringa
  2. integer
  3. float
  4. boolean>
Ne esistono altri tipi.

...che sono i più interessanti!
array, ad esempio...

Ma vediamo la funzione var_dump.
Nel tutorial questa funzione è applicata agli arrays, ma adesso la applico alle variabili già viste...

<?php
$integer=23;
$float=2.4;
$stringa="questa è una stringa";
$booleana=false;
var_dump($integer);
echo "<br>";
var_dump($float);
echo "<br>";
var_dump($stringa);
echo "<br>";
var_dump($booleana);
?>
int(23) 
float(2.4) 
string(21) "questa è una stringa" 
bool(false)
Ecco: viene espresso il tipo di variabile e il valore tra parentesi, tranne che per la stringa, per la quale viene messo tra parentesi il numero di caratteri e il valore viene scritto a seguire.

Passiamo agli array.
<?php
$setteNani=array("gongolo","mammolo","pisolo","cucciolo","dotto","eolo","brontolo");
var_dump($setteNani);
?> 
array(7) { [0]=> string(7) "gongolo" [1]=> string(7) "mammolo" [2]=> string(6) "pisolo" [3]=> string(8) "cucciolo" [4]=> string(5) "dotto" [5]=> string(4) "eolo" [6]=> string(8) "brontolo" }

Bene, sì: viene messo tra parentesi il numero di elementi dell'array, quindi gli indici tra parentesi quadre e, separata dal segno =>, ogni variabile che fa parte dell'array.

Per il momento mi fermo qua, perché poi ci sono anche in php le classi.

domenica 22 aprile 2018

Creazione di una nuova tabella in database Access con VB.NET

Ed ecco il codice per la creazione di una nuova tabella del database (Sempre Access 2003).
Imports System.Data.OleDb
Public Class Form1
    Dim con As New OleDb.OleDbConnection
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        con.ConnectionString = "Provider=microsoft.jet.oleDB.4.0;" &
            "data source=C:\users\antonello\documents\tavoloDB.mdb"
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Not con.State = ConnectionState.Open Then
            con.Open()
        End If
        Dim cmd As New OleDb.OleDbCommand("CREATE TABLE tblCavolo(id int,testo varchar)", con)
        cmd.ExecuteNonQuery()
        con.Close()

    End Sub
End Class
...che ha funzionato.

sabato 21 aprile 2018

INSERT e UPDATE database Access mediante VB.NET

Vediamo se riesco a decifrare il codice per inserire un record nella tabella del database.

L'ho scritto.
Imports System.Data.OleDb
Public Class Form1
    Dim con As New OleDb.OleDbConnection
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        con.ConnectionString = "Provider=microsoft.jet.oleDB.4.0;" &
            "data source=C:\Users\Antonello\Documents\tavoloDB.mdb"
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Not con.State = ConnectionState.Open Then
            con.Open()
        End If
        Dim cmd As New OleDb.OleDbCommand
        cmd.Connection = con
        cmd.CommandText = "INSERT INTO Tabella (nome,cognome) VALUES('BINGO','BONGO')"
        cmd.ExecuteNonQuery()

        con.Close()


    End Sub
End Class


Ora distruggo il mandala e lo ricostruisco una prima volta.

Ecco la mia ricostruzione:
Imports System.Data.OleDb
Public Class Form1
    Dim con As New OleDb.OleDbConnection

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        con.ConnectionString = "Provider=microsoft.jet.oleDB.4.0;" &
        "data source=C:\Users\Antonello\Documents\tavoloDB.mdb"
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Not con.State = ConnectionState.Open Then
            con.Open()
        End If
        Dim cmd As New OleDb.OleDbCommand
        cmd.Connection = con
        cmd.CommandText = "INSERT INTO Tabella(nome,cognome) VALUES('PINCO', 'PALLINO')"
        cmd.ExecuteNonQuery()
        con.Close()
    End Sub
End Class
In rosso, la riga che ho dimenticato, ottenendo il risultato "connessione non inizializzata".
Ripeto il Mandala:
Imports System.Data.OleDb
Public Class Form1
    Dim con As New OleDb.OleDbConnection
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        con.ConnectionString = "Provider=microsoft.jet.oleDB.4.0;" &
            "data source=C:\users\antonello\documents\tavoloDB.mdb"
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Not con.State = ConnectionState.Open Then
            con.Open()
        End If

        Dim cmd As New OleDb.OleDbCommand
        cmd.Connection = con
        cmd.CommandText = "INSERT INTO Tabella(nome,cognome) VALUES('TIZIO','CAIO')"
        cmd.ExecuteNonQuery()
        con.Close()
    End Sub
End Class
Questa volta me la sono cavata solo con un errore di sintassi SQL nel CommandText (VALUE al posto di VALUES).


Ora provo a cambiare il comando SQL per vedere se posso updatare piuttosto che inserire un nuovo dato.
Ecco:
Imports System.Data.OleDb
Public Class Form1
    Dim con As New OleDb.OleDbConnection
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        con.ConnectionString = "Provider=microsoft.jet.oleDB.4.0;" &
            "data source=C:\users\antonello\documents\tavoloDB.mdb"
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Not con.State = ConnectionState.Open Then
            con.Open()
        End If

        Dim cmd As New OleDb.OleDbCommand
        cmd.Connection = con
        cmd.CommandText = "UPDATE Tabella2 SET nome = 'ABDULLAH'," &
        "cognome ='AKBAR' WHERE id=2;"
        cmd.ExecuteNonQuery()
        con.Close()
    End Sub
End Class
Ho dovuto creare una nuova tabella con il contatore chiamato id perché con l'underscore _id ottenevo un messaggio di errore nella clausola WHERE. Dunque in Access l'underscore non è ammesso, diversamente da quanto accade in Java Android dove è consigliabile.
Questo codice ha funzionato!
Ora su questa tabella di database:
id nome cognome
1 MARIO ROSSI
2 ABDULLAH AKBAR
3 GIUSEPPE VERDI
4 CICCIO PAGNOTTA
5 JOE FETECCHIA
faccio un esercizio: aggiungere PIPPO CAROGNA e sostituire il nome arabo con un nome greco.
Vai!

Ho provato:
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Not con.State = ConnectionState.Open Then
            con.Open()
        End If

        Dim cmd As New OleDb.OleDbCommand
        cmd.Connection = con
        cmd.CommandText = "INSERT INTO Tabella2(nome, cognome) VALUES('PIPPO','CAROGNA')"
        cmd.ExecuteNonQuery()
        cmd.CommandText = "UPDATE Tabella SET nome='MIKIS',cognome='PARALIRIGORIS'" &
            "WHERE id=2"
        cmd.ExecuteNonQuery()
        con.Close()
    End Sub
ma ottengo errore. Il primo comando me lo esegue, quindi probabilmente il problema sta nel secondo comando. Forse sbaglio qualcosa nell'esecuzione in serie di più comandi.

Ecco, forse ho capito: devo dichiarare come New anche il secondo comando.
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Not con.State = ConnectionState.Open Then
            con.Open()
        End If

        Dim cmd As New OleDb.OleDbCommand
        cmd.Connection = con
        cmd.CommandText = "INSERT INTO Tabella2(nome, cognome) VALUES('PIPPO','CAROGNA')"
        cmd.ExecuteNonQuery()
        Dim cmd2 As New OleDb.OleDbCommand
        cmd2.Connection = con
        cmd2.CommandText = "UPDATE Tabella2 SET nome='MIKIS',cognome='PARALIRIGORIS'" &
            " WHERE id=2"
        cmd2.ExecuteNonQuery()
        con.Close()
    End Sub
Ho trovato questa soluzione. Non capisco perché non posso usare la variabile cmd per i due comandi...

Comunque la tabella è cambiata:
id nome cognome
1 MARIO ROSSI
2 MIKIS PARALIRIGORIS
3 GIUSEPPE VERDI
4 CICCIO PAGNOTTA
5 JOE FETECCHIA
12 PIPPO CAROGNA
Rimetto un altro nome al numero 2, cancello l'ultimo record (il fatto che riporta l'id = 12 testimonia i vari tentativi con ripetute cancellazioni del record che era stato aggiunto), e riprovo.

Provo così:
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Not con.State = ConnectionState.Open Then
            con.Open()
        End If

        Dim cmd As New OleDb.OleDbCommand
        cmd.Connection = con
        cmd.CommandText = "INSERT INTO Tabella2(nome, cognome) VALUES('PIPPO','CAROGNA')"
        cmd.ExecuteNonQuery()
        cmd = New OleDb.OleDbCommand
        cmd.CommandText = "UPDATE Tabella2 SET nome='GIULIO',cognome='CESARE'" &
            " WHERE id=2"
        cmd.ExecuteNonQuery()
        con.Close()
...e ottengo l'errore La proprietà connection non è stata inizializzata.

Allora la inizializzo.
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Not con.State = ConnectionState.Open Then
            con.Open()
        End If

        Dim cmd As New OleDb.OleDbCommand
        cmd.Connection = con
        cmd.CommandText = "INSERT INTO Tabella2(nome, cognome) VALUES('PIPPO','CAROGNA')"
        cmd.ExecuteNonQuery()
        cmd = New OleDb.OleDbCommand
        cmd.Connection = con
        cmd.CommandText = "UPDATE Tabella2 SET nome='GIULIO',cognome='CESARE'" &
            " WHERE id=2"
        cmd.ExecuteNonQuery()
        con.Close()
    End Sub
Non ho avuto messaggi di errore.
Ora vediamo la tabella:
id nome cognome
1 MARIO ROSSI
2 GIULIO CESARE
3 GIUSEPPE VERDI
4 CICCIO PAGNOTTA
5 JOE FETECCHIA
13 PIPPO CAROGNA
14 PIPPO CAROGNA
Perfetto! La duplicazione di PIPPO CAROGNA è dovuta al fatto che ho dimenticato di eliminare il record aggiunto quando l'esecuzione è stata interrotta per il primo errore.
Ho dimenticato una clausola WHERE nell'UPDATE, e mi ha updatato tutti i records con un solo valore. Cancello manualmente e ricostruisco la tabella a mano (gli ID sono tutti sbagliati).
Ecco la nuova tabella:
id nome cognome
16 MARIO ROSSI
17 GIULIO CESARE
18 GIUSEPPE VERDI
19 CICCIO PAGNOTTA
20 JOE FETECCHIA
21 PIPPO CAROGNA
Ora vediamo con questo codice:
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Not con.State = ConnectionState.Open Then
            con.Open()
        End If

        Dim cmd As New OleDb.OleDbCommand("INSERT INTO Tabella2(nome,cognome) VALUES('ANTONIO','CICCETTI')", con)
        Dim cmd2 As New OleDb.OleDbCommand("UPDATE Tabella2 SET nome='YOUSSEF',cognome='KHANZIR'" &
                                           " WHERE id=17", con)
        cmd.ExecuteNonQuery()
        cmd2.ExecuteNonQuery()
        con.Close()
    End Sub
Vediamo...

id nome cognome
16 MARIO ROSSI
17 YOUSSEF KHANZIR
18 GIUSEPPE VERDI
19 CICCIO PAGNOTTA
20 JOE FETECCHIA
21 PIPPO CAROGNA
23 ANTONIO CICCETTI
Ho dovuto cambiare da 2 a 17 per via del casino che ho combinato con gli ID cancellando e riscrivendo manualmente.

venerdì 20 aprile 2018

VB.NET: connessione a un database e importazione di una tabella

Un po' di esercizio con i database in vb.net.
Salvo il mio codice che si è dimostrato in grado di riportare il contenuto dei record di una tabella di database:
Imports System.Data.OleDb
Public Class Form1

    Dim con As OleDbConnection
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        If Not con.State = ConnectionState.Open Then
            con.Open()
        End If

    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load

        con = New OleDb.OleDbConnection
        con.ConnectionString = "Provider=microsoft.jet.oleDB.4.0; data source = c:\tavoloDB.mdb"

        If Not con.State = ConnectionState.Open Then
            con.Open()
        End If

        Dim da As New OleDb.OleDbDataAdapter("SELECT * FROM Tabella", con)
        Dim dt As New DataTable
        da.Fill(dt)

        Debug.Print(dt.Rows(1)("nome").ToString)
        'Me.dgv.DataSource = dt

        con.Close()
    End Sub
End Class
Distruggo tutto.

Ora riscrivo il codice da zero: innanzitutto la stringa di connessione...

Ecco, prima devo dichiarare la nuova connessione, e quindi attribuirle la stringa.
Ma per prima cosa devo importare System.Data.dbOle.
Imports System.Data.OleDb
Public Class Form1
    Dim con As New OleDb.OleDbConnection
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        con.ConnectionString = "Provider=microsoft.jet.oleDB.4.0; data source=C:\tavoloDB.mdb"

    End Sub
End Class
Ora devo decidere quando aprire la connessione.
Facciamo al click del pulsante...

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Not con.State = ConnectionState.Open Then
            con.Open()
        End If
    End Sub
Ecco la formula "rituale" per aprire la connessione al database se non è già aperta.

Ora come identifico la tabella?
Tengo presente che devo creare un oggetto tabella che deve essere riempito da un adapter.
Comincio con l'adapter.
    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        If Not con.State = ConnectionState.Open Then
            con.Open()
        End If
        Dim da As New OleDb.OleDbDataAdapter("SELECT * FROM Tabella", con)

    End Sub
Quindi devo creare l'oggetto tabella, il cui tipo è DataTable, e riempirla con l'adapter da.
        Dim da As New OleDb.OleDbDataAdapter("SELECT * FROM Tabella", con)
        Dim dt As New DataTable
        da.Fill(dt)
Proviamo a scrivere il campo "nome" del primo record della tabella...
        Dim da As New OleDb.OleDbDataAdapter("SELECT * FROM Tabella", con)
        Dim dt As New DataTable
        da.Fill(dt)
        Debug.Print(dt.Rows(0)("nome").ToString)
Vediamo se funziona...

CICCIO

Funziona!

Rompo e ricostruisco il Mandala...

Bene il secondo tentativo.
Ora lo replico in video.

venerdì 6 aprile 2018

Aggiornamento di una TextView ogni secondo con i Thread

Per aggiornare ogni secondo una TextView allo scopo di costruire un cronometro:



Ora rompo il Mandala e lo ricostruisco...

mercoledì 4 aprile 2018

Mandala di broadcast receiver registrato dinamicamente e attivato da un AlarmManager sulla stessa activity

Mandala.
Costruire un AlarmManager di tipo RTC_WAKEUP che aziona la suoneria mediante broadcast, con broadcastreceiver registrato dinamicamente.

Salvataggio:
public class MainActivity extends AppCompatActivity {

    BroadcastReceiver receiver;
    IntentFilter filter;
    Ringtone ringtone;

    AlarmManager alarmManager;
    Intent intent;
    PendingIntent pendingIntent;

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

        stopButton=(Button)findViewById(R.id.button);
        stopButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                ringtone.stop();
            }
        });
        receiver=new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {

                Uri ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(getApplicationContext(),
                        RingtoneManager.TYPE_ALARM);
                ringtone = RingtoneManager.getRingtone(getApplicationContext(), ringtoneUri);
                ringtone.play();
            }
        };

        filter=new IntentFilter();
        filter.addAction("suona");
        registerReceiver(receiver,filter);


        intent=new Intent();
        intent.setAction("suona");

        pendingIntent=PendingIntent.getBroadcast(getApplicationContext(),
                0,
                intent,
                0);
        alarmManager=(AlarmManager)getSystemService(ALARM_SERVICE);

        calendar=Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        calendar.set(Calendar.HOUR_OF_DAY,9);
        calendar.set(Calendar.MINUTE,0);
        calendar.set(Calendar.SECOND,0);


        alarmManager.set(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(),pendingIntent);

    }


}

Parto da questo scheletro:
public class MainActivity extends AppCompatActivity {


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




martedì 3 aprile 2018

Mandala completo del service binding

Ora faccio il primo Mandala completo: distruggo sia la main che il Service e li ricostruisco.

Scheletro della main:
public class MainActivity extends AppCompatActivity {

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

    }

}


Scheletro del Service:
public class Servizio extends Service {

    public Servizio() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}



Binding services. Mandala della activity principale.

Prima di passare ai Mandala dell'activity principale, mi studio il codice di connessione e disconnessione del service.
In OnStart:
    @Override
    protected void onStart() {
        super.onStart();
        Intent intent=new Intent(this,Servizio.class);
        bindService(intent,serviceConnection,BIND_AUTO_CREATE);


    }
La parte dell'Intent è come sempre.
La parte successiva implica il dover indicare l'intent, ma anche la serviceConnection e la costante BIND_AUTO_CREATE, che non mi è molto chiara, ma per il momento soprassediamo.


    @Override
    protected void onStop() {
        super.onStop();
        if(mBound){
            unbindService(serviceConnection);
            mBound=false;
        }
    }
Viene chiuso il service usando solo la serviceConnection e viene dichiarata false la variabile booleana mBound, che ho dimenticato di aggiungere nel metodo OnServiceConnected di ServiceConnection, mentre invece nel codice che ho consultato l'avevo messa in modo improprio.
Provo a fare un mandala di tutto, non prima di aver salvato tutta la main.
public class MainActivity extends AppCompatActivity {

    ServiceConnection serviceConnection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Servizio.LocalBinder myIBinder=(Servizio.LocalBinder)iBinder;
            Servizio myService=myIBinder.getService();
            myService.metodoPerVerifica();
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };


    boolean mBound=false;

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

    }

    @Override
    protected void onStart() {
        super.onStart();
        Intent intent=new Intent(this,Servizio.class);
        bindService(intent,serviceConnection,BIND_AUTO_CREATE);


    }

    @Override
    protected void onStop() {
        super.onStop();
        if(mBound){
            unbindService(serviceConnection);
            mBound=false;
        }
    }


}

Parto da questo scheletro:
public class MainActivity extends AppCompatActivity {



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

    }
}


Ecco il Mandala ricostruito:
public class MainActivity extends AppCompatActivity {

    boolean mBound=false;

    ServiceConnection serviceConnection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Servizio.LocalBinder myIBinder=(Servizio.LocalBinder)iBinder;
            Servizio myService=myIBinder.getService();
            mBound=true;
            myService.metodoPerVerifica();

        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };


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

    }

    @Override
    protected void onStart() {
        super.onStart();
        Intent intent=new Intent(getApplicationContext(),Servizio.class);
        bindService(intent,serviceConnection,BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if(mBound){
            unbindService(serviceConnection);
            mBound=false;
        }
    }
}
Ora, se funziona, dovrebbe scrivermi in LogCat la parola "VERIFICA" secondo il metodo che ho creato nel Service.
Vediamo...

04-04 06:42:37.962 2148-2148/? I/System.out: VERIFICA
Perfetto!

Mandala del service.

Adesso faccio un mandala con il service. Lo distruggo completamente e lo ricostruisco.

Parto dallo scheletro:
public class Servizio extends Service {

  
    public Servizio() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }


}
Ho inserito anche un metodo per la verifica, da eseguire da parte della main, che già mi risulta nella main, buon segno.
public class Servizio extends Service {

    IBinder mBinder = new LocalBinder();
    public Servizio() {
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    public class LocalBinder extends Binder{
        Servizio getService(){
            return Servizio.this;
        }
    }

    public void metodoPerVerifica(){
        System.out.println("VERIFICA");
    }


}
Provo ad eseguire e verifichiamo.
04-04 06:12:40.044 471-471/? I/System.out: VERIFICA
Perfetto!

Ripasso del binding di un service

Non ricordo come si binda un service.
E' necessario fare un po' di mandala in proposito.

Per prima cosa si costruisce una classe di tipo LocalBinder che estende Binder.
Questa classe restituisce il Service stesso.
    class LocalBinder extends Binder {
        Servizio getService(){
            return Servizio.this;
        }
    }
Da questa classe LocalBinder si può creare un oggetto come interfaccia IBinder, in quanto, dato che LocalBinder estende Binder e IBinder è implementatata da Binder, la procedura è del tutto lecita.
IBinder mBinder=new LocalBinder();
Questo va poi "sparato" nel metodo IBinder onBind(Intent intent)
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
Sulla principale, invece, la cosa non me la ricordo affatto...

Si comincia con il creare nella sezione "dichiarazioni", un oggetto di classe ServiceConnection.
public class MainActivity extends AppCompatActivity {


    ServiceConnection connection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Servizio.LocalBinder myIBinder=(Servizio.LocalBinder)iBinder;
            Servizio servizio=myIBinder.getService();
            servizio.verbo();
            mBound=true;

        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            mBound=false;
        }
    };
    boolean mBound=false;

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

    }
Quindi (l'ho messo nel metodo onStart dell'activity non ricordo perché), si binda il service, che viene invece "sbindato" nel metodo onStop:
    @Override
    protected void onStart() {
        super.onStart();
        Intent intent=new Intent(this,Servizio.class);
        bindService(intent,connection,BIND_AUTO_CREATE);


    }

    @Override
    protected void onStop() {
        super.onStop();
        if(mBound){
            unbindService(connection);
            mBound=false;
        }
    }

Sarebbe il caso di analizzare il codice della creazione dell'oggetto di tipo ServiceConnection...

Distruggo selettivamente la creazione dell'oggetto per ricostruirla.

Questo è ciò che mi viene in automatico:
    ServiceConnection serviceConnection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };
Nel metodo onServiceConnected vengono forniti due parametri, ComponentName componentName e IBinder iBinder. Questi dovrebbero essere fondamentali...

IBinder iBinder dovrebbe essere quello che mi viene fornito dal metodo
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
del Service.
che è di classe LocalBinder. Quindi devo creare un oggetto nell'activity principale che sia dello stesso tipo LocalBinder, onde renderlo uguale all'oggetto liberatomi nei parametri, che è di tipo LocalBinder, e che quindi va castato. Provo ad eseguire a memoria:
    ServiceConnection serviceConnection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            Servizio.LocalBinder myIBinder=(Servizio.LocalBinder)iBinder;
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {

        }
    };
Ricordando che la classe LocalBinder, cui appartiene il mio oggetto "da questa parte" MyIBinder e l'oggetto "da quella parte" IBinder ha un metodo di tipo Servizio che restituisce il Service che sta da "quella parte", posso ottenere da questo metodo il Service.
Il metodo era di tipo Servizio e si chiamava getService(), e restituiva Servizio.this.
    class LocalBinder extends Binder {
        Servizio getService(){
            return Servizio.this;
        }
    }
Fatto questo posso ottenere il Service da questa parte.

lunedì 2 aprile 2018

Realizzare una sveglia con AlarmManager RTC

Obiettivo: realizzare una sveglia con il pulsante per accenderla e quello per spegnerla.

Cerchiamo di studiare la sveglia.
Innanzitutto abbiamo un pulsante per l'attivazione e per la disattivazione.
Per il momento creo un pulsante per l'attivazione e uno diverso per la disattivazione.

Il codice è questo:
public class MainActivity extends AppCompatActivity {

    AlarmManager alarmManager;
    Intent intent;
    PendingIntent pendingIntent;
    Button button;
    Button button2;
    Calendar calendar;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        button=(Button)findViewById(R.id.button);
        button2=(Button)findViewById(R.id.button2);

        intent=new Intent(getApplicationContext(),MyService.class);
        pendingIntent=PendingIntent.getService(getApplicationContext(),0,intent,0);
        alarmManager=(AlarmManager)getSystemService(ALARM_SERVICE);

        calendar=Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        calendar.set(Calendar.HOUR_OF_DAY,23);
        calendar.set(Calendar.MINUTE,0);
        calendar.set(Calendar.SECOND,0);

        button.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View view) {
                alarmManager.set(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(),pendingIntent);
            }
        });

        button2.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View view) {
                if(alarmManager!=null){
                    alarmManager.cancel(pendingIntent);
                    if(pendingIntent!=null)pendingIntent.cancel();
                }
            }
        });
e funziona per una volta, non ripetibile.
La normale sveglia funziona per una volta, ma si presenta con un pulsante che consente l'opzione di rinviare o di spegnere del tutto la sveglia. Per spegnerla bisogna zittire la suoneria e disattivare alarmManager, due cose che penso di poter fare.
Per rinviare, si dovrebbe programmare a breve scadenza con un AlarmManager di tipo ELAPSED il riattacco della suoneria.