03 - Anatomia di un'applicazione Android(TM)

Copyright (C) 2013 - Alca Società Cooperativa

Anatomia di un'applicazione Android(TM)

PON2013 @ IISS E.Medi - Galatone
http://learn.alcacoop.it/2013/android
Copyright (C) 2013 - ALCA Società Cooperativa

SOMMARIO

Il formato apk

Android Manifest

Informazioni principali di un Manifest

Struttura Manifest

    <?xml version="1.0" encoding="utf-8"?>
    <manifest package="it.alcacoop.backgammon">
­
        <uses-sdk android:minSdkVersion="5"
          android:targetSdkVersion="17" />
­
        <application>
            <activity>
            </activity>
        </application>
­
    </manifest>

Creare un progetto Android via CLI

Creare un progetto Android via CLI

android create project \
  --target <target_ID> \
  --name <your_project_name> \
  --path path/to/your/project \
  --activity <your_activity_name> \
  --package <your_package_namespace>

Anatomia di un progetto Android

La root directory...

AndroidManifest.xml
bin
gen
proguard.cfg
project.properties
res
src

Anatomia di un progetto Android (2)

La directory res...

drawable-hdpi
drawable-ldpi
drawable-mdpi
layout
raw
values

Build e installazione (CLI)

Gestione dei permessi

Es.: Accesso ai servizi di rete

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

Es.: Accesso ai servizi di rete

private boolean isNetworkAvailable() {
­
  ConnectivityManager connectivityManager =
    getSystemService(Context.CONNECTIVITY_SERVICE);
­
  NetworkInfo activeNetworkInfo = 
    connectivityManager.getActiveNetworkInfo();
­
  return activeNetworkInfo != null;
}

Modello di sicurezza

Obiettivi:

Android fornisce un robusto modello di sicurezza, caratterizzato da diversi livelli di implementazione e granularità a livello applicativo

Modello di sicurezza

API Protetta

Ricapitolando...

Application components

Tutte le applicazioni Android sono strutturate come composizione di una o più tra queste componenti:

Activities

Activities

Activities

<application>
  <activity android:name=".ExampleActivity"/>
  <activity android:name=".ExampleActivity2"/>
  ...
</application

Activities

<intent-filter>
  <action android:name="android.intent.action.MAIN"/>
  <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>

Task e gestione del Back Stack

Task e gestione del Back Stack

Task e gestione del Back Stack

Services

Content Providers

Broadcast Receivers

Activity lifecycle

Activity Lifecycle Methods
Method Description Killable Next
onCreate() Called when activity first created No onStart()
onRestart() Called after activity stopped, prior to restarting No onStart()
onStart() Called when activity is becoming visible to user No onResume()/onStop()
onResume() Called when activity starts interacting with user No onPause()
onPause() Called when a previous activity is about to resume Yes onResume()/onStop()
onStop() Called when activity no longer visible to user Yes onRestart()/onDestroy()
onDestroy() Final call received before activity is destroyed Yes Nothing

Lifecycle Example

Reimplementiamo tutti gli hook che gestiscono il ciclo di vita di una activity con delle semplici print (Log.*)...

Lifecycle Example

@Override
public void onCreate(Bundle savedInstanceState)
{
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  Log.e("LIFECYCLE", "CREATE!!!");
}
@Override
public void onRestart() {
  super.onRestart();
  Log.e("LIFECYCLE", "RESTART!!!");
}
...

Lifecycle Example

adb shell     #apre una shell sul dispositivo
ps            #mostra la lista dei processi attivi

Android Native UI

Android Native UI

Android Native UI

Android Native UI

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
}

Vantaggi dell'approccio XML

Es: Aggiungiamo un bottone!

<Button
    android:id="@+id/create_dialog"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Open Dialog!" />

Nota: è sempre necessario assegnare un ID ai compenenti che si aggiungono, attraverso il quale sarà possibile referenziare l'oggetto nel codice Java

Es. Click listeners

final Button button = 
  (Button) findViewById(R.id.create_dialog);
­
button.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
    //DO SOMETHING
  }   
});

Es.: Aprire una Dialog

private AlertDialog dialog;
­
public void createDialog() {
  AlertDialog.Builder builder = 
    new AlertDialog.Builder(this);
­
  builder.setMessage("HELLO!")
    .setTitle("TEST DIALOG")
    .setPositiveButton("OK", null);
­
  dialog = builder.create();
}

Put them all together..

onCreate() {
  setContentView...
  createDialog...
­
  button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
      dialog.show();
    }   
  }); 
}

Resources

Resources

Resources

Resources

Android App Localization

Android App Localization

Layout:

<TextView
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="@string/hello_world"

Android App Localization

string.xml

<resources>
  <string name="hello_world">
    Hello World from MainActivity
  </string>
</resources>

Android App Localization

Accedere programmaticamente ad una stringa:

(String)getResources().getText(R.string.hello_world)

Far collaborare applicazioni Android

Far collaborare applicazioni Android

Far collaborare applicazioni Android

Risoluzione delle Intent

Risoluzione di Intent espliciti

L'istanza della classe Intent contiene la classe del componente da eseguire:

/** Creazione di una Intent esplicita
*
* param Context   Application Context
* param Class     Component Class
*/
Intent myIntent = new Intent(this, MainActivity.class);

Risoluzione di Intent implicite

Intent myIntent = new Intent(
  Intent.ACTION_VIEW,
  Uri.parse("http://google.it")
);

Risoluzione di Intent implicite

Risoluzione di Intent implicite

Intent delivery

Intent filtering

<intent-filter>
  <action android:name="android.intent.action.MAIN"/>
  <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>

Es. YouTube WatchActivity

<intent-filter>
  <action android:name="android.intent.action.VIEW"/>
  <category android:name="android.intent.category.DEFAULT"/>
  <category android:name="android.intent.category.BROWSABLE"/>
  <data android:scheme="http"/>
  <data android:scheme="https"/>
  <data android:host="youtube.com"/>
  <data android:host="www.youtube.com"/>
  <data android:host="m.youtube.com"/>
  <data android:pathPrefix="/watch"/>
  <data android:pathPrefix="/v/"/>
  <data android:pathPrefix="/e/"/>
  <data android:pathPrefix="/embed/"/>
</intent-filter>

Intent example

<Button
  android:id="@+id/open_google"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="Send Intent!"
  android:onClick="sendIntent"/>

Intent example

public void sendIntent(View view) {
  Intent myIntent = new Intent(
    Intent.ACTION_VIEW, 
    Uri.parse("http://google.it")
  );
  startActivity(myIntent);
}

Richiami sul Threading model Java

Richiami sul Threading model Java

Richiami sul Threading model Java

Thread vs Runnable

class MyThread extends Thread {
  public void run() {
    //LOGICA DI ESECUZIONE
  }
}
­
MyThread myThread = new MyThread();
myThread.start(); //LANCIA IL THREAD

Thread vs Runnable

Thread vs Runnable

Thread(Runnable r)

Thread vs Runnable

class MyRunnable implements Runnable {
  public void run() {
    //LOGICA DI ESECUZIONE
  }
}
­
MyRunnable r = new MyRunnable();
Thread myThread = new Thread(r);
myThread.start(); //LANCIA IL THREAD

Thread in Android

Thread in Android

ANR Error

ANR Error

ANR Error

//LONG TASK
public void longTask() {
  File root = Environment.getExternalStorageDirectory();
  File file = new File(root, "test.txt");
  try {
    if (root.canWrite()){
      FileWriter filewriter = new FileWriter(file);
      BufferedWriter out = new BufferedWriter(filewriter);
      for (int i=0; i<1000000; i++) out.write(i);
      out.close();
    }
  } catch (IOException e) {}
}

Se eseguito su UIThread genera ANR!

button.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
    longTask();
    dialog.show();        
  }
});

Soluzione con errore

public void onClick(View v) {
  Thread t = new Thread() {
    @Override
    public void run() {
      longTask();
      dialog.show();
    }
  };
  t.start();          
}

Soluzione corretta

public void onClick(View v) {
  Thread t = new Thread() {
    @Override
    public void run() {
      longTask();
      runOnUiThread(new Runnable() {
        @Override
        public void run() {
          dialog.show();        
        }
      });
    }
  };
  t.start();          
}

Link reference

Next week