JavascriptProva

domenica 4 novembre 2018

Ancora sul trucco per non riavviare l'applicazione dopo i permessi a runtime per l'overlay

Views in overlay.
Con l'occasione, ripasso il "trucco" per non dover riavviare il programma una volta concesso il permesso a runtime per gli overlay.

Iniziamo da qui:
public class MainActivity extends AppCompatActivity {
    
    Intent i;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

    }

}
Ora, devo inserire il codice per i permessi.
Innanzitutto non deve mancare mai il classico permesso nel manifest!
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.antonello.studiooverlay">
    <uses-permission android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name" 


Quindi ci sono i permessi a runtime.
Approfitto dell'occasione per ripassare un po' i "meccanismi" della cosa...

Se l'API è uguale o superiore alla 23, se contemporaneamente non è impostato il permesso di Overlay (!Settings.canDrawOverlays(getApplicationContext())), si crea un intent avente per parametri ACTION_MANAGE_OVERLAY_PERMISSION e Uri.parse(...col nome del package...).
Questo dovrebbe bastare a cambiare le carte in tavola dopo aver chiamato startActivity(intent).
Però sempre dopo aver riavviato l'applicazione.

Ecco il codice:
        if(Build.VERSION.SDK_INT >= 23 ){
            if(!Settings.canDrawOverlays(getApplicationContext())){
                Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:"+getPackageName()));
                startActivity(i);
            }
        }
Ora applichiamo il "trucco".
public class MainActivity extends AppCompatActivity {


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

        Runnable runnable = new Runnable() {
            @RequiresApi(api = Build.VERSION_CODES.M)
            @Override
            public void run() {
                if(Settings.canDrawOverlays(getApplicationContext())){
                    Intent i = new Intent(getApplicationContext(),MainActivity.class);
                    i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
                    startActivity(i);
                }else{
                    new Handler().postDelayed(this,1000);
                }
            }
        };


        if(Build.VERSION.SDK_INT >= 23 ){
            if(!Settings.canDrawOverlays(getApplicationContext())){
                Intent i = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:"+getPackageName()));
                startActivity(i);
                new Handler().postDelayed(runnable,1000);
            }
        }

    }

}
Ora realizzo un video con due emulatori aventi rispettivamente API 22 e API 23 per metterne in luce le differenze di comportamento.

Rappresentazione dei dati di un database in un DataGridView (parte iniziale)

Dunque riepilogando: mi conviene stare dietro alle tecniche più nuove per la gestione dei database.
Per prima cosa devo creare la coppia String e Connection, in quanto la connection si serve della string per connettersi al database.
Ecco:
        Dim connString As String = "Provider = Microsoft.Jet.OLEDB.4.0; data source = C:\users\antonello\documents\anto.mdb"
        Dim conn As New OleDbConnection(connString)
Questo funziona.
Ora devo vedere bene come si gestiscono i comandi.
Il command accetta due parametri: una query e la connessione, che deve però essere già stata inizializzata con la stringa di connessione.
Quindi, prima creiamo la connessione con la stringa di connessione per parametro, quindi il comando con per parametri la query e la connessione.
        Dim conn As OleDbConnection
        Dim cString As String = "Provider = Microsoft.Jet.OLEDB.4.0; data source=C:\users\antonello\Documents\anto.mdb"
        conn = New OleDbConnection(cString)
        Dim command As New OleDbCommand("select * from pazienti", conn)
O anche:
        Dim conn As OleDbConnection
        Dim cString As String = "Provider = Microsoft.Jet.OLEDB.4.0; data source=C:\users\antonello\Documents\anto.mdb"
        conn = New OleDbConnection(cString)
        Dim query As String = "select * from pazienti"
        Dim command As New OleDbCommand(query, conn)
Per un migliore aiuto mnemonico:
        Dim conn As OleDbConnection
        Dim cString As String = "Provider = Microsoft.Jet.OLEDB.4.0; data source=C:\users\antonello\Documents\anto.mdb"
        conn = New OleDbConnection(cString)


        Dim query As String = "select * from pazienti"
        Dim command As New OleDbCommand(query, conn)

Ora leggiamo i dati che ci sono nel database, mediante la query.
Per fare questo c'è un oggetto OLEDBDataReader.
        Dim reader As OleDbDataReader
        reader = command.ExecuteReader
Per mezzo di questo reader si possono elencare le voci presenti nella tabella.
Però, mentre il command, (e ovviamente la connessione) può essere inizializzato senza che la connessione sia aperta, il reader, che esegue un'azione, richiede sempre la connessione aperta, altrimenti genera un errore:
        conn.Open()

        Dim reader As OleDbDataReader
        reader = command.ExecuteReader


        While (reader.Read)
            MsgBox(reader.GetString(1))
        End While

        conn.Close()

In questo modo ottengo una serie di MessageBoxes contenenti le stringhe del campo n.1.

Ora andiamo avanti e creiamo un DataAdapter, che avrebbe la funzione di prendere tutti i dati del database (forse quelli selezionati dalla query...).

giovedì 1 novembre 2018

Ancora sui form php.

Nel file denominato alla voce "action" si processa l'informazione.

Il form è questo:
<form action=pagina.php method = "POST">
    <input type="text" name = "nome">
    <input type="text" name = "cognome">
    <input type= "submit" value = "Mannalo affanculo">
</form> 
e la pagina è:
<?php
echo $_POST;
?>
No! In questo caso ottengo solo:
Array
Invece la pagina deve essere così, come se $_POST fosse un array i cui elementi siano quelli chiamati con "nome" e "cognome" (come li ho chiamati io nel form, avrei potuto chiamarli pure "Pasquale" e "Cicciobello".
<?php
echo $_POST["nome"];
echo $_POST["cognome"];
?>
Vediamo adesso...
cicciofatticcio
Ecco, mi sono venuti attaccati perché non ho messo nessuno spazio vuoto fra le due risposte.
Vediamo come viene trasmessa l'informazione mediante il metodo GET:
<form action=pagina.php method = "GET">
    
    
    
</form>
La barra degli indirizzi:
https://trigon.xyz/pagina.php?nome=ciccio&cognome=fatticcio
La pagina è vuota perché vengono richieste variabili di tipo POST.
Provo a richiederle GET:
<?php
echo $_GET["nome"];
echo $_GET["cognome"];
?>
La barra degli indirizzi è sempre così:
https://trigon.xyz/pagina.php?nome=ciccio&cognome=bello
E la pagina risultante è:
cicciobello

Ripasso del PHP. Ricominciamo dai form

Per il ripasso del PHP, cominciamo dai forms.
Questo è quel poco che ricordo dei forms:
<form action="POST" >
    

</form> 

Vediamo come si ampliano...

<form action=pagina.php method = "POST">
    
⁢/form>
Ecco, con action si intende la pagina di destinazione.Il Method è, per quanto ricordo, la possibilità di far apparire sulla barra degli indirizzi i dati o no...

Vediamo il contenuto del form...

<form action=pagina.php method = "POST">
    <input type="text" name = "nome">
    <input type="text" name = "cognome">
    <input type= "submit" value = "Mannalo affanculo">
</form> 
Che fa questo form? Assolutamente una minchia, suppongo...

Infatti, ecco il risultato:



Mi sembra evidente che manchi la pagina "pagina.php".
Ora la creo. Vuota. Per vedere l'effetto che fa!

E infatti appare una pagina completamente BIANCA!
Diamo uno sguardo pure alla barra degli indirizzi:
Questa è quella che mi appare adesso:
https://trigon.xyz/pagina.php


Ma proviamo a cambiare il method con "GET":
https://trigon.xyz/pagina.php?nome=Ciccio&cognome=Molliccio
Appare anche il contenuto degli "input".

mercoledì 24 ottobre 2018

Lettura delle tabelle di un database come recordset per mezzo delle librerie DAO da VB.NET

Ecco, anche l'apertura dei recordset e la loro rappresentazione presenta qualche differenza. I codici con il punto esclamativo non mi hanno funzionato.
E' comunque possibile fare ugualmente:
    Private Sub apri()
        Dim engine As DBEngine = New DBEngine
        Dim db As Database
        db = engine.OpenDatabase("C:\users\antonello\documents\anto.mdb")
        Dim rs As Recordset = db.OpenRecordset("pazienti")
        rs.MoveFirst()
        Do While Not rs.EOF

            MsgBox(rs.Fields("nome").Value)
            rs.MoveNext()
        Loop
    End Sub

Creazione di un database a runtime con le librerie DAO

Un bel ripasso dei database gestiti con le librerie DAO in VB.NET.
C'è qualche differenza con la sintassi che conoscevo dall'antico VB6, ma niente di insuperabile, almeno finora:
Imports DAO

Public Class Form1
    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Dim engine = New DBEngine
        Dim db As Database
        db = engine.OpenDatabase("C:\users\antonello\bikongo.mdb")
        Dim tabella As TableDef = db.CreateTableDef("Tabella1")


        tabella.Fields.Append(tabella.CreateField("id", DAO.DataTypeEnum.dbInteger))
        tabella.Fields.Append(tabella.CreateField("nome", DAO.DataTypeEnum.dbText))
        tabella.Fields.Append(tabella.CreateField("cognome", DAO.DataTypeEnum.dbText))
        db.TableDefs.Append(tabella)

    End Sub
End Class
Questa è la creazione di una tabella con tre campi, uno numerico e due di testo.

lunedì 22 ottobre 2018

Creazione di una custom view in Android

Costruzione di una customview in android.
L'avevo vista e capita, e poi ho scordato praticamente tutto.

Ho un file xml che ho chiamato my_view.xml, e un file java che ho chiamato myView.java.
Analizziamo questo file.
public class MyView extends RelativeLayout {
    TextView testo1;
    TextView testo2;
    public MyView(Context context) {
        super(context);
        initView(context);
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);

        initView(context);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        initView(context);
    }

    private void initView(Context context){
        inflate(context,R.layout.my_view,this);

    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        testo1=(TextView)findViewById(R.id.testo1);
        testo2=(TextView)findViewById(R.id.testo2);
        this.setBackgroundColor(Color.CYAN);
    }

    public void saluta(){
        testo1.setText("BUONGIORNO");
        testo2.setText("BUONASERA");
    }
}
Le variaabili dichiarate a livello di classe sono due variabili oggetto per le due TextView che saranno contenute nella view, ossia testo1 e testo2.
public class MyView extends RelativeLayout {
    TextView testo1;
    TextView testo2;
Quindi vengono chiamati tutti i costruttori della classe genitore RelativeLayout.
    public MyView(Context context) {
        super(context);
        initView(context);
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);

        initView(context);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        initView(context);
    }
In tutti e tre i costruttori viene chiamato il metodo initView.

Il metodo initView è questo:
    private void initView(Context context){
        inflate(context,R.layout.my_view,this);

    }
in pratice quello che "inflata" il layout specificato in xml entro questo oggetto.
Quindi c'è onFinishInflate, che dovrebbe essere il metodo che entra in azione una volta che l'"inflatazione" sia terminata, in modo che alle variabili oggetto vengano attribuite le views presenti nell'xml.

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        testo1=(TextView)findViewById(R.id.testo1);
        testo2=(TextView)findViewById(R.id.testo2);
        this.setBackgroundColor(Color.CYAN);
    }

Una volta terminata l'inflatazione, si possono creare i metodi, come appunto questo:
    public void saluta(){
        testo1.setText("BUONGIORNO");
        testo2.setText("BUONASERA");
    }
Il file xml è così:
<?xml version="1.0" encoding="utf-8"?>
<merge
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/testo1"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true"
        android:layout_marginTop="100dp"
        android:layout_marginStart="100dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/testo2"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true"
        android:layout_marginTop="150dp"
        android:layout_marginStart="100dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</merge> 

Il tutto va poi inserito in un'applicazione:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.example.antonello.studiocustomview.MyView
        android:id="@+id/myView"
        android:layout_width="200dp"
        android:layout_height="200dp" />



</RelativeLayout> 
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MyView myView = (MyView)findViewById(R.id.myView);
        myView.saluta();
    }
}
Ecco, adesso credo di aver rinfrescato a sufficienza il modo di creare delle CustomViews.