JavascriptProva

domenica 29 ottobre 2017

VB.NET: giocando con le matrici per scomporre un numero nelle sue cifre.

Rispolvero il VB.
L'idea è raccogliere i numeri derivati dalla scomposizione di un numero in unità, decine, centinaia eccetera, in una matrice, per poi scriverli comodamente ognuno in una label.
Vediamo...

Per ridimensionare le matrici dinamiche in VB ho costruito questo codice:
If (matrice(0) <> Nothing) Then ReDim Preserve matrice(UBound(matrice) + 1)
che dovrebbe funzionare.
Ora metto dei numeri consecutivi da 1 a 10 in una matrice dinamica che inizia con lunghezza 1 (uBound = 0) e si allunga progressivamente a seconda della quantità di elementi che possiederà alla fine.

Public Class Form1

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

        Dim matrice(0) As Integer

        For n = 1 To 10
            If matrice(0) <> Nothing Then ReDim Preserve matrice(matrice.Length)
            matrice(UBound(matrice)) = n
        Next

        For n = 0 To UBound(matrice)
            Debug.Print(matrice(n))
        Next

    End Sub
End Class
1
2
3
4
5
6
7
8
9
10
Posso cambiare liberamente anche la quantità dei dati da immettere nella matrice:
Public Class Form1

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

        Dim matrice(0) As Integer

        For n = 1 To 15
            If matrice(0) <> Nothing Then ReDim Preserve matrice(matrice.Length)
            matrice(UBound(matrice)) = n
        Next

        For n = 0 To UBound(matrice)
            Debug.Print(matrice(n))
        Next

    End Sub
End Class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Il codice dice che se la voce 0 non è pari a nulla la matrice va ridimensionata a un indice superiore di 1 all'ultimo indice già presente (e quindi uguale alla lunghezza della matrice), quindi il numero va scritto all'ultimo indice presente.
Molto semplice.

Ora posso scomporre il mio numero.
Ecco il codice che ho elaborato, che mi mette in una matrice le cifre di un numero, dopo aver eliminato l'eventuale virgola:
Public Class Form1

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


        Dim numero As Double = 3453653
        Dim stringa As String = numero.ToString.Replace(",", "")
        numero = Convert.ToDouble(stringa)
        Debug.Print(numero)
        Dim quoziente As Integer
        Dim resto As Integer
        Dim matrice(0) As Double

        Do While numero > 0
            quoziente = numero \ 10
            resto = numero Mod 10
            If matrice(0) <> Nothing Then ReDim Preserve matrice(matrice.Length)
            matrice(UBound(matrice)) = resto
            numero = quoziente
        Loop

        For n = UBound(matrice) To 0 Step -1
            Debug.Print(matrice(n))
        Next
    End Sub
End Class
3453653
3
4
5
3
6
5
3
(la matrice va letta al contrario)

sabato 27 maggio 2017

Animazioni, primi approcci

Sono riuscito a ottenere delle animazioni.
Preferisco farle programmaticamente perché non sono riuscito in XML a spostare la view effettivamente.

Questo un codice:
public class MainActivity extends AppCompatActivity {

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

        imageView=(ImageView)findViewById(R.id.imageView);
        imageView.getLayoutParams().width=200;
        imageView.setAdjustViewBounds(true);

        animation=new TranslateAnimation(0,100,0,0);

        animation.setInterpolator(AnimationUtils.loadInterpolator
                (this,android.R.anim.linear_interpolator));
        animation.setDuration(200);
        animation.setFillAfter(false);
        animation.setFillEnabled(true);

        animation.setAnimationListener(new Animation.AnimationListener(){

            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                RelativeLayout.LayoutParams params=
                        (RelativeLayout.LayoutParams)imageView.getLayoutParams();
                System.out.println(params.leftMargin);
                params.leftMargin+=100;
                params.rightMargin=-1;
                imageView.setLayoutParams(params);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

        imageView.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View view) {
                imageView.startAnimation(animation);

            }
        });
    }

}
Ora rompo il Mandala e ricomincio...

sabato 20 maggio 2017

Immagine tonda che appare a intervalli prestabiliti

Ecco un'immagine circolare che appare a intervalli di tempo prestabiliti.

MainActivity:
package com.antonello.tavolaccio5;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;
import android.provider.Settings;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;

public class MainActivity extends AppCompatActivity {

    Button bttCancel;
    Button button;
    RelativeLayout mainLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mainLayout=(RelativeLayout)findViewById(R.id.mainLayout);
        button=(Button)findViewById(R.id.button);
        bttCancel=(Button)findViewById(R.id.button2);




        button.setOnClickListener(new Button.OnClickListener(){

            @Override
            public void onClick(View v) {
                if(Build.VERSION.SDK_INT>=23 && !Settings.canDrawOverlays(getApplicationContext())){
                    Intent intent=new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:"+getPackageName()));
                    startActivityForResult(intent,0);
                }else {
                    AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
                    Intent intent = new Intent(getApplicationContext(), Servizio.class);
                    PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0, intent, 0);
                    alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 1000 * 5,
                            pendingIntent);
                }
            }
        });

        bttCancel.setOnClickListener(new Button.OnClickListener(){

            @Override
            public void onClick(View v) {

                AlarmManager alarmManager=(AlarmManager)getSystemService(ALARM_SERVICE);
                Intent intent=new Intent(getApplicationContext(),Servizio.class);
                PendingIntent pendingIntent=PendingIntent.getService(getApplicationContext(),0,intent,0);
                alarmManager.cancel(pendingIntent);
                if(pendingIntent!=null)pendingIntent.cancel();
            }
        });

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data){

        if(Build.VERSION.SDK_INT>=23 && Settings.canDrawOverlays(getApplicationContext())){
            AlarmManager alarmManager=(AlarmManager)getSystemService(ALARM_SERVICE);
            Intent intent=new Intent(getApplicationContext(),Servizio.class);
            PendingIntent pendingIntent=PendingIntent.getService(getApplicationContext(),0,intent,0);
            alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime()+1000*5,
                    pendingIntent);
        }
    }
}


Servizio.java
package com.antonello.tavolaccio5;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.view.View;
import android.view.WindowManager;

/**
 * Created by Antonello on 19/05/2017.
 */

public class Servizio extends Service {

    RoundedImage roundedImage;
    WindowManager.LayoutParams wParams;
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId){
        final WindowManager windowManager=(WindowManager)getSystemService(WINDOW_SERVICE);

        wParams=new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT
        );

        roundedImage = new RoundedImage(this, BitmapFactory.decodeResource(getResources(),R.drawable.scrofalo),100);
        roundedImage.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {
                windowManager.removeView(v);
                //roundedImage=null;
                AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
                Intent intent = new Intent(getApplicationContext(), Servizio.class);
                PendingIntent pendingIntent = PendingIntent.getService(getApplicationContext(), 0, intent, 0);
                alarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 1000 * 5,
                        pendingIntent);

            }
        });

        windowManager.addView(roundedImage,wParams);

        stopSelf();
        return START_NOT_STICKY;
    }



}


RoundedImage.java
package com.antonello.tavolaccio5;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;


/**
 * Created by Antonello on 19/05/2017.
 */

public class RoundedImage extends android.support.v7.widget.AppCompatImageView {

    private Bitmap figura;
    private int radius;

    public RoundedImage(Context context, Bitmap figura, int radius){
        super(context);

        this.figura=figura;
        this.radius=radius;

        Bitmap bitmap=Bitmap.createBitmap(radius,radius,Bitmap.Config.ARGB_8888);

        Paint paint=new Paint();
        Canvas canvas=new Canvas(bitmap);
        canvas.drawCircle(bitmap.getWidth()/2,bitmap.getHeight()/2,bitmap.getWidth()/2,paint);

        Rect fromRect=new Rect(0,0,figura.getWidth(),figura.getHeight());
        Rect toRect=new Rect(0,0,bitmap.getWidth(),bitmap.getHeight());
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

        canvas.drawBitmap(figura,fromRect,toRect,paint);

        setImageBitmap(bitmap);

    }
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mainLayout"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.antonello.tavolaccio5.MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:id="@+id/textView" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="99dp"
        android:text="Button" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/button"
        android:layout_alignStart="@+id/button"
        android:layout_below="@+id/button"
        android:layout_marginTop="120dp"
        android:text="Button" />

</RelativeLayout> 

venerdì 19 maggio 2017

Permessi di disegno di un overlay nelle API da 23 in su

Ecco il codice:
public class MainActivity extends AppCompatActivity {

    Intent i;
    RelativeLayout mainLayout;
    @TargetApi(Build.VERSION_CODES.M)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mainLayout=(RelativeLayout)findViewById(R.id.mainLayout);

        if(Build.VERSION.SDK_INT>=23 && !Settings.canDrawOverlays(this)){
                Intent intent=new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                        Uri.parse("package:"+getPackageName())
                );
                startActivityForResult(intent,0);

        }else {
        i = new Intent(this, Servizio.class);
        startService(i);
        }

    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data){
        if(Build.VERSION.SDK_INT>=23) {
            if (Settings.canDrawOverlays(this)) {
                i = new Intent(this, Servizio.class);
                startService(i);

            }
        }
    }
}


Service:
public class Servizio extends Service {


    Bitmap bitmap;

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

   
    @Override
    public int onStartCommand(Intent intent, int flags, int startId){


        bitmap=BitmapFactory.decodeResource(getResources(),R.drawable.scrofalo);
        RoundedImage image=new RoundedImage(this,bitmap,200);
        WindowManager windowManager=(WindowManager)getSystemService(WINDOW_SERVICE);

        WindowManager.LayoutParams params=new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT
        );

        windowManager.addView(image,params);
        return START_NOT_STICKY;
    }

}
Chiama la classe RoundedImage, che ho creato e messo in una libreria.

mercoledì 17 maggio 2017

Immagine tonda fluttuante sullo schermo

Immagine rotonda fluttuante sullo schermo.

MainActivity.java:
public class MainActivity extends Activity {


    Button button;
    Button button2;
    Button button3;
    ImageView imageView;
    RelativeLayout mainLayout;



    @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);
        button3=(Button)findViewById(R.id.button3);
        imageView=new ImageView(this);
        mainLayout=(RelativeLayout)findViewById(R.id.activity_main);


        Intent intent=new Intent(getApplicationContext(),ChatHeadService.class);
        startService(intent);

        button.setOnClickListener(new Button.OnClickListener(){

            @Override
            public void onClick(View v) {

            }
        });
        
    }
}


RoundedImage.java:
public class RoundedImage extends ImageView{

    private Bitmap figura;
    private int radius;



    public RoundedImage(Context context, Bitmap figura, int radius){
        super(context);

        this.figura=figura;
        this.radius=radius;

        Bitmap bitmap=Bitmap.createBitmap(radius,radius,Bitmap.Config.ARGB_8888);

        Paint paint=new Paint();
        Canvas canvas=new Canvas(bitmap);
        canvas.drawCircle(bitmap.getWidth()/2,bitmap.getHeight()/2,bitmap.getWidth()/2,paint);

        Rect fromRect=new Rect(0,0,figura.getWidth(),figura.getHeight());
        Rect toRect=new Rect(0,0,bitmap.getWidth(),bitmap.getHeight());
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

        canvas.drawBitmap(figura,fromRect,toRect,paint);

        setImageBitmap(bitmap);
    }
}


ChatHeadService.java:
public class ChatHeadService extends Service {

    WindowManager manager;
    WindowManager.LayoutParams params;
    RoundedImage image;

    int initialX,initialY,initialTouchX,initialTouchY;
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate(){
        super.onCreate();
        System.out.println("TEST");
        manager=(WindowManager)getSystemService(WINDOW_SERVICE);

                params=new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT
        );

        params.gravity= Gravity.TOP | Gravity.LEFT;
        params.x=100;
        params.y=100;

        image=new RoundedImage(this,
                BitmapFactory.decodeResource(getResources(),R.drawable.facciadaculo),
                100
        );

        manager.addView(image,params);


        image.setOnTouchListener(new View.OnTouchListener(){

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch(event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        initialX=params.x;
                        initialY=params.y;
                        initialTouchX=(int)event.getRawX();
                        initialTouchY=(int)event.getRawY();
                        return true;
                    case MotionEvent.ACTION_MOVE:
                        params.x=initialX+(int)(event.getRawX()-initialTouchX);
                        params.y=initialY+(int)(event.getRawY()-initialTouchY);
                        manager.updateViewLayout(image,params);
                        return true;
                }

                return false;
            }
        });
    }

}


POST SCRIPTUM: Ho scoperto che tutto questo è valido fino all'API 22.
Con la 23, Marshmallow, è più complicato avere il permesso di caricare un'immagine su WindowManager.

Ecco il codice, comunque:
public class MainActivity extends AppCompatActivity {

    WindowManager.LayoutParams params;
    WindowManager windowManager;
    ImageView imageView;
    Bitmap bitmap;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView=new ImageView(this);

        windowManager=(WindowManager)getSystemService(WINDOW_SERVICE);
        bitmap= BitmapFactory.decodeResource(getResources(),R.drawable.scrofalo);
        imageView.setImageBitmap(bitmap);

        params=new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT
        );
        params.gravity= Gravity.TOP | Gravity.LEFT;

        if(Build.VERSION.SDK_INT>=23) {
            if (!Settings.canDrawOverlays(this)) {
                Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                        Uri.parse("package:" + getPackageName()));
                startActivityForResult(intent,0);

            }
            else{
                windowManager.addView(imageView, params);
            }
        }else {
            windowManager.addView(imageView, params);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data){
        System.out.println("RESULT");

        if(Build.VERSION.SDK_INT>=23){
            if(Settings.canDrawOverlays(this)){
                windowManager.addView(imageView, params);
            }

        }


    }


}

lunedì 15 maggio 2017

Aggiunta di una ImageView rotonda alla finestra

Codice per l'aggiunta di una ImageView contenente una bitmap rotonda alla finestra.

MainActivity:
public class MainActivity extends Activity {


    Button button;
    Button button2;
    Button button3;
    ImageView imageView;
    RelativeLayout mainLayout;



    @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);
        button3=(Button)findViewById(R.id.button3);
        imageView=new ImageView(this);
        mainLayout=(RelativeLayout)findViewById(R.id.activity_main);

        WindowManager windowManager=(WindowManager) getSystemService(WINDOW_SERVICE);

        WindowManager.LayoutParams wParams= new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT
        );

        Bitmap b= BitmapFactory.decodeResource(getResources(),R.drawable.gatto);
        RoundedImage roundedImage=new RoundedImage(this,b,200);

        windowManager.addView(roundedImage,wParams);
    }
}


RoundedImage:
public class RoundedImage extends ImageView{

    private Bitmap figura;
    private int radius;

    public RoundedImage(Context context, Bitmap figura, int radius){
        super(context);

        this.figura=figura;
        this.radius=radius;

        Bitmap bitmap=Bitmap.createBitmap(radius,radius,Bitmap.Config.ARGB_8888);

        Paint paint=new Paint();
        Canvas canvas=new Canvas(bitmap);
        canvas.drawCircle(bitmap.getWidth()/2,bitmap.getHeight()/2,bitmap.getWidth()/2,paint);

        Rect fromRect=new Rect(0,0,figura.getWidth(),figura.getHeight());
        Rect toRect=new Rect(0,0,bitmap.getWidth(),bitmap.getHeight());
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

        canvas.drawBitmap(figura,fromRect,toRect,paint);

        setImageBitmap(bitmap);

    }
}
E accidenti, se funziona!

Immagini rotonde in Android

Ecco il codice:
public class MainActivity extends Activity {


    Button button;
    Button button2;
    Button button3;
    ImageView imageView;
    RelativeLayout mainLayout;



    @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);
        button3=(Button)findViewById(R.id.button3);
        imageView=new ImageView(this);
        mainLayout=(RelativeLayout)findViewById(R.id.activity_main);


        Bitmap bitmap= Bitmap.createBitmap(300,300,Bitmap.Config.ARGB_8888);
        Bitmap immagine= BitmapFactory.decodeResource(getResources(),R.drawable.facciadaculo);

        Paint paint=new Paint();

        paint.setColor(Color.BLUE);
        Canvas canvas=new Canvas(bitmap);

        canvas.drawCircle(bitmap.getWidth()/2,bitmap.getHeight()/2,bitmap.getWidth()/2,paint);

        Rect rect1=new Rect(0,0,426,426);
        Rect rect=new Rect(0,0,bitmap.getWidth(),bitmap.getHeight());


        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
        canvas.drawBitmap(immagine,rect1,rect,paint);

        imageView.setImageBitmap(bitmap);

        mainLayout.addView(imageView);
        imageView.bringToFront();

    }
}
Descriviamo i passaggi ordinatamente, in modo da cercare di memorizzarli.
  • Si crea una nuova bitmap delle dimensioni volute. Però bisogna anche manipolare quella che credo sia la quantità di pixel necessari alla memorizzazione dei colori e dell'alpha, mediante Bitmap.Config.ARGB_8888.
  • Si ottiene una bitmap dall'immagine in risorse da rendere circolare.
Questa la prima parte, la generazione delle bitmaps.
Poi:
  • Si crea il Canvas avente per parametro la bitmap creata ex novo.
  • Si crea il Paint.
Quindi si disegna il cerchio e l'immagine da rendere tonda
  • Si disegna il cerchio.
  • Si predispongono per la bitmap scelta: XferMode, rettangolo di partenza e rettangolo di destinazione.
  • Si disegna la bitmap mettendo i parametri rettangolo di partenza e destinazione.
Provo a rompere il "Mandala" e rifare tutto da capo...

Okay, direi okay...

sabato 8 aprile 2017

Aggiunta ed eliminazione di una libreria aar da un progetto Android

Importazione di una libreria esterna (aar).
Intanto con New -> New Module ho modificato setting.gradle in questo modo:
include ':app', ':mylibrary-release'


e ho visto apparire il modulo mylibrary-release nella directory principale del mio progetto.

Quindi con New -> Import module, importo il modulo mylibrary che ora mi appare anch'esso nella directory.
Quindi devo risistemare il build.gradle di app aggiungendo l'ultima riga:
dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    testCompile 'junit:junit:4.12'
    compile project(":mylibrary")
}
Ora faccio la verifica: in questa libreria c'è una classe chiamata semplicemente Classe. Vedo se viene riconosciuta.
Ma prima devo sincronizzare Gradle!

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Classe classe=new Classe();
        classe.setNumero(123);
        System.out.println(classe.getNumero());

    }
}
Non ho ottenuto messaggi di errore. Ciò significa che la classe è stata riconosciuta.
Ora eseguo:
04-06 21:19:37.172 11679-11679/? I/System.out: 123


Perfetto!
Ora sarà più difficile togliere questa libreria, perché non so se ricordo bene la procedura...

Sono andato su File -> Project Structure e, andando su app, ho eliminato mylibrary.
Come risultato, build.gradle di app si è modificato con la sparizione della riga che avevo aggiunto a dependencies:
dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    testCompile 'junit:junit:4.12'
}
Persiste nel setting.gradle questo:
include ':app', ':mylibrary-release', ':mylibrary'


Nel riquadro a sinistra permangono sia mylibrary sia mylibrary-release.

Torno su Project Structure ed elimino a sinistra sia library sia library-release...

Permangono nel riquadro a sinistra i due moduli, mentre setting.gradle si è modificato così:
include ':app'


Proviamo se il progetto "vuoto" gira normalmente...

Sembra di sì. Sia pure ancora in modo parzialmente empirico, sono riuscito ad eliminare la libreria aggiunta.

mercoledì 5 aprile 2017

Creazione di librerie in Android Studio

Ora provo passo passo a creare una libreria.

File -> New Module -> Android Library
Scelta del nome dell'applicazione e del nome del modulo.

Android Studio elabora...

E' apparsa la cartella mylibrary (nome scelto per il modulo).


Ora devo agire su Gradle.
Apro Settings.Gradle e mi appare questo:
include ':app', ':mylibrary'




Quindi apro build.gradle(Module app).
E mi appare questo:
apply plugin: 'com.android.application'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.3"
    defaultConfig {
        applicationId "com.antonello.laboratoriolibrerie"
        minSdkVersion 18
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    testCompile 'junit:junit:4.12'
}
e vi devo aggiungere la riga:
....

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    testCompile 'junit:junit:4.12'

compile project (":mylibrary")
}
e quindi clicco Sync Now sulla barra di Gradle.
Bene, ora ho una libreria senza libri!
Provo ad eseguire...

Non succede nulla, ovviamente.
Ora provo a istanziare una fantomatica classe...
public class MainActivity extends AppCompatActivity {

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

        classe=new Classe();
    }
}
Ottengo messaggi di errore.

Quindi prendo mylibrary - java - com.antonello.mylibrary e ci aggiungo una classe chiamata Classe con il seguente codice:
public class Classe {
    private int numero;
    
    public void setNumero(int n){
        numero=n;
    }
    
    public int getNumero(){
        return numero;
    }
}
Ora torno su MainActivity e riprovo a istanziare la classe Classe:
public class MainActivity extends AppCompatActivity {
    
    Classe classe;

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

        classe = new Classe();
        classe.setNumero(246);
        System.out.println(classe.getNumero());
    }
}
Non ottengo messaggi di errore.
Eseguo:
04-05 21:59:26.757 9815-9815/? I/System.out: 246



Ecco, dopo vari problemi e distrazioni (mancanza di spazio sull'emulatore, collegamento erroneo del cellulare reale al computer...) alla fine la cosa è riuscita!

sabato 18 febbraio 2017

Esercizio di conversione di indirizzi di memoria in immagini, array di bytes e stringhe.

Ripasso tutte le conversioni di immagini.
  • Uri a Path
  • da Path a Bitmap
  • da Bitmap a byte array (salvabile come blob)
  • da Bitmap a byte array e quindi a stringa (salvabile come stringa e con possibilità di interazione con il database online.

Da Uri a Path:
public class MainActivity extends AppCompatActivity {

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

        imageView=(ImageView)findViewById(R.id.imageView);
        button=(Button)findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {
                Intent intent=new Intent();
                intent.setData(Uri.parse("content://media/external/images/media"));
                intent.setAction(Intent.ACTION_PICK);
                startActivityForResult(intent,0);

            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data){
        if(resultCode==RESULT_OK){
            System.out.println(UriToPath(data.getData()));


        }
    }

    private String UriToPath(Uri uri){
        Cursor crs=getContentResolver().query(uri,null,null,null,null);
        crs.moveToFirst();
        int indice=crs.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
        String s =crs.getString(indice);
        return s;
    }
02-18 23:15:29.203 4670-4670/? I/System.out: /storage/sdcard/DCIM/facciadaculo.jpeg


Da Path a Bitmap:
public class MainActivity extends AppCompatActivity {

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

        imageView=(ImageView)findViewById(R.id.imageView);
        button=(Button)findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {
                Intent intent=new Intent();
                intent.setData(Uri.parse("content://media/external/images/media"));
                intent.setAction(Intent.ACTION_PICK);
                startActivityForResult(intent,0);

            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data){
        if(resultCode==RESULT_OK){
            String s=UriToPath(data.getData());
            Bitmap b=PathToBitmap(s,300);
            imageView.setImageBitmap(b);


        }
    }

    private String UriToPath(Uri uri){
        Cursor crs=getContentResolver().query(uri,null,null,null,null);
        crs.moveToFirst();
        int indice=crs.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
        String s =crs.getString(indice);
        return s;
    }

    private Bitmap PathToBitmap(String path, int dimensioni){
        BitmapFactory.Options opzioni=new BitmapFactory.Options();
        opzioni.inJustDecodeBounds=true;
        BitmapFactory.decodeFile(path);
        int fattore=1;
        while(opzioni.outWidth/fattore>dimensioni && opzioni.outHeight/fattore>dimensioni){
            fattore*=2;
        }
        opzioni.inSampleSize=fattore;
        opzioni.inJustDecodeBounds=false;
        Bitmap bmp=BitmapFactory.decodeFile(path,opzioni);
        return bmp;
    }
}
E funziona anche questa.
Da Bitmap a byte array:
public class MainActivity extends AppCompatActivity {

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

        imageView=(ImageView)findViewById(R.id.imageView);
        button=(Button)findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {
                Intent intent=new Intent();
                intent.setData(Uri.parse("content://media/external/images/media"));
                intent.setAction(Intent.ACTION_PICK);
                startActivityForResult(intent,0);

            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data){
        if(resultCode==RESULT_OK){
            String s=UriToPath(data.getData());
            Bitmap b=PathToBitmap(s,300);
            byte[] bt=BitmapToByteArray(b);
            System.out.println(bt);


        }
    }

    private String UriToPath(Uri uri){
        Cursor crs=getContentResolver().query(uri,null,null,null,null);
        crs.moveToFirst();
        int indice=crs.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
        String s =crs.getString(indice);
        return s;
    }

    private Bitmap PathToBitmap(String path, int dimensioni){
        BitmapFactory.Options opzioni=new BitmapFactory.Options();
        opzioni.inJustDecodeBounds=true;
        BitmapFactory.decodeFile(path);
        int fattore=1;
        while(opzioni.outWidth/fattore>dimensioni && opzioni.outHeight/fattore>dimensioni){
            fattore*=2;
        }
        opzioni.inSampleSize=fattore;
        opzioni.inJustDecodeBounds=false;
        Bitmap bmp=BitmapFactory.decodeFile(path,opzioni);
        return bmp;
    }

    private byte[] BitmapToByteArray(Bitmap bmp){
        ByteArrayOutputStream stream=new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.JPEG,80,stream);
        byte[] b=stream.toByteArray();
        return b;
    }


}
02-18 23:25:30.707 4855-4855/? I/System.out: [B@1a6afe00

(questa non la capisco... forse si tratta perlopiù di numeri non traducibili in caratteri)
Da bitmap a stringa:
public class MainActivity extends AppCompatActivity {

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

        imageView=(ImageView)findViewById(R.id.imageView);
        button=(Button)findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener(){

            @Override
            public void onClick(View v) {
                Intent intent=new Intent();
                intent.setData(Uri.parse("content://media/external/images/media"));
                intent.setAction(Intent.ACTION_PICK);
                startActivityForResult(intent,0);

            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data){
        if(resultCode==RESULT_OK){
            String s=UriToPath(data.getData());
            Bitmap b=PathToBitmap(s,300);
            String stringa=BitmapToString(b);
            System.out.println(stringa);


        }
    }

    private String UriToPath(Uri uri){
        Cursor crs=getContentResolver().query(uri,null,null,null,null);
        crs.moveToFirst();
        int indice=crs.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
        String s =crs.getString(indice);
        return s;
    }

    private Bitmap PathToBitmap(String path, int dimensioni){
        BitmapFactory.Options opzioni=new BitmapFactory.Options();
        opzioni.inJustDecodeBounds=true;
        BitmapFactory.decodeFile(path);
        int fattore=1;
        while(opzioni.outWidth/fattore>dimensioni && opzioni.outHeight/fattore>dimensioni){
            fattore*=2;
        }
        opzioni.inSampleSize=fattore;
        opzioni.inJustDecodeBounds=false;
        Bitmap bmp=BitmapFactory.decodeFile(path,opzioni);
        return bmp;
    }

    private byte[] BitmapToByteArray(Bitmap bmp){
        ByteArrayOutputStream stream=new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.JPEG,80,stream);
        byte[] b=stream.toByteArray();
        return b;
    }
    private String BitmapToString(Bitmap bmp){
        ByteArrayOutputStream stream=new ByteArrayOutputStream();
        bmp.compress(Bitmap.CompressFormat.JPEG,80,stream);
        byte[] b=stream.toByteArray();
        String s= Base64.encodeToString(b,Base64.DEFAULT);
        return s;
    }


}
02-18 23:30:24.629 4970-4970/? I/System.out: /9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcU
02-18 23:30:24.629 4970-4970/? I/System.out: FhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/2wBDAQcHBwoIChMKChMoGhYaKCgoKCgo
02-18 23:30:24.629 4970-4970/? I/System.out: KCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCj/wAARCAFAAUADASIA
02-18 23:30:24.629 4970-4970/? I/System.out: AhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQA
02-18 23:30:24.629 4970-4970/? I/System.out: AAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3

.....

...che sarebbe una minima parte della stringa che rappresenterebbe la mia faccia.

giovedì 19 gennaio 2017

Salvataggio di date come Long in un database e rilevarne valori minimo e massimo.

Se io devo impostare una data, cosa mi conviene, usare Date o Calendar?
E come si fa?

Prima modalità:
        Date data1=new Date("5/09/1961");
        Date data2=new Date("13/06/1962");
        System.out.println(data1);
Ottengo:
01-19 00:48:04.397 28832-28832/? I/System.out: Tue May 09 00:00:00 GMT+00:00 1961
In questo modo (deprecato) bisogna ordinare mese e giorno secondo la notazione anglosassone, però.

Un'altra modalità sarebbe convertire la stringa in Date:
        Date data1=new Date();
        String strDat="5/9/1961";
        SimpleDateFormat sdf=new SimpleDateFormat("dd/MM/yyyy");
        try {
            data1=sdf.parse(strDat);
            System.out.println(data1);
        } catch (ParseException e) {
            e.printStackTrace();
        }
01-19 00:58:48.387 31082-31082/? I/System.out: Tue Sep 05 00:00:00 GMT+00:00 1961
Queste modalità creano un tipo Date (ovviamente contenente una data) a partire da una data specifica, espressa come stringa.


Per riportare il tipo Date a stringa, si usa sempre SimpleDateFormat con l'istruzione format.

Ora metto diverse date in ordine sparso nel database e poi le ordino con ORDER BY.
Queste sono le date ordinate, ottenute creando tipi Date con la stringa della data come parametro nel costruttore, i quali vengono memorizzati mediante la funzione Date.getTime().
Vengono ripresi dal database creando un Date avente nel costruttore il Long.
        Date data1=new Date("09/05/1961");
        Date data2=new Date("01/10/2003");
        Date data3=new Date("06/13/1962");

        helper.save(data1.getTime());
        helper.save(data2.getTime());
        helper.save(data3.getTime());
,,,

            public void onClick(View v) {
                Cursor crs=helper.query();
                do {
                    System.out.println(new Date(crs.getLong(crs.getColumnIndex("millidat"))));
                }while(crs.moveToNext());
            }
Ora invece di Date uso Calendar:
        Calendar data1=Calendar.getInstance();
        data1.set(Calendar.YEAR,1961);
        data1.set(Calendar.MONTH,8);
        data1.set(Calendar.DAY_OF_MONTH,5);
        
Questo porta via molto tempo e codice: c'è un modo più facile di creare un Calendar impostando una data?
Sì, c'è:
        Calendar cal1=Calendar.getInstance();
        Calendar cal2=Calendar.getInstance();
        Calendar cal3=Calendar.getInstance();
        cal1.set(1961,8,5);
        cal2.set(2003,0,10);
        cal3.set(1962,5,13);

        helper.save(cal1.getTimeInMillis());
        helper.save(cal2.getTimeInMillis());
        helper.save(cal3.getTimeInMillis());

Salvati i dati nel database, ho trovato come estrapolarne il minimo e il massimo:
    public Cursor query(){
        SQLiteDatabase db=this.getWritableDatabase();
        Cursor c=db.rawQuery("select min(millidat) as millidat from tabella",null);
        c.moveToFirst();
        return c;
    }
    public Cursor query(){
        SQLiteDatabase db=this.getWritableDatabase();
        Cursor c=db.rawQuery("select max(millidat) as millidat from tabella",null);
        c.moveToFirst();
        return c;
    }

CalendarPickerView: parametri di init e range.

Questo datepicker prende due parametri di data.
Nominiamoli "primadata" e "secondadata" o qualcosa di simile.
Ora faccio che primadata è oggi, e secondadata è pure oggi.
Metto da parte il codice per l'evento di selezione delle date sul datePicker.
        pickerView.setOnDateSelectedListener(new CalendarPickerView.OnDateSelectedListener() {

            @Override
            public void onDateSelected(Date date) {
                ArrayList range = (ArrayList) pickerView.getSelectedDates();
            }

            @Override
            public void onDateUnselected(Date date) {

            }

        });


Ora cancello e procedo...
public class MainActivity extends AppCompatActivity {

    Calendar primaData;
    Calendar secondaData;


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

        pickerView = (CalendarPickerView) findViewById(R.id.calendar_view);

        primaData = Calendar.getInstance();
        secondaData=Calendar.getInstance();



        pickerView.init(primaData.getTime(), secondaData.getTime())
                .withSelectedDate(primaData.getTime())
                .inMode(CalendarPickerView.SelectionMode.RANGE);
    }
}
Errore perché la data selezionata deve essere fra la prima e l'ultima.
Provo ad aumentare la seconda di un giorno, ma non so come si fa.
Fatto, ora me l'accetta.
Ecco, quindi i due parametri di init definiscono il periodo in cui si può selezionare il range.
withSelectedDate esprime la data selezionata di base, che può anche mancare.

martedì 17 gennaio 2017

Regole per il parsing di y in SimpleDateFormat

Ho trovato un costruttore di SimpleDateFormat che non ha parametri. Forse per il parse, ossia la conversione di una stringa in tipo Date, è sufficiente questo costruttore. Sperimentiamo...

No.
E' necessario però imparare le regole, e ce ne sono sia per il parsing sia per il formatting.
PARSING: REGOLE PER YEAR:
Se le y sono fino a 2, l'anno viene interpretato come troncato delle prime due cifre: 61 viene inteso come '61 ovvero 1961;
Se le y sono più di 2, l'anno viene interpretato in senso letterale: 61 viene inteso come 61 dopo Cristo.
        String strData="5/9/61";
        Date dat;
        SimpleDateFormat sdf=new SimpleDateFormat("d/M/y");
        try {
            dat=sdf.parse(strData);
            System.out.println(dat);
        } catch (ParseException e) {
            System.out.println("errore");
        }
01-17 17:20:49.099 5729-5729/? I/System.out: Tue Sep 05 00:00:00 GMT+00:00 1961


        String strData="5/9/61";
        Date dat;
        SimpleDateFormat sdf=new SimpleDateFormat("d/M/yy");
        try {
            dat=sdf.parse(strData);
            System.out.println(dat);
        } catch (ParseException e) {
            System.out.println("errore");
        }
01-17 17:21:57.209 5812-5812/? I/System.out: Tue Sep 05 00:00:00 GMT+00:00 1961


        String strData="5/9/61";
        Date dat;
        SimpleDateFormat sdf=new SimpleDateFormat("d/M/yyy");
        try {
            dat=sdf.parse(strData);
            System.out.println(dat);
        } catch (ParseException e) {
            System.out.println("errore");
        }
01-17 17:38:03.107 5937-5937/? I/System.out: Sat Sep 05 00:00:00 GMT+00:00 61

Ripasso Date e SimpleDateFormat

Studio del Calendar.
Mi ricordo che avevo già avuto a che fare con le date e il Calendar. Vediamo di ritrovare i miei appunti. In fondo è per questo, fra l'altro, che tengo un blog.

Link di riferimento
La base di tutto è il SimpleDateFormat.
Se ricordo bene, si crea una variabile di tipo SimpleDateFormat, che si istanzia come?
Semplicemente con new SimpleDateFormat avente per parametro una stringa con il formato in formato stringa.
Ci proviamo.

Scrivo una data in formato stringa, quindi creo un SimpleDateFormat, quindi vedrò come convertirlo in oggetto tipo Date.
        String strData="5/9/1961";
        
        SimpleDateFormat sdf=new SimpleDateFormat("dd/MM/yyyy");
Si converte con il metodo parse di SimpleDateFormat.
        String strData="5/9/1961";

        SimpleDateFormat sdf=new SimpleDateFormat("dd/MM/yyyy");

        try {
            Date dat=sdf.parse(strData);
            System.out.println(dat);
        } catch (ParseException e) {
            e.printStackTrace();
        }
E così funziona:
01-17 16:45:44.392 4692-4692/? I/System.out: Tue Sep 05 00:00:00 GMT+00:00 1961
Quindi è parse. Ho qualche perplessità sul parametro di SimpleDateFormat, che vedrò dopo per evitare di impelagarmi.
Vediamo l'operazione inversa, che si dovrebbe fare con format.
Mi predispongo un tipo Date ben individuato. Quindi lo converto in stringa mediante format.
        Date dat=new Date();
        String strDate;

        SimpleDateFormat sdf=new SimpleDateFormat("dd/MM/yyyy");
        strDate=sdf.format(dat);
        System.out.println(strDate);
E funziona:
01-17 16:57:59.640 4841-4841/? I/System.out: 17/01/2017