Sunteți pe pagina 1din 602

Dispozitive și Aplicații Mobile

Cursul 1
Prezentare disciplină
• Obiective
• Elemente de conținut
• Modalitatea de evaluare
Obiective
• Utilizarea eficientă a tehnologiilor mobile în
cadrul societății informaționale actuale
• Asimilarea conceptelor specifice dezvoltării
aplicațiilor destinate dispozitivelor mobile
• Însușirea modelului de programare pentru
platforma Android
• Dezvoltarea capacității studenților de rezolvare a
problemelor practice prin dezvoltarea de aplicații
eficiente pentru platforma Android
Elemente de conținut
• Introducere:
– Dispozitive mobile (DM)
– Sisteme de operare pentru DM
– Aplicații mobile
• Programarea aplicațiilor Android
– Instrumente de dezvoltare
– Interfața utilizator
– Accesul la rețea
– Stocarea persistentă a datelor
– Grafică bidimensională
– Introducere servicii, furnizori de conținut și receptori de mesaje
– Utilizarea Google Maps în aplicații
– Publicarea aplicațiilor în magazinul virtual
Sumar
• Dispozitive mobile
• Modelul de programare Android
• Instrumente de dezvoltare
• Structura aplicațiilor Android; componente
• Structura unui proiect
• Activități
Dispozitive mobile (DM)

• Telefoane mobile
• Smartphone-uri
• Tablete
– cu/fără suport telefonie
• PDA
– fără suport telefonie
• Dispozitive portabile (wearable)
– cu/fără suport telefonie
DM Limitări (vs. PC)

• Autonomie (baterie)
• Fragmentare
• Bandă de transfer
– acoperirea
• Modalități de interacțiune
• Dimensiuni
– ecran
• Putere de calcul
• Memorie (RAM şi ROM)
Dispozitive mobile

System on a
Chip (SoC)
Memorie Memorie Sursă
Flash RAM tensiune

Procesor Ecran
Grafic
(GPU)

Procesor Procesor
comunicaţii aplicaţii

SIM
Alte
Audio
dispozitive de I/O
Dispozitive mobile
Conector Procesor
SIM

Camera

Conector
cartelă
memorie
Ecran

Difuzor
Motor
vibrații
Placa de bază
(față/verso)
Dispozitive mobile
Sisteme de operare
• Sisteme de operare proprii
• Sisteme de operare
smartphones/tablete/portabile
– Posibilitatea dezvoltării de aplicații pe baza unui
SDK
Sisteme de operare
• Android (Google)
• Tizen (Tizen Association)
• iOS (Apple)
• Linux Mobile
• Windows 10 Mobile/Windows
Phone/Windows CE/Windows Mobile
(Microsoft)
Aplicații mobile
• Aplicații destinate dispozitivelor mobile
• Implementare
– Aplicații Native
– Aplicații Hibride
• Cod binar interpretabil sau compilat JIT
• Utilizează un nivel intermediar
– Aplicații Web mobile
• Cu/fără acces la rețea
ANDROID
Android

• Open Handset Alliance


• Proiect inițiat de Google
• Nucleul Linux 2.6.x/3.x
• Aplicații bazate pe Java/Kotlin
• Disponibilitate
– Telefoane mobile
– Tablete
– Dispozitive portabile
– Televizoare/STB
– Auto
Smartphone (2008-2011)
Altii
iPhone iPhone
3.30%
OS Altii OS
2.77% 3.40% 13.70%
BlackBerry Symbian
17.36% 50.30%

Windows Symbian
Mobile 57.12% BlackBerr
12.02% Linux y Windows Android
7.32% 20.90% Mobile 2.80%
9.00%
iPhone
OS
16.01%
BlackBer Altii Windows, Bada, 2.2 Altii, 0.9 Symbian,
2.96% 16.9
RIM, 11 1.5
ry Symbian
14.43% 30.63%

iOS, 15

Windows
Mobile
3.06%
Android
32.91%
Android,
52.5

Sursa: Canalys/Gartner
Smartphone 2012/13/15/16+

Symbian Altii Windows Windows Altii, 1.2


3% 2% Phone/ Phone, 4
BlackBerry iOS, 18
Windows
4%
iOS Mobile
19% 3%

Android
69% Android,
Altii, 0.3 77
Windows Phone, 1.2
iOS, 18.6 iOS, 11.7 Windows Phone, 0.4 Altii, 0.3

Android,
79.6
Android, 87.6

http://ctstech.net/blog/2013/02/14/idcs-smartphone-stats-for-4q-2012-and-a-review-of-their-mobile-os-share-prediction-for-2015/
http://gadgets.ndtv.com/mobiles/news/windows-phone-grows-104-percent-year-over-year-in-q4-2013-abi-research-478672
http://www.idc.com/prodserv/smartphone-os-market-share.jsp
De ce Android?

• Numărul mare de instalări existente


• Limbajul Java
• Posibilitatea de testare a aplicațiilor direct pe telefonul mobil
• Varietatea dispozitivelor mobile
• Costuri mai mici pentru dezvoltatori
• Magazinul virtual Google Play
ANDROID: MODELUL DE
PROGRAMARE
Modelul de programare
• Nucleul Linux
– Biblioteci native C
• Limbaje de programare
– Java, Kotlin
– C/C++ (interfața de programare nativă)
• Mașină virtuală proprie
Medii de execuție
• ART – Android RunTime
– Mediul de execuție curent al aplicațiilor Android
• Începând cu Android 4.4
– Compilare înainte de execuție
• Mașină virtuală proprie (Dalvik VM)
– Cod binar executabil incompatibil Java SE
• Fișiere dex
– Fiecare aplicație rulează într-un proces separat
– Compilarea JIT
Facilități de programare
• Interfața utilizator • Rețea și comunicații
• Baze de date – Socket
– SQLite – HTTP
• Media API – Bluetooth
– Audio – NFC
– Video • Telefonie
• Camera • Senzori
• Grafică 2D, Animație – GPS
– Accelerometru
• Grafică 3D (OpenGL)
– Giroscop
• Informații personale – Busolă
INSTRUMENTE DE DEZVOLTARE
Instrumente de dezvoltare
• Java SE Development Kit (JDK)
• Android SDK
• Mediu de dezvoltare integrat (IDE)
Medii de dezvoltare integrate
• Android Studio
– Furnizat de Google
• Eclipse
– plugin: Android Development Toolkit (ADT)
– fără suport oficial
• IntelliJ IDEA
Instrumente de dezvoltare
• Visual Studio + Xamarin
• Dezvoltare
– Multiplatformă
– Nativă
• Limbaje de programare
– C#
– F#
• Bazat pe biblioteci .Net (Mono) și SDK nativ
(Android, iOS etc.)
Dezvoltare multiplatformă
• Apache Cordova
– Adobe PhoneGap
– Ionic
• Appcelerator Titanium
• React Native
• NativeScript
• Xamarin
API Android

Versiuni și nume de cod Nivel API

Android 2.2 (Froyo) 8

Android 2.3.3 – 2.3.7 (Gingerbread) 10


Android 3.x (Honeycomb) 11-13 (tablete)
Android 4.0.x (Ice Cream Sandwich) 14, 15

Android 4.1, 4.2, 4.3 (Jelly Bean) 16, 17, 18


API Android

Versiuni și nume de cod Nivel API


Android 4.4, 4.4W (KitKat) 19, 20
Android 5.0, 5.1.x (Lollipop) 21, 22
Android 6.0 (Marshmallow) 23
Android 7.0, 7.1 (Nougat) 24, 25
Android 8.0, 8.1 (Oreo) 26, 27
Android 9.0 (Pie) 28
Distribuție versiuni Android
0.30% 0.30% 3.20% Gingerbread (API 10)
7.80%
19.20% ICS (API 15)

Jelly Bean (API 16, 17 și 18)


18.30%
KitKat (API 19)

Lollipop (API 21 si 22)

Marshmallow (API 23)


29.30%
Nougat (API 24 și 25)

21.60% Oreo (API 26 și 27)

Sursa: https://developer.android.com/about/dashboards/index.html
Ultima actualizare: 28 Septembrie 2018
Android SDK
• Biblioteci și resurse specifice fiecărei
platforme Android
• Resurse și imagini emulatoare
• Instrumente pentru compilare și generarea
conținutului binar executabil
– Cod sursă
– Resurse
Android SDK
• Build-tools
– Director: sdk/build-tools/versiune/
– Instrumente
• aapt – compilare resurse, generarea fișierului R.java, fișiere APK
• dx - conversie cod binar Java la cod binar Dalvik
• Platform-tools
– Specifice fiecărei platforme
– Director: sdk/platform-tools
– Instrumente:
• adb – comunicarea cu dispozitivele Android
• sqlite3
• SDK Tools
– Independente de platformă
– Subdirector: sdk/tools
– Instrumente:
• script-uri ant pentru obținerea pachetului binar al aplicației
• monitor(ddms)
• emulator-arm, emulator-x86
Android SDK Manager
• Gestiunea platformelor și a instrumentelor
necesare
• Acces direct sau din mediul de dezvoltare
• Platforma
– Biblioteci
– Cod sursă
– Documentație
– Imagini emulator
Android SDK Manager
Android Virtual Device (AVD)
• Dispozitive virtuale Android
– Emulatoare
• Caracteristici
– Procesor (ARM, x86_x64)
– Ecran (rezoluție ,dimensiune)
– Memorie (RAM, internă persistentă, externă),
– Versiune API
– Camere
• Comunicare prin aplicația adb.exe
Emulatoare
• Emulare
– ARM
– X86, x64
• Necesită Intel HAXM și procesor cu suport virtualizare
• API
– Standard
– Google API
– Google Play
Android Debug Bridge (ADB)
• Asigură comunicarea între mașina de
dezvoltare și dispozitivele Android (reale sau
virtuale)
• Componente
– Client
• Permite transmiterea de comenzi
– Server
• Mașina de dezvoltare
• Dispozitivul Android
Exemple de comenzi
• adb devices
• adb kill-server
• adb install
• adb pull
• adb push
• adb shell
AVD Manager
• Dispozitive virtuale
– Definire
– Modificare
– Ștergere
• Accesat direct sau din mediul integrat de
dezvoltare
• Pot fi definite oricîte dispozitive virtuale
– Se va alege unul la lansarea în execuție a aplicației
AVD Manager
AVD Manager
Consola de mesaje (LogCat)
• Afișează mesaje transmise din aplicații
– Utilizator
– Sistem
• Mesaje
– Avertizare (w)
– Depanare (d)
– Eroare (e)
– Informare (i)
– Informare detaliată (v)
– Eroare excepțională (wtf)
Consola de mesaje (LogCat)
Consola de mesaje (LogCat)
• Clasa android.util.Log
• Metode statice asociate tipurilor de mesaje:
– e(), w(), i(), d(), v(), wtf()
• Parametri:
– Identificator sursă mesaj (String)
• Numele clasei, aplicației, activității etc.
• Posibilitatea de filtrare
– Mesajul care va fi afișat (String)
• Metoda statică generală
– println()
– În plus, primul parametru include tipul mesajului
• Log.ASSERT, Log.ERROR, Log.INFO etc.
Consola de mesaje (LogCat)
• Log.i("Activitate1", "Mesaj de informare");
• Log.println(Log.ASSERT, "Activitate 1",
"Aserțiune invalida!");
STRUCTURA APLICAȚIILOR
ANDROID
Structura aplicațiilor Android
• Includ una sau mai multe componente
• Componentele sînt înregistrate de sistem
– Pot fi și componente locale
• Componentele pot fi activate
– Local, în cadrul aplicației
– Global, la nivelul sistemului
Componente de bază ale aplicațiilor
Android
• Activități
– clasa de bază android.app.Activity
• Servicii
– clasa de bază android.app.Service
• Furnizori de conținut
– clasa de bază android.content.ContentProvider
• Receptori de mesaje
– clasa de bază android.content.BroadcastReceiver
– mesaje
• clasa de bază android.content.Intent
Activități
• Asociate ferestrelor aplicației
• O aplicație poate avea una sau mai multe
activități
– O singură activitate principală
• Componente vizuale asociate
• Derivate din clasa View
Activități
Servicii
• Rutine care rulează în paralel cu firul principal
• Nu prezintă interfață grafică
• Permit derularea unor acțiuni în fundal fără a
bloca:
– firul principal de execuție
– Interacțiunea cu aplicațiile
Furnizori de conținut
• Suport pentru partajarea datelor între aplicații
• Datele partajate sunt stocate în diferite surse
de date (fișiere, baze de date etc.)
• Pun la dispoziție o modalitatea standard
pentru accesul la date și actualizarea acestora
• Accesul se realizează printr-un URI de forma
content://
Mesaje (obiecte de tip Intent)
• Pentru activarea componentelor se utilizează
mesaje asincrone
– încapsulate în obiecte de tip Intent
• Invocare componente
– Deschidere navigator, inițiere aplicație apeluri
telefonice, afișarea hărții la o anumită poziție
geografică etc.
• Comunicare între componente
Recepționarea evenimentelor
• Aplicațiile pot reacționa la apariția unor
evenimente la nivelul sistemului prin utilizarea
claselor derivate din BroadcastReceiver
– Apel telefonic, modificarea nivelului bateriei,
recepționarea unui mesaj, mesaje transmise de alte
aplicații etc.
• Nu prezintă interfață grafică
• O aplicație poate include mai multe componente
pentru recepționarea de evenimente
STRUCTURA PROIECTELOR
ANDROID
Aplicații Android cu interfață grafică
• Includ una sau mai multe activități
• Fiecare activitate are asociată o componentă
vizuală părinte
– Definită procedural, în fișiere XML
– Definită în cod
• Includ resurse:
– Asociate interfeței utilizator
– Fișiere prelucrate în cadrul aplicației
Structura unui proiect Android Studio
• Proiecte și module
• Proiect
– Include unul sau mai multe module
• Modul
– Fișiere sursă, resurse, fișiere de configurare
– Permit împărțirea proiectului în module
funcționale
– Dependențe între module
– Utilizare: biblioteci, tipuri de dispozitive etc.
Structura unui proiect Android Studio
• Fișiere sursă (src)
– Fișiere sursă Java (java)
– Resurse (res)
• drawable
• layout
• menu
• mipmap
• raw
• values
• xml
• Resurse preluate ca fluxuri de date (assets)
• Fișier de configurare (AndroidManifest.xml)
• Proprietățile sistemul de compilare (proiect și modul)
– build.gradle
• Fișiere generate (gen)
– R.java
AndroidManifest.xml
• Componentele aplicației
– declarare activități, servicii, furnizori de conținut,
receptori de mesaje
– denumirile claselor asociate
– Proprietăți
• Versiunile SDK (minim, maxim, dorită)
– Preluate de fișierul build.gradle
• Informații pachet (denumire, versiune)
• Atribute aplicație (denumire, pictograma
asociată, tema, opțiuni memorie, restricții,
permisiuni etc.)
AndroidManifest.xml
• Filtrele de mesaje
– definite în cadrul aplicației/componentelor
• Permisiunile de acces
– <uses-permission android:name="permisiune"/>
• Cerințe hardware și software
– <uses-feature android:name="cerință"
android:required="true/false"/>
Exemple de permisiuni
Pentru … este necesară permisiunea
android.permission. …
acces la Internet/rețea INTERNET
scriere și citire date de contact READ_CONTACTS, WRITE_CONTACTS
scriere și citire în Calendar READ_CALENDAR, WRITE_CALENDAR
trimitere SMS-uri, scriere şi citire SEND_SMS, READ_SMS, WRITE_SMS
SMS-uri
utilizarea telefoniei CALL_PHONE
accesare mediu extern de stocare READ_EXTERNAL_STORAGE,
WRITE_EXTERNAL_STORAGE
identificare poziţie geografică ACCESS_FINE_LOCATION,
ACCESS_COARSE_LOCATION
Permisiuni
• API 23 (Marshmallow)
• Normale
– Accesul este acordat automat
– Exemple: Internet, Bluetooth, NFC, Vibrații etc.
• Cu risc/Periculoase
– Accesul este acordat individual de către utilizator
– Aplicațiile controlează accesul la execuție
– Exemple: Calendar, Camera, Contacts, SMS,
Location, Phone, Storage etc.
Cerințe hardware și software pentru
dispozitive
• android.hardware.camera
• android.hardware.camera.autofocus
• android.hardware.camera.flash
• android.hardware.nfc
• android.hardware.sensor.gyroscope
• android.hardware.Bluetooth
• android.software.live_wallpaper
• android.software.home_screen
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ase.pdm.sem1" android:versionCode="1" android:versionName="1.0" >
<uses-permission android:name="android.permission.INTERNET"/>
<application android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity> ... </activity>
<service>...</service>
<provider>...</provider>
<receiver>...</receiver>
</application>
</manifest>
build.gradle
android {
compileSdkVersion 24
buildToolsVersion "24.0.4"

defaultConfig {
applicationId "ro.ase.pdm.myapplication"
minSdkVersion 16
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
}

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.android.support:design:23.0.1'
}
Fișierele binare Android
• Extensia apk (Android Package)
• Conțin codul binar și resursele
• Resursele pot fi compilate sau nu
• Pe lîngă resurse poate fi adăugat orice tip de
fișier
Fișierele binare Android

.java .class .dex .apk


(+resurse)

• javac • dx • aapt
Fișierele binare Android

apk

• /META-INF
• /lib
• /res
• /assets
• AndroidManifest.xml
• classes.dex
• resources.arsc
Fișierele binare Android

.dex .odex (Dalvik)


.oat (ART)

• dexopt
• dex2oat
ACTIVITĂȚI
Clasa Context
• Clasă abstractă definită în pachetul
android.content
• Asigură accesul la mediul aplicației
• Acces la resurse
• Lansarea de activități noi
• Acces la servicii de sistem
• Acces la baze de date și fișiere
Clasa aplicație
• Accesul la setările și metodele ale aplicației
• Clasă derivată din Application
• Generată implicit
• Poate fi creată o clasă utilizator prin derivare
• Are un context asociat
– Disponibil pe toată durată rulării aplicației
– getApplicationContext()
Activități
• Asociate ferestrelor aplicației
• O aplicație poate avea una sau mai multe
activități
• Stiva de activități
– Task-uri
• Derivate din clasa de bază android.app.Activity
– Derivată din clasa Context (în vîrful ierarhiei)
• Contextul activității = this
• Fiecare obiect grafic referă contextul activității din
care face parte
Activități
• Au o fereastră asociată
– Reprezentarea interfeței grafice
• Dispun de un ciclu de viață
– Mai multe stări
– Metode cu apel invers
• Invocate la trecerea într-o stare
• Posibilitatea de salvare a stării activității (conținut,
poziție componente vizuale, proprietăți etc.)
Ciclul de viață al activităților
Stare
onCreate()
Creată
(invizibilă)
onStart() onRestart()
Inițializată
(vizibilă)
onResume()
Activă
(vizibilă)
onPause()
Întreruptă
(parțial
vizibilă) onStop()
Inactivă
(ascunsă)
onDestroy()
Terminată
Stiva de activități

Task1 Task2 Task3

Semnifică lansarea unei noi activități din lista de


aplicații recente ( )
sau din lista de programe (după apăsarea butonului
Home )
Activități
import android.app.Activity;
import android.os.Bundle;

public class TestActivity extends Activity


{
@Override
public void onCreate(Bundle stare) {
super.onCreate(stare);
//inițializare conținut vizual
setContentView(view);
//inițalizari activitatate
}
}
Modificarea configurației
• Schimbarea orientării dispozitivului
– rotire
• Activarea/dezactivarea tastaturii fizice
• Schimbare limbii utilizate
– Setări regionale
• etc.
• Activitățile sunt recreate pentru a corespunde
noilor condiții
Clasa Bundle
• Permite stocarea și regăsirea de valori după o cheie de tip String
• Valorile stocate
– Tipuri simple
– Tipuri care implementează interfețele
• Parcelable
• Serializable
• Adăugare valori
– putString(cheie, valoare_String),
– putInt (cheie, valoare_int),
– putObject(cheie, valoare_object),
– putLongArray(cheie, valoare_long_array) etc.
• Regăsire valori
– getString(cheie),
– getInt(cheie),
– getObject(cheie),
– getLongArray(cheie) etc.
Salvarea/restaurarea stării
• Salvarea stării
– onSaveInstanceState(Bundle stare)
• Apelată la ieșirea forțată din aplicație (modificarea
configurației)
• Restaurarea stării
– onRestoreInstanceState(Bundle stare) sau
– onCreate(Bundle stare)
• stare poate fi null!
Ciclul de viață al activităților (2)
Stare
onCreate()
Creată
(invizibilă)
onStart() onRestart()
Inițializată
(vizibilă) onRestoreInstanceState()
onResume()
În execuție
(vizibilă)
onPause()
Întreruptă onSaveInstanceState()
(parțial
vizibilă) onStop()
Inactivă
(ascunsă)
onDestroy()
Terminată
Proprietățile activităților în
AndroidManifest.xml
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
Bibliografie
• S. Komatineni, D. MacLean – Pro Android 4, Apress, 2012
• E-P Lim, K Siau (ed) – Advances in Mobile Commerce Technologies,
Idea Group, 2003
• M. Mallick – Mobile and Wireless Design Essentials, John Wiley &
Sons, 2003
• R. Meier – Professional Android 4 Application Development, Wiley,
2012
• P. Pocatilu, Programarea dispozitivelor mobile, Editura ASE, 2012
• P. Pocatilu, I. Ivan ș.a. – Programarea aplicațiilor Android, Editura,
ASE, 2015
• M. Sauter – Communication Systems for the Mobile Information
Society, John Wiley & Sons, 2006
• http://developer.android.com
Dispozitive și Aplicații Mobile

Cursul 2
Sumar
• Resurse
• Mesaje (Intent)
• Interfața cu utilizatorul
– componente vizuale
– containere
• Interfața grafică în mod declarativ
• Interfața grafică în mod procedural
• Containere
• Tratarea evenimentelor
RESURSE
Resurse
• Şiruri de caractere, culori, masive, stiluri (res/values):
– color
– string
– dimen
– array
• Imagini (res/drawable)
• Pictograme aplicație (res/mipmap)
• Fişiere XML compilate (res/xml)
• Fişiere necompilate (res/raw)
• Fişiere de animație (res/anim)
• Pentru fiecare resursă se generează identificatori în clasa R
• Clasa predefinită android.R
Selectori pentru configurații
Resurse
<resources>
<string name="mesaj">Document nou</string>
</resources>

<resources>
<color name="culoare_fundal">#00CCCC</color>
</resources>

<resources>
<array name="optiuni">
<item>zip</item>
<item>rar</item>
<item>7z</item>
</array>
</resources>
Clasa R
Clasa R
• Subclase
– color
– string
– dimen
– array
– layout
– id
– menu
– etc.
• Membri
– Identificatori/denumire
• Exemple
– R.id.buton
– R.string.denumire_aplicatie
– R.color.rosu
Referirea resurselor din cod
• Clasa Resources
– Metoda getResources() din clasa Context
• Metode dedicate
– getString()
– getColor()
– getDimension()
– etc.
Referirea resurselor din fișiere XML
• @resursa/nume
• @android:resursa/nume
• Exemple
– @string/mesaj
– @color/culoare_fundal
– @array/optiuni
– @id/id_element
– @+id/id_text1
Resurse
//preluarea unui sir de caractere
String sir = getResources().getString(R.string.mesaj);

//preluarea unei culori:


int culoare = getResources().getColor(R.color.culoare_fundal);

//initializarea unei liste de valori din resurse


String [] optiuni=
getResources().getStringArray(R.array.optiuni);
INTERFAȚA CU UTILIZATORUL
Interfața grafică
• Definită prin intermediul componentelor vizuale
și a containerelor
• Asociate activităților și altor componente vizuale
• Inițializare
– Declarativ, prin fișiere XML
• Separă codul de interfața grafică
• Procedural, prin cod
• Componente vizuale (widgets) – controale
• Modalităţi de aranjare și structurare
(ViewGroup/Layout) – containere
Interfața grafică
• View
– Utilizată pentru desenarea suprafeței și tratarea
evenimentelor
– Clasa de bază pentru componente vizuale simple
(widgets)
– Pachetul android.view
• ViewGroup
– Derivată din clasa View
– Clasă de bază pentru containere și componente
vizuale complexe
– Pachetul android.view
Containere
• Definesc structura vizuală a interfeței utilizator
• Structurarea conținutului vizual:
– Liniară (verticală/orizontală)
– Tabelară
– Relativă
• Clasă de bază în ierarhie: ViewGroup
• Definire
– Descriptiv
– Procedural
Containere
• LinearLayout
– Orizontal sau vertical
• TableLayout
– Linii si coloane
– TableRow
• GridLayout
– Linii și coloane
– Combină TableLayout cu LinearLayout
• RelativeLayout
– Relativ la alte componente
Containere
• ConstraintLayout
– Relativ la alte componente
• FrameLayout
– Componentele vizuale sînt suprapuse (stivă)
• ScrollView /HorizontalScrollView
– Permite derularea conținutului pe
verticală/orizontală
• AbsoluteLayout (depreciat)
– Poziționare absolută
Componente vizuale
• Controale
• Pachetul android.widget.*;
• Incluse
– Text static
– Text editabil
– Butoane
– Liste
– Bare de progres
– etc.
Componente vizuale
• TextView
– Text static
• EditText
– Introducere text
– Suport pentru selecția tipului de date (inputType)
• AutoCompleteTextView
– Derivată din EditText
– Introducere text
– Are asociată o listă de sugestii
• Space
– Inserarea de spații între componente
Componente vizuale
• Button
– Buton standard
– Derivat din TextView
• RadioButton
– Buton utilizat în selecția exclusivă
– Derivat din TextView
– uzual, este inclus într-un RadioGroup;
• CheckBox
– Buton utilizat în selecția multiplă
• ToggleButton
– Buton cu două stări, starea apăsat fiind
marcată prin intermediul unui indicator
• Switch
– Buton cu două stări (stînga-dreapta)
Componente vizuale
• ImageView
– Control pentru afișarea
de imagini
• ImageButton
– Buton care permite
afișarea unei imagini
– Derivat din ImageView
Componente vizuale

• ProgressBar
– Bară de progres
– Determinată (limita
superioară stabilită)
– Indeterminată (fără limită
superioară, ciclică)
• SeekBar
– Derivat din ProgressBar,
– permite selectarea valorii
curente
Componente vizuale
• AnalogClock
– Ceas analogic
• TextClock
– DigitalClock (depreciată)
– Ceas digital
– Afișat conform setărilor de
sistem
• Chronometer
– Cronometru
• RadioGroup
– permite gruparea
butoanelor radio
Componente vizuale complexe

• Spinner
– control asemănător unei
liste combinate
• ListView
– listă compusă care afișează
elementele componente
pe verticală
• GridView
– permite poziționarea
componentelor vizuale sub
formă de linii și coloane
Componente vizuale complexe
• ExpandableListView
– listă compusă în care
elementele sînt grupate
pe categorii
Componente vizuale complexe
• DatePicker
– selecția datei
– derivat din FrameLayout

• TimePicker
– selecția orei
– derivat din FrameLayout
Android Support Library
• AndroidX
• Biblioteci de clase
• Asigură compatibilitatea pentru versiunile
anterioare Android
– Fragmente, bara de acțiune, container tabular, bară de
instrumente etc.
• Include componente noi
– ViewPager, DrawerLayout
– RecyclerView
– Snackbar
Exemple dispozitiv Android
INTERFAȚA ÎN MOD DECLARATIV
Interfața în mod declarativ
• Fișiere XML
• Definire
– Elemente interfaţă grafică/elemente vizuale (res/layout)
– Meniuri (res/menu)
• Posibilitatea de reutilizare (includere)
• Resurse referite
– Valori constante (res/values)
• string
• dimen
• color
• Asocierea componentelor vizuale activităților
– metoda setContentView()
Fișierele XML (layout)
• Descriu structura ecranelor sau a
componentelor vizuale
• Fiecare componentă inclusă este reprezentată
de un element XML
• Denumirile elementelor XML = denumirile
claselor asociate componentelor
• Atributele = proprietățile asociate
componentelor
Proprietăți
• android:proprietate
– Specifice fiecărei componente vizuale
• android:layout_proprietate
– clasa LayoutParams
– Transmise componentei părinte în vederea poziționării
și dimensionării
• obligatorii:
– android:layout_width și android:layout_height
• Valori:
– wrap_content sau match_parent sau
– mărimi constante
Referirea resurselor (XML)
• @pachet:tip_resursa/nume_resursa
• Proiectul curent
– @tip_resursa/nume_resursa
– Exemplu:
• @dimen/dim_font
• @color/culoare_fundal
• Resurse predefinite
– @android:tip_resursa/nume_resursa
– Exemplu
• @android:color/background_light
• @android:string/dialog_alert_title
Valori constante
• px (pixels)
• dp (density-independent pixels)
– un dp = un pixel pentru o densitate de 160 dpi
• mm, in
– Raportare la dimensiunea fizică a ecranului
• pt (puncte; 1/72 inch)
– fonturi
• sp (scale-independent pixels)
– fonturi
Densitatea (PPI/DPI)
ℎ𝑝2 +𝑣𝑝2
• Densitatea =
𝑑𝑖𝑎𝑔
– hp – rezoluția pe orizontală (pixeli)
– vp – rezoluția pe verticală (pixeli)
– diag – diagonala (inci)
Dimenisiuni - conversii
• Din pixeli în dp
𝑝𝑥 ∗160
– 𝑑𝑝 =
𝐷𝑃𝐼
• Din dp în pixeli
𝑑𝑝 ∗𝐷𝑃𝐼
– 𝑝𝑥 =
160
Dimenisiuni – conversii (în cod)
DisplayMetrics dm =
getResources().getDisplayMetrics();

//conversie la pixeli
int px = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, dp, dm);

//sau

int px = Math.round(dp * dm.density);


Dimensiuni

2.5”, 240x320 7”, 800x1280 4.7”, 768x1280


Proprietăți
• Identificatorul componentei
• android:id
• Asociere identificator: "@+id/identificator"
• Referire identificator existent:
– XML: @id/identificator
– Java: R.id.identificator
Proprietăți
Proprietate Atribut Exemple de valori
Textul asociat resursei android:text "Text în clar"
@string/text_control
Distanţa conţinutului android:padding 10dp
faţă de margini android:paddingTop|Left|Right|
Bottom
Culoarea de fundal android:background #FF00FF
@drawable/imag
Modul de aliniere a android:gravity center, left
conţinutului
Distanţa faţă android:layout_margin, 30dp
de marginile android:layout_marginTop|Left|
containerului Right|Bottom
Afișarea/ascunderea android:visibility visible, invisible, gone
componentei
Proprietăți

Container

View

margin padding
Conținut View height

width
Exemplu
<!—res/layout/main.xml--> <!-- /res/values/strings.xnl -->
<LinearLayout <!-- … --> <resources>
<string name="titlu">Titlul</string>
android:layout_width="match_parent"
<string name="introduceti">Introduceti titlul</string>
android:layout_height="wrap_content" <string name="trimite">Trimite</string>
android:orientation="vertical" > </resources>
<TextView
android:id="@+id/textViewTitlul" // /src/Activitate.java
//in metoda onCreate()
android:layout_width="wrap_content" setContentView(R.layout.main)
android:layout_height="20dp"
android:text="@string/titlul" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10"
android:hint="@string/introduceti" >
</EditText>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/trimite" />
</LinearLayout>
Referirea componentelor în cod
• Metoda din clasa Activity:
– View findViewById(int idResursa)
– <T extends View> T findViewById(int idResursa)
• Exemplu
– TextView tv = (TextView)
findViewById(R.id.textViewTitlul);
– tv.setText("text stabilit din cod");
• Apelul se realizează după invocarea metodei
setContentView()!
INTERFAȚA ÎN MOD PROCEDURAL
Interfața în mod procedural
• Controalele inițializate din cod
• Constructori
– Contextul curent
• Inițializare proprietăți
• Adăugare la containere
– Metoda addView()
• Anumite dimensiuni trebuie calculate
• Asociere conținut în activitate
– setContentView()
– Poate fi un container sau un control
Proprietăți comune
• Dimensiuni:
– getWidth()
– getHeight()
• Aspect
– setBackgroundColor(int culoare)
– setBackground(Drawable)
– setBackgroundResource(int idResursa)
Proprietăți comune
• Spațiere (distanţă faţă de conţinut):
– setPadding()
– getPaddingLeft()
– getPaddingTop()
– getPaddingRight()
– getPaddingBottom()
• Activare:
– setEnabled(boolean)
– isEnabled()
• Posibilitatea de selectare
– setFocusable(boolean)
– isFocusable()
Proprietăți comune
• Parametri container
– setLayoutParams(LayoutParams)
– LayoutParams getLayoutParams()
• Vizibilitate:
– setVisibility(int) – VISIBLE, INVISIBLE, GONE
Proprietăți comune
• Poziție (pixeli):
– absolută
• setX()/getX()
• setY()/getY()
– relativă la părinte
• setLeft()/getLeft()
• setTop()/getTop()
• setRight()/getRight()
• setBottom()/getBottom()
Proprietăți comune
• Tratare evenimente:
– setOnClickListener()
– setOnLongClickListener()
– setOnDragListener()
– setOnKeyListener()
– setOnTouchListener()
INTERFAȚA ÎN MOD PROCEDURAL
Interfața în mod procedural
//containerul
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);

//controlul static
TextView tv = new TextView(this);
tv.setText("Titlul:");

//conversie 20dp la pixeli


DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
int hPixeli = (int)
TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20,
displayMetrics);
Interfața în mod procedural
//inaltime 20dp, latime WRAP_CONTENT
LayoutParams lpt = new
LayoutParams(LayoutParams.WRAP_CONTENT, hPixeli);
tv.setLayoutParams(lpt);

//pentru WRAP_CONTENT la controlul de editare si la


buton
LayoutParams lp = new
LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
Interfața în mod procedural
//controlul de editare
EditText et = new EditText(this);
et.setText("introduceti titlul" );
et.setEms(10);
et.setLayoutParams(lp);

//butonul
Button buton = new Button(this);
buton.setText("Trimite");
buton.setLayoutParams(lp);

//adaugare la container
layout.addView(tv); layout.addView(et); layout.addView(buton);

//asociere continut
setContentView(layout);
CONTAINERE
LinearLayout
• Modul de aranjare a componentelor:
android:orientation
– horizontal

– vertical
LinearLayout
• Distribuirea spațiului rămas liber (proporții)
– android:layout_weight

view1, view2, view3:


android:layout_width="wrap_content"
view1, view2, view3:
android:layout_width="0dp"
android:layout_weight="1"
view1, view2
android:layout_width="wrap_content"
view3:
android:layout_width="0dp"
android:layout_weight="1"
LinearLayout
• Alinierea componentelor în cadrul
containerului
android:layout_gravitiy="center_vertical"

– android:layout_gravity
android:layout_gravitiy="center_horizontal"
"top"

"left" "right"

"bottom"
android:orientation="horizontal" android:orientation="vertical"
RelativeLayout
• Aliniere
– Relativă la container (true/false):
• android:layout_alignParentTop|Left|Right|Bottom
• android:layout_centerHorizontal|Vertical
• android:layout_centerInParent
– Relativă la alte componente (id-ul):
• android:layout_alignLeft|Right|Start|Top|End
• Poziționare
– android:layout_below, android:layout_above
– android:layout_toEnd|Left|Start|RightOf
RelativeLayout

android:layout_alignLeft="@id/id3"
android:layout_alignParentTop = true

id1 id2 id3


id4 id5
id6 id7
id8 id9

android:layout_toRightOf="@id/id8"
android:layout_below="@id/id1"
ConstraintLayout
• Ierarhie care nu implică imbricarea
controalelor
• Asemănător containerului de tip
RelativeLayout
• Integrat cu editorul vizual din Android Studio
• Creșterea performanțelor
ConstraintLayout
dependencies {
implementation 'com.android.support.constraint:constraint-layout:x.x.x'
}
Restricții
• Puncte de conectare între controale și
– alte controale
– containerul părinte
– puncte de referință
Restricții
• Poziționare relativă
– Identificatorii controalelor sau parent
• Margini
– Inclusiv controlul față de componentele ascunse
• Centrare/poziționare proporțională
• Înlănțuire
• Dimensiuni
• Puncte de referință
Poziționarea relativă
• app:layout_constraint[PunctSursă]_[PunctDestinație]=
"[IdentificatorDestinație]"
• PunctSursă
– Start
– Top
– Bottom
– End
• PunctDestinție
– toStartOf
– toEndOf
– toBottomOf
– toTopOf
Înlănțuiri
• Proprietăți
– layout_constraintHorizontal_chainStyle
– sau layout_constraintVertical_chainStyle
• Se aplică primului element din înlănțuire
• Valori
– spread
– spread_inside
– packed
Manipulatori
• Dimensionare
• Restricții laturi
• Restricții puncte de referință
TableLayout
• Derivată din LinearLayout
• Linii
– TableRow
• Coloana asociată
– android:layout_column
• Întinderea pe mai multe coloane:
– android:layout_span
• Adaptarea la conținut (pe baza indecșilor coloanelor)
– android:shrinkColumns
• Eliminarea spațiului liber
– android:stretchColumns
• Extinderea coloanelor pentru a ocupa spațiul liber
– android:collapseColumns
• Ascunderea coloanelor
TableLayout

TableRow

android:layout_span="2"
android:layout_column="0"
GridLayout
• Număr coloane
– android:columnCount
• Întinderea pe mai multe linii:
– android:layout_rowSpan
• Întinderea pe mai multe coloane:
– android:layout_columnSpan
GridLayout

android:layout_rowSpan="3"
android:layout_columnCount="3"

android:layout_row="3"

android:layout_columnSpan="2"
android:layout_column="0"
FrameLayout
• În mod uzual, este afișată o singură
componentă vizuală
• Poziționarea componentelor:
– Implicit: colțul stînga-sus
– Suprapunere pe niveluri pe axa z
• adîncime
• android:layout_gravity
– Suprapunerea componentelor vizuale
FrameLayout

android:layout_gravitiy="center"
ScrollView/HorizontalScrollView
• Derivată din FrameLayout
• Acceptă o singură componentă vizuală;
• Afișare bare de defilare
– android:scrollbars="vertical"
• Ocuparea întregii suprafețe disponibile
– android:fillViewport="true"
Parametrii containerelor
• Clasa de bază ViewGroup.LayoutParams
• Definită în fiecare clasă de tip container
– LinearLayout.LayoutParams, RelativeLayout.LayoutParams
• Referire din clasa View
– setLayoutParams()
– getLayoutParams()
• Proprietăți comune
– width, height
• Proprietăți specifice containerului
– gravity, weight
• Constructor
– width, height
Parametrii containerelor
//inaltime 20 pixeli
LinearLayout.LayoutParams lp = new
LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, 20);
lp.setMargins(10, 10, 10, 10);//left, top, right, bottom (pixeli)
view.setLayoutParams(lp);

//daca obiectul view este deja atasat la un container


LayoutParams lpb = view.getLayoutParams();
lpb.width = ViewGroup.LayoutParams. MATCH_PARENT;
lpb.height = ViewGroup.LayoutParams.WRAP_CONTENT;
view.setLayoutParams(lpb);
TRATAREA EVENIMENTELOR
Tratarea evenimentelor
• Interfețe de tip listener
– Ex: View.OnClickListener
• Metode pentru tratarea evenimentelor
– Ex.: onClick()
• Înregistrarea evenimentelor
– Ex.: setOnClickListener()
Tratarea evenimentelor

Metoda pentru
Interfața tratarea Înregistrarea obiectului
evenimentului
View.OnClickListener onClick() setOnClickListener()
View.OnKeyListener onKey() setOnKeyListener()
View.OnTouchListener onTouch() setOnTouchListener ()
View.OnLongClickListener onLongClick() setOnLongClickListener()
Tratarea evenimentelor
• Implementarea interfeței într-o clasă
– dedicată
– existentă (clasa de tip activitate etc.)
• Implementarea interfeței într-o clasă anonimă
• Varianta rapidă pentru evenimentul click:
– proprietatea onClick în fișierul XML
– metoda de tratare a evenimentului în clasa
activitate asociată
Tratarea evenimentelor (1)
public class Activitate extends Activity implements
View.OnClickListener {

public void onCreate(Bundle savedInstanceState) {

//înregistrare clasă tratare eveniment pentru Button buton


buton.setOnClickListener(this);
//...
}

//tratare eveniment
public void onClick(View view) {
// Tratarea evenimentului
}
}
Tratarea evenimentelor (2)
public class EvenimClick implements View.OnClickListener {
//tratare eveniment
public void onClick(View view) {
// Tratarea evenimentului
}
}
public class Activitate extends Activity {
public void onCreate(Bundle savedInstanceState) {
//înregistrare clasă tratare eveniment pentru Button buton
buton.setOnClickListener(new EvenimClick());
//…
}
}
Tratarea evenimentelor (3)
//Înregistrare și implementare clasă anonimă
//pentru tratare eveniment pentru controlul
//buton de tip Button. Codul poate fi în onCreate()

buton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Tratarea evenimentului
}
});
Tratarea evenimentelor (4)
• XML
– android:onClick="numeMetoda"
• În clasa derivată din Activity:
– public void numeMetoda(View view) { … }
• Aceeși metodă pentru mai multe controale
– Diferența între controale:
• view.getId()
Bibliografie
• S. Komatineni, D. MacLean – Pro Android 4,
Apress, 2012
• R. Meier – Professional Android 4 Application
Development, Wiley, 2012
• P. Pocatilu, Programarea dispozitivelor mobile,
Editura ASE, 2012
• P. Pocatilu, I. Ivan ș.a. – Programarea
aplicațiilor Android, Editura, ASE, 2015
• http://developer.android.com
Dispozitive și aplicații mobile

Cursul 3 - 4
Sumar
• Stiluri și teme
• Deserializarea componentelor
• Meniuri și bara aplicației
– Menu, ActionBar, Toolbar
• Fragmente
• Ferestre de informare
• Mesaje (2)
STILURI ȘI TEME
Stiluri și teme
• Stilurile
– descriu proprietățile de formatare pentru diferite elemente de
interfață grafică (controale și containere)
– se aplică în mod individual
• Temele
– stiluri care se aplică la nivelul unei activități/control/container
– se utilizează global
• Predefinite și utilizator
• Resurse utilizator
– res/values/styles.xml
• Resurse predefinite
– R.style
Stiluri: Definire
<resources>
<style name="stil_titlu">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">#FF0000</item>
<item name="android:textStyle">bold</item>
</style>
</resources>
Stiluri: Referire
<TextView
style="@style/stil_titlu"/>

<TextView
...
style="@android:style/TextAppearance.Large" />
Teme
• Atributul android:theme la nivelul
– Aplicației (toate activitățile)
– Unei activități
– Unui container/control
• AndroidManifest.xml
Exemple de teme predefinite
• Theme.Holo
• Theme.Holo.Light
• Theme.Holo.Light.DarkActionBar
• Theme.Material
• Theme.Material.Light
• Theme.Material.Light.DarkActionBar
• Theme.AppCompat
• Theme.AppCompat.NoActionBar
• Theme.AppCompat.Light
• Theme.AppCompat.Light.DarkActionBar
Teme
<activity
android:theme =
"@android:style/Theme.Holo.Dialog">
...
</activity>
DESERIALIZAREA COMPONENTELOR
Deserializarea componentelor
• Crearea de obiecte pe baza unui fișier XML
• Clasa
– LayoutInflator
• Instanțierea obiectelor pentru conversie:
– Activity#getLayoutInflater()
– Context#getSystemService(String)
– LayoutInflater.from(context)
• Metoda de conversie:
– View inflate(id_resursa, părinte)
MENIURI
Meniuri
• Meniu principal activitate
• Meniuri contextuale
– Apăsarea prelungită pe ecran
• Meniuri de tip popup
Opțiuni meniu
• Definire în fișiere de resurse dedicate
– res/menu
• Definire în mod programatic
– Interfața MenuItem
Opțiuni de meniu
• Identificatorul grupului din care face parte
opțiunea
• Identificatorul opțiunii
• Ordinea de afișare în meniu
• Titlul
• Pictograma asociată
– Nu este afișată decît în bara aplicației
Meniul principal
• Pînă la API 11
– Un buton dedicat (MENU)
– Lansează meniul aplicației
• Începînd cu API 11
– Nu mai este obligatoriu butonul dedicat
• Definire
– Resurse
– Programatic
Meniul principal
Versiune Android Aspect Meniu

2.3.3, buton Menu

4.x, buton Menu

4.x, fă ră buton Menu


Meniul principal
• Metode cu apel invers din clasele derivate din
Activity
• Creare:
public boolean onCreateOptionsMenu(Menu meniu)
• Tratarea evenimentelor:
public boolean onOptionsItemSelected(MenuItem mi)
• Modificarea dinamică a conținutului:
public boolean onPrepareOptionsMenu(Menu meniu) {
Deserializarea meniurilor
• Clasa
• MenuInflator
– Inițializare
• Activity#getMenuInflater()
• Context#getSystemService(String)
– Deserializare
• inflate(int id_meniu, Menu meniu)
Meniul principal – XML
@Override
public boolean onCreateOptionsMenu(
Menu meniu) {
//…
getMenuInflater().inflate(R.menu.main, meniu);
//…
return true; R.menu.main
– resursă res/menu/main.xml
}
Meniul principal – Java
@Override
public boolean onCreateOptionsMenu(
Menu meniu) {

meniu.add(Menu.NONE,
MI_INAINTE, 0, "Inainte");

return true;
}
MI_INAINTE
– identificator constant pentru opțiune (int)
Meniul principal
public boolean onOptionsItemSelected(MenuItem mi)
{
//tratarea evenimentelor generate de selecția din meniu
switch (mi.getItemId()) {
case R.id.INAINTE : {
//
break;
}
//...
}
}
Meniuri contextuale
• Interfața ContextMenu
• Inițializare
public void onCreateContextMenu(ContextMenu
menu, View v, ContextMenuInfo menuInfo)
• Tratare evenimente
public boolean onContextItemSelected(MenuItem mi)
• Asociere control
registerForContextMenu(view)
BARA APLICAȚIEI
Bara aplicației
• Acces rapid la acțiuni și comenzi specifice
• Suport pentru navigare în aplicație
• Informații cu privire la contextul utilizatorului
în cadrul aplicației
• Identitatea aplicației
• Comutarea între perspective
Bara aplicației
Bara aplicației
• ActionBar
– Integrată activității din care face parte
– Suport pentru navigare (depreciat începînd cu API 21)
• Meniu de tip listă (control de tip Spinner);
• Control de navigare prin selectori (tab);
• Toolbar (API 21, Material Design)
– Definită sub format unui control uzual
• Poate fi plasată oriunde pe ecran
– Flexibilitate ridicată
Bara aplicației
• Control de navigare (meniu sau pictogramă
săgeată)
• Pictograma aplicației/Logo
• Titlul aplicației/activității
• Subtitlu
• Controale utilizator/opțiuni din meniu
• Pictograma meniului (overflow icon)
– opțiuni din meniu
Bara aplicației
• Acces la obiectul de tip ActionBar
– getActionBar()
• Stabilire bară aplicație
– setActionBar()
ActionBar
• Ascundere/afișare bară
– hide()/show()
• Afișare titlu/subtitlu
– setTitle()/setSubtitle()
• Modificare mod de navigare (depreciat)
– setNavigationMode()
• NAVIGATION_MODE_STANDARD
• NAVIGATION_MODE_LIST
• NAVIGATION_MODE_TABS
Toolbar
• Tema fără bara de acțiune
– Theme.Tema.NoActionBar
• sau temă proprie, cu atributele:
– <item name="android:windowNoTitle">true</item>
– <item name="android:windowActionBar">false</item>
Afișare opțiuni meniu
• res/menu
• showAsAction
– always
– ifRoom
– withText
– never
FRAGMENTE
Fragmente
• Posibilitatea de modularizare a interfeței
• Gestiunea facilă a dimensiunilor diferite
• Transmiterea obiectelor între ecranele
aplicației
• Suport pentru navigare între ecrane
– Stiva de fragmente
Fragmente
Fragmente
• Derivate din clasa Fragment
• Asociate activităților
• Au un ciclu de viață propriu
• Recepționează evenimente
• Interfața inițializată din XML sau cod
– Static vs. dinamic
• Necesită un container
Fragmente – ciclul de viață
Activitate Fragment
1. onCreate()
1. onAttach()

2. onAttachFragment()
2. onCreate()
3. onCreateView()
4. onActivityCreated()
3. onStart()
5. onStart()
4. onResume()
6. onResume()
Fragmente – ciclul de viață (cont.)
Activitate Fragment
1. onPause()
1. onPause()
2. onSaveInstanceState()
2. onSaveInstanceState()
3. onStop()
3. onStop()
4. onDestroyView()
5. onDestroy()
6. onDetach()
4. onDestroy()
Clasa Fragment
• Referire activitate container
– getActivity()
Fragmente - XML
Fragmente- XML
• Creare clasă de tip fragment, derivată din Fragment
• Definire machetă activitate (layout_activitate.xml)
– Include elementul fragment
– Referă clasa de tip fragment
• Clasa de tip activitate referă resursa de tip machetă
care include fragmentul
• Definire machetă fragment (layout_fragment.xml)
• În clasa de tip fragment:
– deserializare machetă fragment (inflate)
• metoda onCreateView()
Fragmente - XML
public class ClasaFragment extends Fragment {

@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle bundle) {
// macheta asociată fragmentului
return inflater.inflate(R.layout.layout_fragment,
container, false);
}
}
Referirea fragmentelor
• Inițializarea unui obiect de tip
FragmentManager
– getFragmentManager() din clasa activitate
• Inițializarea unui obiect de tip Fragment
definit în layout:
– FragmentManager#findFragmentById(id)
– FragmentManager#.findFragmentByTag(tag)
Fragmente dinamice
• Nu se utilizează elementul fragment în
fișierele de tip machetă
• Se definește un container pentru fragment
– uzual un FrameLayout
• Clase specializate pentru tranzacții
Tranzacții cu fragmente
• FragmentManager
– Gestionează fragmentele din cadrul activităților
– Interacțiunea cu fragmentele în cadrul activităților
• FragmentTransaction
– Operații cu fragmente
• adăugare
• ștergere
• înlocuire
Tranzacții cu fragmente
• Inițierea unei tranzacții
– apelul metodei beginTransaction() din clasa
FragmentManager
• se obține un obiect de tip FragmentTransaction
• Operații cu fragmente (FragmentTransaction):
– Adăugare – metoda add()
– Eliminare –metoda remove()
– Înlocuire fragment –metoda replace()
• Salvarea operațiilor (FragmentTransaction):
– metoda commit()
Tranzacții cu fragmente – exemplu
FragmentManager fm = getFragmentManager();

FragmentA fragmentA = new FragmentA();


FragmentB fragmentB = new FragmentB();

// adaugare fragment A
FragmentTransaction ft = fManager.beginTransaction();
ft.add(R.id.fragId, fragmentA, "fragmentA");
ft.commit();
Tranzacții cu fragmente - exemplu
// înlocuire fragment A cu B
FragmentTransaction ft2 = fm.beginTransaction();
ft2.replace(R.id.fragId, fragmentB, ”fragmentB”);
// adaugare fragment in stiva (revenire cu Back)
ft2.addToBackStack(null);
ft2.commit();

// eliminare fragment B
FragmentTransaction ft3 = fm.beginTransaction();
ft3.remove(fm.findFragmentByTag("fragmentB"));
ft3.commit();
Fragmente
• DialogFragment
• ListFragment
• PreferenceFragment
• WebViewFragment
Bibliografie
• R. Meier – Professional Android 4 Application
Development, Wiley, 2012
• S. Komatineni, D. MacLean – Pro Android 4, Apress,
2012
• P. Pocatilu, Programarea dispozitivelor mobile,
Editura ASE, 2012
• P. Pocatilu, I. Ivan ș.a. – Programarea aplicațiilor
Android, Editura, ASE, 2015
• http://developer.android.com
Dispozitive și aplicații mobile

Cursul 5
Sumar
• Componente vizuale complexe
– Liste
• Adaptoare
• Tratarea selecțiilor
COMPONENTE VIZUALE COMPLEXE
Componente vizuale complexe
• Controale complexe (ViewGroup)
– Elemente de tip View
• Implementează clasa abstractă AdapterView
• Inițializate prin intermediul unui adaptor
• Asocierea
– metoda setAdapter()
Componente vizuale complexe
• ListView, GridView
• Spinner
• RecyclerView
• AutoCompleteTextView
• MultiAutoCompleteTextView
• Gallery
• ListActivity
– getListView()
– setListAdapter()
• ListFragment
Adaptoare
• Asigură legătura dintre sursa de date și
controale de tip listă de elemente
• Acces la sursa de date
• Creează un View pentru fiecare element din
sursa de date
Adaptoare
• Clase derivată din BaseAdapter
– implementează interfața Adapter
• ArrayAdapter
• CursorAdapter
– SimpleCursorAdapter
• SimpleAdapter
Componente vizuale complexe
Componente vizuale complexe

Sursa de date Adaptor Controale complexe


(AdapterView)

• Array • ArrayAdapter • ListView


• ArrayList • SimpleCursorAdapter • GridView
• Cursor • CursorAdapter • Spinner
•… • utilizator

Layout element

• utilizator
• Implicite (android.R.layout.)
• simple_spinner_dropdown_item
• simple_list_item_1
• etc.
Resurse predefinite
Resursă predefinită Descriere
(android.R.layout… )
simple_spinner_item Text pe o singură linie
simple_spinner_dropdown_item Text pe o lini e care i nclude suport
pentru selecț ie
simple_list_item_1 Text pe o singură linie
simple_list_item_2 Text pe două linii
simple_list_item_simple_choice Text pe o lini e care i nclude suport
pentru selecț ia exclusivă
simple_list_item_multiple_choice Text pe o lini e care i nclude suport
pentru selecț ia multiplă
simple_expandable_list_item_1 Text pe o singură linie
simple_expandable_list_item_2 Text pe dou
ă linii
ArrayAdapter
• Sursa de date simplă:
– ArrayList, Array etc.
• Constructor:
– Contextul (activitate)
– Identificatorul resursei de tip machetă asociat unui
element din listă
– Identificatorul controlului de tip TextView (dacă este cazul)
– Lista de șiruri
• Pentru un element din sursă:
– Apelează metoda toString()
– Asociază conținutul unui TextView
Exemplu (1)
String [] tari = new String[] {"Romania", "Bulgaria", "Grecia"};

//inițializare listă
ListView lv = (ListView)findViewById(R.id.lista1);

//initializarea adaptor
ArrayAdapter<String> adaptor = new ArrayAdapter<>(
this,
android.R.layout.simple_list_item_1,
tari);

//asociere adaptor
lv.setAdapter(adaptor);
Exemplu (1-1)
String [] tari = new String[] {"Romania", "Bulgaria", "Grecia"};

//iniț ializare listă


ListView lv = (ListView)findViewById(R.id.lista1);

//initializarea adaptor
ArrayAdapter<String> adaptor = new ArrayAdapter<>(
this,
R.layout.element_lista,
R.id.textViewTara
tari);

//asociere adaptor
lv.setAdapter(adaptor);
Exemplu (2)
class Tara {
String nume ;
int populatie;
Bitmap steag;
//metode de acces publice (ex. getNume()/setNume())
public String toString() {
return "Denumire: " + nume + ", populatie: " + populatie;
}
}
Exemplu (2)
ArrayList<Tara> listaTari = new ArrayList<>();

//inițializare listă
ListView lv = (ListView)findViewById(R.id.lista1);

//initializarea adaptor
ArrayAdapter<Tara> adaptor = new ArrayAdapter<>(
this,
android.R.layout.simple_list_item_1,
listaTari);

//asociere adaptor
lv.setAdapter(adaptor);
SimpleAdapter
• Contextul curent
• Lista de obiecte care vor fi afișate în listă
– incluse în obiecte de tip Map
• cheia este de tip String
• cheia identifică numele coloanei ale că rei valori sunt iniț ializate
• Identificatorul unei resurse de tip machetă
• Lista coloanelor ale căror valori vor fi afișate pe fiecare
linie din listă
– numele coloanelor trebuie identificate în obiectele de tip
Map din lista de date
• Lista identificatorilor asociați resurselor de tip
TextView utilizate
Exemplu (3)
ArrayList<Map<String, String>> tari = new ArrayList<>();

final String NUME = "nume";


final String POPULATIE = "populatie";

//in metoda onCreate()

for (Tara obTara : listaTari) {


HashMap<String, String> tara = new HashMap<String, String>();
tara.put(NUME, obTara.getNume());
tara.put(POPULATIE, obTara.getPopulatie() + " locuitori");
tari.add(tara);
}
Exemplu (3)
String[] proprietati = { NUME, POPULATIE };
int[] identificatori = { android.R.id.text1, android.R.id.text2 };

SimpleAdapter adaptor = new SimpleAdapter(


this, // contextul
tari,// lista de obiecte
android.R.layout.simple_list_item_2, // identificatorul machetei
proprietati, // proprietatile utilizate
identificatori);
//activitatea este de tip ListActivity
setListAdapter(adaptor);
ADAPTOR PERSONALIZAT
Derivare din clasa BaseAdapter
• int getCount( )
– returnează numărul de elemente disponibile în sursa de
date
• object getItem(int pozitie)
– returnează elementul de la poziția indicată
• long getItemId(int pozitie)
– returnează identificatorul înregistrării de la poziția indicată
• View getView(int pozitie, View convertView,
ViewGroup parinte)
– metoda returnează obiectul de tip View creat și inițializat
pentru afișarea în listă a elementului de la poziția indicată
Exemplu (4)

Container

Romania
TextView

19.544.000 locuitori
TextView

ImageView

res/layout/element_lista.xml
Exemplu (4) - Adaptorul
public class AdaptorTari extends BaseAdapter {

List<Tara> tari; LayoutInflater layoutInflater;

AdaptorTari(Context context, List<Tara> tari) {


layoutInflater = LayoutInflater.from(context);
this.tari = tari;
}
//urmează implementarea metodelor clasei abstracte
}
Exemplu (4) - cont
@Override
public int getCount() {
return tari.size();
}

@Override
public Object getItem(int position) {
return tari.get(position);
}

@Override
public long getItemId(int position) {
return position;
}
Exemplu (4.1) - cont.
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
converView = layoutInflater.inflate(R.layout.element_lista,
parent, false);
}
//initializare obiecte controale
ImageView steag = (ImageView)
convertView.findViewById(R.id.imageViewSteag);
TextView nume = (TextView)
convertView.findViewById(R.id.textViewNume);
TextView populatie = (TextView)
convertView.findViewById(R.id.textViewPopulatie);
Tara tara = tari.get(position);
//initializare controale cu valori
steag.setImageBitmap(tara.getSteag());
nume.setText(tara.getNume());
populatie.setText(tara.getPopulatie() + "
locuitori");
return convertView;
}
Exemplu (4.2) - cont.
public class AdaptorTari extends BaseAdapter {
private static class ViewHolder {
public ImageView steag;
public TextView nume, populatie;
}
//…
}
Exemplu (4.2) - cont
@Override
public View getView(int position, View convertView, ViewGroup parent) {

ViewHolder holder;

if(convertView == null) {//controlul este afisat pentru prima oara


//initializare obiecte controale
convertView = layoutInflater.inflate(R.layout.element_lista, parent, false);
holder = new ViewHolder();
holder.steag = (ImageView) convertView.findViewById(R.id.imageViewSteag);
holder.nume = (TextView) convertView.findViewById(R.id.textViewNume);
holder.populatie = (TextView) convertView.findViewById(R.id.textViewPopulatie);

convertView.setTag(holder);
}
//else în continuare
Exemplu (4.2) - cont
else {
holder = (ViewHolder)convertView.getTag();
/*reutilizare resurse*/
}

Tara tara = tari.get(position);

//initializare controale cu valori


holder.steag.setImageBitmap(tara.getSteag());
holder.nume.setText(tara.getNume());
holder.populatie.setText(tara.getPopulatie() + " locuitori");
return convertView;
}
Exemplu (4) – Asociere adaptor
AdaptorTari adaptorTari = new AdaptorTari(
this, listaTari);

setListAdapter(adaptorTari);
NOTIFICAREA MODIFICĂRILOR
Notificarea modificărilor
• ArrayAdapter include metode de gestiune a
sursei de date
– add(), insert(), remove(), clear()
• După fiecare modificare se apelează prin,
intermediul adaptorului, metoda
– notifyDataSetChanged()
• Recrearea adaptor cu noua listă
(nerecomandat)
ASOCIERE TEXT LISTĂ VIDĂ
Fișier de tip machetă
/res/layout/layout.xml

<ListView />
<TextView android:id="@+id/empty"

Fișier sursă
//inițializare listă
ListView lv = ...
//initalizare control text listă vidă
TextView textViewListaVida =
(TextView)findViewById(R.id.empty);
//asociere text listă vidă
textListaVida.setText(textListaVida);
//asociere control
lv.setEmptyView(textViewListaVida);
SELECȚIA ELEMENTELOR
Spinner
• getSelectedItem()
• getSelectedItemId()
Spinner
• Interfața
– AdapterView.OnItemSelectedListener
• Metodele implementate
– onItemSelected()
– onNothingSelected()
• Asociere
– setOnItemSelectedListener()
Selecția elementelor (Spinner)
spinner.setOnItemSelectedListener(new
AdapterView.OnItemSelectedListener() {

@Override
public void onItemSelected(AdapterView<?> parent, View view,
int poz, long id) {
//parent.getItemAtPosition(poz);
}

@Override
public void onNothingSelected(AdapterView<?> parent) {

}
});
ListView
• getItemAtPosition()
• getItemIdAtPosition()
ListView
• Interfața
– AdapterView.OnItemClickListener
• Metoda implementată
– onItemClick()
• Asociere
– setOnItemClickListener()
Selecția elementelor (liste)
lista.setOnItemClickListener(new
OnItemClickListener() {
public void onItemClick(AdapterView<?> parent,
View item, int poz, long id){
//referim elementul selectat prin poz;
//parent.getItemAtPosition(poz);
}
});
Bibliografie
• R. Meier – Professional Android 4 Application
Development, Wiley, 2012
• S. Komatineni, D. MacLean – Pro Android 4, Apress,
2012
• P. Pocatilu, Programarea dispozitivelor mobile,
Editura ASE, 2012
• P. Pocatilu, I. Ivan ș.a. – Programarea aplicațiilor
Android, Editura, ASE, 2015
• http://developer.android.com
Programarea Dispozitivelor Mobile

Cursul 6 - 7
Sumar
• Ferestre de informare
• Mesaje (Intent)
• Operații asincrone
• Accesul la rețea
– Socket
– HTTP
– Servicii Web
• Prelucrarea fișierelor XML și JSON
FERESTRE DE INFORMARE
Ferestre de informare
• Clasa Activity
– @android:style/Theme.***.Dialog
• Clasa Dialog sau derivate
• Clasa AlertDialog
• Clasa DialogFragment
• Ferestre de dialog predefinite
– ProgressDialog
– TimePickerDialog
– DatePickerDialog
• Clasa Toast
AlertDialog
• Create prin intermediul clasei AlertDialog.Builder
• Ferestrele includ:
– Titlu (text + pictogramă)
– Mesaj/Listă/Opțiuni (exclusive sau multiple)
– Butoane (maxim trei)
• Creare și afișare: show()
• Inchidere: dismiss(), cancel()
AlertDialog.Builder
Stabilire Metoda
Mesaj setMessage(mesaj)
Titlu setTitle(titlu)
Buton acț iune pozitivă (OK) setPositiveButton(eticheta, tratare_actiune)
Buton acț iune negativă (No) setNegativeButton(eticheta, tratare_actiune)
Buton acț iune neutră (Cancel) setNeutralButton(eticheta, tratare_actiune)
Pictograma titlu setIcon(idPictograma)
Acț iune tasta Back setCancelable(true/false)

Constructorul: contextul curent


Creare AlertDialog: create()
Ferestre de informare

new AlertDialog.Builder(this)
.setTitle("Info")
.setMessage("Exemplu AlertDialog")
.show();
Ferestre de informare cu liste
• setItems()
– Lista elemente
– Obiect tratare eveniment selecție
• setSingleChoiceItems()
– + element selectat sau -1
• setMultipleChoicheItems()
– + lista elemente selectate sau null
Exemplu
new AlertDialog.Builder(this)
.setTitle("Font")
.setMultiChoiceItems(optiuni, null, new
DialogInterface.OnMultiChoiceClickListener() {
public void onClick(DialogInterface dialog, int id, boolean isChecked) {
// preluare selectie}})
.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//prelucrare confirmare selectie
dialog.dismiss(); }})
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//renuntare la selectie
dialog.cancel(); }})
.show()
Exemplu
Clasa Toast
• Afișarea unui mesaj de informare pentru o durată determinată
• Inițializare
– Constructor
– Metoda statică makeText()
• Context, text și durată
• Durată
– Toast.LENGTH_SHORT
– Toast.LENGTH_LONG
• Afișare
– show()
Clasa Toast
• Metode:
– setText()
– setDuration
– setGravity()
• poziționare pe ecran
• Poate fi personalizată
– setView()
Clasa Toast

Toast.makeText(this,
"Fisierul a fost salvat",
Toast.LENGTH_SHORT).show();
MESAJE (INTENT)
Obiecte de tip Intent
• Mesaje asincrone
• Utilizare
– Invocare activități
– Invocare servicii
– Transmitere mesaje globale
– Partajare date
Caracteristicile mesajelor de tip Intent
• Acțiuni
• Date
– Tip de date
• Categorie
• Date adiționale
• Componenta destinație
Tipuri de mesaje
• Explicite
– Sînt invocate anumite componente
– Necesară cunoașterea numelui componentei
• Implicite
– Sînt invocate acele componentele care corespund unor criterii
(acțiune, tip date etc.)
– Componentele nu sînt cunoscute la apel
Acțiuni
• Definite sub forma unor operații (String)
• Operații
– Predefinite (sistem)
– Definite de programator
• Generice sau specializate
– VIEW vs. CALL
Date
• Prezentate sub forma unui URI (Uri)
• Caracterizate prin tip (formatul MIME)
– text/html, text/plain, application/pdf etc.
• Date suplimentare (Bundle atașat)
– Extras
Date suplimentare
• Obiect de tip Bundle atașat
– Container de date
• Adăugare date
– putExtra(cheie, valoare)
• Adăugare conținut container existent de date
– putExtras(Bundle)
• Preluare date
– getTIPExtra(cheie): getFloatExtra(), getStringExtra() etc.
• Obținere container date
– Bundle getExtras()
Acțiuni predefinite
Acţ iunea (Intent.__) Date asociate Semnificaţ ie
ACTION_VIEW Ur i reprezentâ nd con ţ inutul Lansează o apli caţ ie pe baza
care va fiî ncă rcat î napli caţ i a asoci erii acest ei a cu un anu mi t
asociată . tip de conţ inut.
ACTION_CALL Ur i reprezentâ nd un num ă rDeschide fereastra de apelare a
de telefon (schema tel://).
apelul.
ACTION_DIAL Deschide fereastra de iniţ iere a
apelurilor telefonice.
ACTION_PICK Ur i reprezentâ nd con ţ inutul
care va fiî ncă rcat î napli caţ i a dintr-o listă .
as oci ată î n veder ea
selectă rii.
ACTION_EDIT Ur i asoci at con
ț inut ul ui care
va fi editat datelor.
ACTION_WEB_SEARCH Ur i reprezentâ nd secvenţ aDeschide o fereastră de că utare.
de că utat sau un URL care va
fi deschisî n navigatorul Web.
Categorii
• Asociate componentei care prelucrează mesajul
• Informații suplimentare cu privire modalitatea de lansare a
activității destinație
• Exemple
– CATEGORY_LAUNCHER
– CATEGORY_HOME
– CATEGORY_PREFERENCE
Constructori
• Mesaje generice
– Fără parametri
• Mesaje implicite
– Acțiune (String)
– Acțiune (String) și date (Uri)
• Mesaje explicite
– Context și componentă (Class)
– Acțiune (String), date (Uri), Context și componentă (Class)
Modificarea proprietăților
• setAction(String)
• addCategory(String)
• setData(Uri)
• setType(String)
– Tip MIME
• setDataAndType()
• setComponent(Context)
• setClass(Class)
Transmiterea și filtrarea mesajelor
• Orice componentă Android (activitate, serviciu, receptor)
poate fi informată prin intermediul mesajelor (Intent)
• Includerea de filtre (XML și/sau cod)
• Filtre
– Acțiune: ACTION_VIEW, ACTION_PICK etc.
• Categorie (android.intent.category): DEFAULT, LAUNCHER, TAB etc.
– Tip conținut
• Protocol: http, content, geo etc.
• MIME: text/plain, vnd.android-dir/mms-sms etc.
Transmiterea și filtrarea mesajelor
• Componentele includ filtre de mesaje
– Acțiune, tip date, protocol etc.
• După transmiterea unui mesaj
– Sistemul identifică acele componente care corespund mesajului (filtrare)
– Dacă există una sau mai multe componente
• Sînt invocate direct
• Utilizatorul selectează componenta dintr-o listă de componente
– Dacă nu există
• Excepție
Filtrarea mesajelor (XML)
• Elementul intent-filter în fișierul manifest
• Pot fi mai multe intrări de acest tip
• Este asociat unei componente:
<componenta>
<intent-filter>
<action android:name="actiune" />
<category android:name="categorie" />
<data android:scheme="protocol"/>
</intent-filter>
</componenta>
• Pot include priorități în tratarea acestora de către componente
(activități/receptori
– android:priority
Lansarea unei activități din proiect
• Intent explicit
• Parametri constructor Intent:
– Contextul curent
– Clasa activității destinație
• Metode (clasa Context):
– startActivity(Intent)
Lansarea unei activități

startActivity(intent)
+ date (opțional)
Activitate 1 Activitate 2

intent.putExtra(cheie, valoare) În onCreate()


valoare = getIntent().getExtras().get(cheie)
Lansarea unei activități cu transmitere de date:
Exemplu
/*
Din activitatea de curentă (referită prin this) este lansată activitatea de tip
ActivitateIntrebari
*/
Intent intent = new Intent(this, ActivitateIntrebari.class);
//se transmite un parametru
intent.putExtra("idTest", 1001);
//se lansează activitatea
startActivity(intent);
Preluarea datelor în activitatea invocată: Exemplu
@Override
public void onCreate(Bundle stare)
{
super.onCreate(stare);
//obținere container date
Bundle param = getIntent().getExtras();
//se testează în prealabil dacă param este null
int idTest = param.getInt("idTest")
//…SAU
int idTest = getIntent().getIntExtra("idTest", 0);

}
Mesaje implicite
• Pe baza unei acțiuni precizate
• Componentele (activități, servicii) se înregistrează pentru
diferite acțiuni
• Rezultat
– Excepție: Nici o componentă înregistrată
– Lansare componentă: există o singură componentă înregistrată sau
implicită
– Selecție componentă: mai multe componente înregistrate, nici una
implicită; utilizatorul va opta pentru o componentă
Mesaje implicite: Exemplul 1
//Deschiderea navigatorului Web pe baza unui URL:

Intent intent2 = new Intent(Intent.ACTION_VIEW);


intent2.setData(Uri.parse("http://www.ase.ro");
startActivity(intent2);
Mesaje implicite: Exemplul 2
//Deschiderea navigatorului Web pe baza unui URL
//cu verificarea existenței unei aplicații înregistrate

Intent intent2 = new Intent(Intent.ACTION_VIEW);


intent2.setData(Uri.parse("http://www.ase.ro");

if (intent2 .resolveActivity(getPackageManager()) != null) {


startActivity(intent2);
}
Lansarea unei activități pentru răspuns
Activitatea apelantă (1)
1. Inițializare mesaj explicit
– Context + componentă
2. Adăugare date mesaj (opțional)
– putExtras()/putExtra()
3. Invocare activitate (metodă clasa Activity)
– startActivityForResult(Intent, codCerere)
Lansarea unei activități pentru răspuns
Activitatea invocată
4. Obținere mesaj
– getIntent()
5. Preluare date adiționale (opțional)
– getExtra()/getTIPExtras()
6. Adăugare răspuns în mesaj
– putExtras()/putExtra()
7. Stabilire rezultat activitate
– setResult()
• RESULT_OK, RESULT_CANCELED
8. Finalizare activitate
– finish()
Lansarea unei activități pentru răspuns
Activitatea apelantă (2)
9. Preluare răspuns
– supraîncărcare metodă clasa Activity
– onActivityResult(codCerere, codRezultat, Intent)
• codRezultat = RESULT_OK, RESULT_CANCELED, …
Lansarea unei activități pentru răspuns

startActivityForResult(cod, intent)
Activitate Activitate
1 2

intent = getIntent()
onActivtiyResult(cod, codRez, intent) setResult(RESULT_OK, intent);

finish()
Lansarea unei activități pentru răspuns:
Exemplul 1
//Selectarea unui imagini din galerie

final int SEL_IMAGINE = 100;

//lansare activitate de selecție imagine din galerie


Intent intent = = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, SEL_IMAGINE );

//după efectuarea selecției sau renunțare


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

if ((requestCode == SEL_IMAGINE ) && (resultCode == RESULT_OK)) {


Uri uriImagine = intent.getData();
//prelucrare uriImagine
}
}
Lansarea unei activități pentru răspuns:
Exemplul 2
//Selectarea unui contact

final int SEL_CONTACT = 100;

//lansare activitate de selecție contact


Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
startActivityForResult(intent, SEL_CONTACT);

//după efectuarea selecției sau renunțare


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

if ((requestCode == SEL_CONTACT) && (resultCode == RESULT_OK)) {


Uri uriContact= intent.getData();
//prelucrare uriContact cu un furnizor de conținut
}
}
ACCESUL LA REȚEA
Accesul la rețea
• Controlul WebView
• Clase acces prin socket
– Socket
– ServerSocket
– DatagramSocket
• Clase HTTP API
– Java SE
Accesul la rețea
• Permisiunea android.permission.INTERNET
– Excepție
• Prelucrările au loc într-un alt fir de execuție
– Excepție
WebView
• Afișare conținut HTML
• Implicit JavaScript nu este activat
– WebSettings
• getSettings()
• loadUrl()
– Adresa paginii
• loadData()
– Conținut HTML
Accesul prin HTTP
• Specific Java SE
• Pachetul java.net
• Resursa
– URL
• Conexiune
– HttpURLConnection
– HttpsURLConnection
HTTP/HTTPS
1. Inițializare obiect URL
– adresa resursei
2. Inițializare conexiune prin intermediul obiectului URL
– Metoda URL#openConnection()
• HttpURLConnection
3. Stabilire parametri
4. Prelucrare conținut
– HttpURLConnection#getInputStream()
HTTP: Exemplu
URL url = null;
HttpURLConnection conn = null;

try {
url = new URL("http://pdm.ase.ro");
conn = (HttpURLConnection)url.openConnection();
// preluare raspuns
InputStream is = conn.getInputStream();
/*prelucrare conținut*/
}
catch (Exception e) {/*tratare excepție*/ }
finally {
if (conn != null)
conn.disconnect();
}
Prelucrare conținut
• Fluxuri de date
• Octeți
– InputStream
• ByteArrayInputStream
• Caractere
– InputStreamReader
– BufferedReader
• StringBuilder
• StringBuffer
– sincronizat
Descărcarea fișierelor
• Serviciul de sistem DownloadManager
– getSystemService(DOWNLOAD_SERVICE)
• Inițiere
– enqueue()
• Verificare stare transfer
• REVENIRE
– Servicii, Recepționarea mesajelor (BroadcastReceiver), Cursor
SERVICII WEB
Servicii Web
• Oferă un mijloc standard de interoperare între aplicațiile
software care rulează pe o varietate de platforme și
framework-uri
• În mod uzual, clientul și serverul comunică prin HTTP prin
intermediul WWW
• Disponibile în rețeaua Internet sau rețele private (intranet)
• Nu sînt legate de nici un sistem de operare sau limbaj de
programare
• Caracteristici: interoperabilitatea și extensibilitatea
Servicii Web
• SOAP
– Mesaje XML
– WSDL
• REST, RESTful (Representational State Transfer)
– XML, JSON, HTML
Servicii Web SOAP
• Biblioteca kSOAP2
• Se creează un mesaj SOAP
– clasa SoapSerializationEnvelope
• detaliile cererii se adaugă la mesaj prin intermediul clasei
SoapObject;
• Clasa HttpTransportSE este utilizată pentru a efectua apelul real al
metodei serviciului Web, mesajul fiind transmis ca parametru.
– metoda call()
• Rezultatul este preluat de la partea de răspuns a mesajului
– getResponse()
Servicii Web REST
• Acțiunile sunt implementate uzual prin protocolul HTTP
• Comenzi (GET, POST, DELETE etc.) asociate acțiunilor
• Rezultatul returnat
– JSON
– XML
OPERAȚII ASINCRONE
Operații asincrone
• Activități consumatoare de resurse
– intrare/ieșire, prelucrări complexe etc.
• Se realizează fără a bloca firul principal execuție
– Evitarea blocării interfeței aplicației
– Pot rula în alt fir de execuție
• Transmiterea parametrilor
• Problemă: actualizarea componentelor grafice din alt fir de
execuție decât cel în care au fost create
Operații asincrone
Alt fir de execuție Firul principal de execuție

Prelucrare de durată +
Control
rezultat
Control.proprietate = rezultat

NU
Prelucrare de durată +
rezultat
Control.proprietate = rezultat
Operații asincrone
• Java
– clasa Thread
– interfața Runnable
• Android
– clasa Handler
– Metode
• runOnUiThread(Runnable) (clasa Activity)
• post(Runnable) (clasa View)
• postDelayed(Runnable, long) (clasa View)
– clasa AsyncTask
CLASA HANDLER
Clasa Handler
• Transmiterea de obiecte de tip Message și Runnable
• Recepționarea de obiecte de tip Message
• Obiectele sunt transmise între fire de execuție diferite
• Fiecare obiect de tip Handler este asociat
– unui fir de execuție
– unei cozi de mesaje
Clasa Handler
• Prelucrarea mesajelor
– metoda cu apel invers handleMessage()
• Trasmiterea mesajelor
– metode de forma sendYYY()
Clasa Handler
• Obiecte de tip Runnable
– Transmise către coada de obemesaje asociată firului de execuție
• Trasmiterea obiectelor Runnable
– Metode de forma postYYY()
Clasa Handler

Handler

Coada Looper
Fir secundar de
mesaje

Firul principal UI
Inițializare Handler
• Constructor fără parametri
– Asociat firului curent
• Constructor cu un obiect de tip Looper
– Clasă care rulează bucla de mesaje a unui fir de execuție
– Looper.getMainLooper()
• Constructor cu un obiect pentru preluarea apelurilor inverse
– Handler.Callback
• Constructor cu doi parametri
Exemplu: Transmitere mesaj din alt fir de execuție
//inițializare mesaj
Message mesaj = new Message();
mesaj.obj = obiectul_de_transmis;
mesaj.what = cod_mesaj;

Handler handler;
//inițializare handler …

//trimire mesaj
handler.sendMessage(mesaj);
Exemplu (cont.): Receptionare mesaj în firul
principal
//definire la nivelul activității
Handler handler = new Handler() {

@Override
public void handleMessage(Message mesaj) {
switch (mesaj.what) {
case cod_mesaj:
//prelucrare
break;
}
super.handleMessage(mesaj);
}
};
Exemplu: Transmitere obiect Runnable
Handler handler = new Handler();
//...
handler.post(new Runnable() {
@Override
public void run() {
// prelucrări actualizare
}
});
Exemplu: Splash Screen
public class SplashScreen extends Activity {

final int DURATA_AFISARE = 3000;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setari fereastra (full screen)
setContentView(R.layout.splash_screen);
...
Exemplu: Splash Screen
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// dupa scurgerea timpului se apeleaza activitatea principala
Intent i = new Intent(SplashScreen.this, ActivityMain.class);
startActivity(i);
// inchiderea activitatii splash
finish();
}//end run
}, DURATA_AFISARE);
}//end onCreate()
}//end Activitate
Exemplu: Splash Screen
//ascundere titlu
requestWindowFeature(Window.FEATURE_NO_TITLE);
//afisare pe tot ecranul
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN
);
Operații asincrone
Firul principal de execuție

run() Runnable Control

Prelucrare de durată + rezultat Thread

run() Runnable
Control.proprietate = rezultat

Transmise ca parametri
metodelor specifice
METODE SPECIFICE
Metode specifice
• Clasa Activity
– runOnUiThread(Runnable)
• View
– post(Runnable)
– postDelayed(Runnable, long)
Exemplu: runOnUiThread()
this.runOnUiThread(new Runnable() {
@Override
public void run() {
editText.setText(text);
}
});
CLASA ASYNCTASK
Clasa AsyncTask
• Clasa abstractă AsyncTask<param, prog, rez>
• Metode cu apel invers:
– doInBackground(param… pars)
– onProgressUpdate(prog…pars)
• publishProgress()
– onPostExecute(rez par)
– onPreExecute()
• Lansarea în execuție
– metoda execute(param)
Clasa AsyncTask
• onPreExecute()
– Rulată înainte de începerea prelucrărilor
• doInBackground()
– Execută operația de lungă durată
– Rulată în mod asincron
• onProgressUpdate()
– Se apelează periodic pentru afișarea progresului operației de lungă durată
– Invocată după apelurile metodelor de tip publishProgress()
• onPostExecute()
– Se apelează după încheierea prelucrărilor
– Primește ca parametru obiectul rezultat în urma prelucrărilor
Apelurile Clasa AsyncTask
Firul principal Firul secundar
• 1. onPreExecute()

• 2. doInBackground()
• 4. onProgressUpdate() • 3. publishProgress()

• 5. onPostExecute()
Exemplu AsyncTask
//Parametrul transmis este un URL //Apelul din firul principal
//Rezultatul este un şir de caractere (String) URL url = new URL("http://pdm.ase.ro");
//progresul nu este monitorizat (Void)
class PrelAsinc extends AsyncTask<URL, Void, String> { PrelAsinc pa = new PrelAsinc ();

@Override pa.execute(url);
protected String doInBackground(URL... url) {
//acces url: url[0]
//conectare la server si preluare continut
return un_string;
}

@Override
protected void onPostExecute(String un_string) {
//actualizare element interfata grafica;
textView.setText(un_string);
}
}
FIȘIERE XML ȘI JSON
Fișiere XML
• Noduri/elemente
• Un nod rădăcină
• Atribute
Fișiere XML
<?xml version="1.0" encoding="ISO-8859-1"?>

<element_radacina>
<element atribut="val_atribut">
val_element sau alte elemente
</element>

</element_radacina>
Fișiere XML
<?xml version="1.0" encoding="ISO-8859-1"?> <carte cota="19223">
<biblioteca> <autor>
<carte cota="19222"> <nume>S. Hashimi</nume>
<autor> <nume> S. Komatineni</nume>
<nume>R. Meier</nume> <nume> D. MacLean </nume>
</autor> </autor>
<titlu> Professional Android Application <titlu>Pro Android 3</titlu>
Development </titlu> <editura>Apress</editura>
<editura>wiley</editura> <an>2011</an>
<an>2009</an> <isbn>0-321-15040-6</isbn>
<isbn>1-72-11-2222</isbn> <pagini>336</pagini>
<pagini>500</pagini> </carte>
</carte> </biblioteca>
Fișiere JSON
• JavaScript Object Notation
• { } – obiect
• [ ] – vector de valori
• "proprietate" : "valoare"
Fișiere JSON
{
"biblioteca": {
"carte": [
{
"-cota": "19222", "autor": { "nume": "R. Meier" }, "titlu": " Professional Android Application
Development ", "editura": "wiley", "an": "2009", "isbn": "1-72-11-2222", "pagini": "500" },
{
"-cota": "19223", "autor": { "nume": [ "S. Hashimi", " S. Komatineni", " D. MacLean " ] }, "titlu":
"Pro Android 3", "editura": "Apress", "an": "2011",
"isbn": "0-321-15040-6", "pagini": "336"
}
]
}
}
PRELUCRAREA FIȘIERELOR XML ȘI JSON
Prelucrare fișiere XML
• SAX (Simple API for XML)
– org.xml.sax
– SAXParserFactory, SAXParser
– Parcurgere secvențială a documentului XML
– Evenimente – funcții cu apel invers
• XML Pull
– org.xmlpull.v1
– XmlPullParserFactory, XmlPullParser
– Parcurgere secvențială a documentului XML
– Evenimente – tratate imediat
• DOM
– org.w3c.dom
– DocumentBuilderFactory, DocumentBuilder, Document

– Nodurile sînt grupate în liste


SAX
• SAXParserFactory
– utilizată pentru crearea obiectelor de tip SAXParser
• SAXParser
– responsabilă cu prelucrarea fișierului XML
• XMLReader
– citirea fișierului XML
– metoda parse()
• Clasă derivată din DefaultHandler
Clasa derivată din DefaultHandler
• Metode apelate în timpul prelucrării
• startElement()
– apelată la începerea citirii unui nou element;
• endElement()
– apelată la sfârșitul citirii unui element;
• characters()
– apelată la apariția unei secvențe de caractere din cadrul unui element
• Se asociază la XmlReader
– setContentHandler()
• Preluare rezultat
SAX
SAXParserFactory fact = SAXParserFactory.newInstance();
SAXParser xmlParser = fact.newSAXParser();
XMLReader xmlReader = xmlParser.getXMLReader();
SAXHandler handler = new SAXHandler();

xmlReader.setContentHandler(handler);
xmlReader.parse(new InputSource(streamIn));
Exemplu SAX
XML Pull
• Interfața XmlPullParser
• Inițializare
– Resources#getXml()
• res/xml
– Xml.newPullParser()
– XmlPullParserFactory#newPullParser()
• XmlPullParserFactory
– XmlPullParserFactory.newInstance()
• Asociere flux de intrare (InputStream)
– setInput()
XmlPullParser
• next() – parcurgerea documentului
• Evenimente
– Tipuri: START_TAG/END_TAG, TEXT, START_DOCUMENT/END_DOCUMENT
– getEventType()
• nextToken() – parcurgerea cu evenimente adiționale
• getName() – obținere nume etichetă
• getText() – obținere conținut
• getAttributeCount() – număr atribute
• getAttributeValue() – valoare atribut
Exemplu XmlPullParser
static ArrayList<Carte> prelucreazaXML_Pull(InputStream isXML) {
ArrayList<Carte> lista = new ArrayList<Carte>();
Carte carte = null;
int event; String text = null;
try {
// creare parser
XmlPullParser xmlParser = Xml.newPullParser();
xmlParser.setInput(isXML, null);
event = xmlParser.getEventType();
while (event != XmlPullParser.END_DOCUMENT) {
String name = xmlParser.getName();
//aici este switch-ul de ală turi -->
event = xmlParser.next();
}
} catch (Exception e) {e.printStackTrace(); }
return lista;}
Exemplu XmlPullParser
switch (event) {
case XmlPullParser.START_TAG:
if (name.equals("carte")) {
carte = new Carte();
carte.setCota(xmlParser.getAttributeValue(null,"cota"));
}
break;
case XmlPullParser.TEXT:
text = xmlParser.getText();
break;
case XmlPullParser.END_TAG:
if (name.equals("titlu")) {
carte.setTitlu(text);
}
if (name.equals("carte")) {
lista.add(carte);
}
break;
}
DOM
• Interfețe
– Node
– Element (impl. Node)
– NodeList
• item(poz)
• Clasa DocumentBuilder
– metoda parse()
• InputStream
• Clasa Document (impl. Node)
DOM
– Document
• getElementsByTagName()
– NodeList
– Element
• getAttribute()
– Node
• getTextContent()
Exemplu DOM
DocumentBuilderFactory docBuilderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder =
docBuilderFactory.newDocumentBuilder();
//obținerea flux de intrare
InputStream is = getResources().openRawResource(R.raw.biblx);
//creare document
Document docXml = docBuilder.parse(is);
if (docXml != null) {
//obținere listă de noduri de tipul dat
NodeList carti = docXml.getElementsByTagName("carte");
//parcurgere listă
for (int i = 0; i < carti.getLength(); i++) {
//preluare și prelucrare noduri
Node nodCrt = carti.item(i);

if (nodCrt.getNodeType() == Node.ELEMENT_NODE) {
Element obj= (Element) nodCrt;
Carte carte = new Carte();
carte.cota = obj.getAttribute("cota");
carte.titlu = obj.getElementsByTagName("titlu").
item(0).getTextContent();
carte.isbn = obj.getElementsByTagName("isbn").
item(0).getTextContent();
}
}
}
Prelucrare fișiere JSON
• org.json
• JSONObject
– getTIP(): getString(), getBoolean(), getInt() etc.
– getJSONArray()
– getJSONObject()
• JSONArray
– length()
– getTIP(index)
Prelucrare fișiere JSON
JSONObject jObject = new JSONObject(stringJson);
JSONObject joBibl = jObject.getJSONObject("biblioteca");
JSONArray jaCarti = joBibl.getJSONArray("carte");

for (int i = 0; i < jaCarti.length(); i++) {


Carte carte = new Carte();
// preluare carte
JSONObject joCarte = jaCarti.getJSONObject(i);
String titlu = joCarte .getString("titlu");
carte.setTitlu(titlu);
int an = joCarte .getInt("an");
String cota = joCarte.getString("-cota");
….
}
Bibliografie
• S. Komatineni, D. MacLean – Pro Android 4, Apress, 2012
• R. Meier – Professional Android 4 Application Development,
Wiley, 2012
• P. Pocatilu, Programarea dispozitivelor mobile, Editura ASE,
2012
• P. Pocatilu, I. Ivan ș.a. – Programarea aplicațiilor Android,
Editura, ASE, 2015
• http://developer.android.com
Programarea Dispozitivelor
Mobile
Cursul 8 - 9
Sumar
• Stocarea persistentă a datelor
– Baze de date
• SQLite
– Room Persistence Library
– Stocarea în containerul aplicației
– Fișiere de proprietăți
– Fișiere
• Serializarea și deserializarea obiectelor
STOCAREA PERSISTENTĂ A DATELOR
Stocarea persistentă a datelor
• Suport
– Fișiere
– Baze de date SQLite
• Disponibilitate
– Pachetul aplicației
– Extern pachetului aplicației
• Acces
– Zona privată asociată aplicației
– Zona publică
• Mediul de stocare
– Mediu de stocare intern
– Mediul de stocare extern
• Modalități structurate de stocare
– Fișiere de proprietăți
– Baze de date SQLite
Stocarea datelor aplicației
• Zona privată de date
– /data/data/pachet_aplicație
• Zona privată de date (mediu extern de stocare)
– /dir_ext/Android/data/pachet_aplicație
• Subdirectoare
– cache
– databases
– shared_prefs
– files
– etc.
STOCAREA DATELOR ÎN BAZE DE DATE

SQLITE
Baze de date
• SQLite
• Baze de date relaționale
• Pachetul android.database.sqlite
SQLite
• Tipuri de date suportate
– INTEGER
– REAL
– TEXT
– BLOB
• Conversii între tipuri (relații de afinitate)
• Restricții
– nu suportă anumite tipuri de asociere (join)
– restricția de referențialitate
• nu este activată implicit
– nu suportă tranzacții imbricate
SQLiteDatabase
• Asociată bazei de date
• Crearea unei baze de date
– Clasa SQLiteDatabase
• metoda statică openDatabase()
• metoda statică openOrCreateDatabase()
– Clasa Context
• openOrCreateDatabase()
– Clasa SQLiteOpenHelper
• getReadableDatabase()
• getWritableDatabase()
• Închiderea conexiunii
– close()
Crearea bazelor de date (Exemple)
SQLiteDatabase bd =
SQLiteDatabase.openDatabase(
"pim.db", null);
//sau
SQLiteDatabase bd =
openOrCreateDatabase("pim.db",
Context.MODE_PRIVATE, null);
//…
bd.close();
SQLiteDatabase
• Comenzi SQL:
– execSQL() – nu returneaza valori
– rawQuery() – returneaza valori (Cursor)
• Metode specializate
– query()
– insert()
– update()
– delete()
Selecția
• Metoda query() (Parametri comuni)
– Numele tabelei
– Coloanele selectate
• String[]
– Criteriul de selecție (WHERE)
• String
– Valorile asociate parametrilor din criteriul de
selecție
• String[]
Selecția
– Grupare (GROUP BY)
• String
– Condiție de grup (HAVING)
• String []
– Ordinea de sortare (ORDER BY)
• String
• Returnează
– Cursor
Selecția (Exemplu)
Cursor cursor = bd.query(
"studenti",
null,//toate coloanele
null,//fara selectie
null,
null,//fara grupare
null,
null//fara ordine de sortare
);
Selecția (Exemplu)
Cursor cursor = bd.query(
"studenti",
new String[] {"matricola", "nume", "tip" }
"tip=?",
new String[] {"buget"},
null,//fara grupare
null,
"matricola ASC"
);
Inserarea
• Clasa ContentValues
– put("cheie", valoare);
• Metoda SQLiteDatabase#insert()
– Numele tabelei
– null, dacă obiectul ContentValues are valori/un
nume de coloană, în caz contrar
– Obiectul de tip ContentValues
Inserarea (Exemplu)
ContentValues valori = new ContentValues();

valori.put("matricola", 1200);
valori.put("nume", "student");

long rez = bd.insert("studenti" , null, valori)


Modificarea
• Metoda update()
– Numele tabelei
– Obiectul de tip ContentValues cu noile valori
– Parametri pentru clauza WHERE
– Argumentele pentru clauza WHERE
Modificarea (exemplu)
ContentValues valori = new ContentValues();

valori.put("nume", "student nou");

long rez;
rez = bd.update("studenti" , valori, null, null);
rez = bd.update("studenti" , valori, "matricola=?",
new String[] {String.valueOf(1200)});
Ștergerea
• Metoda delete()
– Numele tabelei
– Parametrii pentru clauza WHERE
– Argumentele pentru clauza WHERE
• Exemple
long rez;
rez = bd.delete("studenti" , null, null);
rez = bd.delete("studenti", "matricola=?",
new String[] {String.valueOf(1200)});
Tranzacții
• Inițierea tranzacției
– beginTransaction()
• Aplicarea modificărilor
– setTransactionSuccessful()
• Finalizarea tranzacției
– endTransaction()
Tranzacții (Exemplu)
SQliteDatabase bd = …;

bd.beginTransaction();
try {
opereazaAsupraBazeiDeDate();
bd.setTransactionSuccessful();
}catch (SQLException e) {
//Tratare exceptie
}finally {
bd.endTransaction();
}
SQLiteOpenHelper
• Suport pentru crearea/actualizarea schemei bazei de date
• Se creează o clasă derivată
• Implementate metode cu apel invers
• Crearea bazei de date
– onCreate()
• Actualizarea bazei de date
– onUpgrade()
• Obținerea unei baze de date SQLiteDatabase se realizează
cu metodele
– getReadableDatabase()
– getWritableDatabase()
Exemplu: SQLiteOpenHelper
public class DBHelper extends
SQLiteOpenHelper {
int versiune = 1;

public DBHelper (Context context) {


super(context, "pim.db", null,
versiune);
}
Exemplu: SQLiteOpenHelper(cont.)
@Override
public void onCreate(SQLiteDatabase bd) {
try {
bd.execSQL("CREATE TABLE Intilniri ...");
}
catch(SQLException ex) { ex.printStackTrace(); }
}
Exemplu: SQLiteOpenHelper (cont.)
@Override
public void onUpgrade(SQLiteDatabase bd, int versAnt,
int verNoua) {
try {
bd.execSQL("DROP TABLE IF EXISTS Intilniri");
onCreate(bd);
}
catch(SQLException ex) { ex.printStackTrace(); }
}
}
Exemplu
DBHelper mgrBD = new dbHelper(this);

SQLiteDatabase bd =
dbHelper.getWritableDatabase();


dbHelper.close();
Cursor
• android.database
• Interfață
• permite gestiunea înregistrărilor rezultate în
urma interogării unei baze de date
• SQLiteCursor
– Implementare pentru baze de date SQLite
Cursor
• Parcurgere
– moveToNext()
– moveToPrevious()
– moveToFirst()
– moveToLast()
• Extragerea de valori
– getTIP(): getInt(), getString(), getFloat() etc.
– parametru: indexul coloanei
Cursor: Determinarea poziției
• isFirst()
• isLast()
• isBeforeFirst()
• isBeforeLast()
Cursor: Obținerea de informații
• Numărul de înregistrări
– getCount()
• Numele coloanei
– getColumnName()
• Poziția coloanei
– getColumnIndex()
Adaptoare de tip Cursor
• CursorAdapter
• Coloana _id
• SimpleCursorAdapter
Exmeplu: SimpleCursorAdapter
SimpleCursorAdapter adapter = new SimpleCursorAdapter(
this, // contextul
android.R.layout.two_line_list_item, //sablonul liniei
cursor, // cursorul
new String[] { … }// lista numelor coloanelor,
new int[] { … } //lista identificatorilor de resurse asociate
);
STOCAREA ÎN CONTAINERUL
APLICAȚIEI
Stocarea în containerul aplicației
• Resurse
– Directoarele
• res/raw – orice tip de fișier
• res/xml – fișiere XML compilate
– Acces prin intermediul unui identificator de
resursă
• Directorul assets
– Prelucrare fluxuri de date
– Structurare directoare și fișiere
Stocarea în containerul aplicației
• getResources() -> Resources
• Fișiere din res/raw
– openRawResource() -> InputStream
• Fișiere din res/xml
– getXml() -> XmlPullParser
Stocarea în containerul aplicației
• AssetManager
– getAssets() (clasa Context)
• open(nume_fisier) -> InputStream
• list(cale)
– String[]
• Lista fișiere
FIȘIERE DE PROPRIETĂȚI
Fișiere de proprietăți
• Interfața SharedPreferences
• Stocarea persistentă de perechi de forma cheie-
valoare
• Tipuri pentru valorile stocate:
– boolean
– int
– float
– long
– String
– Set<String>
Obținere fișiere de proprietăți
• Metodă în clasa Context
– getSharedPreferences(String numeFisier, int mod)
– Mai multe fișiere de proprietăți/aplicație
• Metodă în clasa Activity
– getPreferences(int mod)
– Un singur fișier de proprietăți/aplicație/activitate
• Funcție statică în clasa PreferenceManager
– getDefaultSharedPreferences(context)
– Un singur fișier de proprietăți/aplicație/activitate
• Mod
– Activity.MODE_PRIVATE
Preluarea datelor
• Metode de forma getTIP()
– getBoolean(),
– getInt() etc.
Editare fișiere de proprietăți
• Clasa SharedPreferences.Editor
• Inițializare
– SharedPreferences#edit()
• Scriere
– Metode de forma putTIP()
• Ștergere preferințe
– remove()
• Ștergerea tuturor preferințelor
– clear()
• Salvare modificări
– commit() – apel sincron
– apply() – apel asincron
Fișiere de proprietăți
SharedPreferences setari = getSharedPreferences("setari",
Activity.MODE_PRIVATE);

SharedPreferences.Editor editorProp = setari.edit();

editorProp.putBoolean("titlu", false);
editorProp.putBoolean("ajutor", true);
editorProp.putInt("max", 5);

editorProp.commit();
Fișiere de proprietăți
SharedPreferences setari = getSharedPreferences("setari",
Activity.MODE_PRIVATE);

boolean fTitlu = setari.getBoolean("titlu", false);


boolean fAjutor = setari.getBoolean("ajutor", true);
int nMax = setari.getInt("max", 5);
Activități pentru salvarea preferințelor
• Clase
– PreferenceActivity
– PreferenceFragment
– PreferenceScreen
– PreferenceCategory
• Preferences
• Ferestre de dialog
– EditTextPreference
– ListPreference
– MultiSelectListPreference
• Controale
– CheckBoxPreference
– SwitchPreference
Activități pentru salvarea preferințelor
• PreferenceActivity
• PreferenceFragment
• Definire în fișier XML
Asociere conținut
– addPreferencesFromResource(R.xml.preferinte);
Exemplu: activitate pentru salvarea
preferințelor
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android" >

<PreferenceCategory android:title="Informatii conectare" >

<EditTextPreference
android:key="utilizator"
android:summary="Introduceti numele de utilizator"
android:title="Utilizator" />
Exemplu: activitate pentru salvarea
preferințelor (cont.)
<EditTextPreference
android:inputType="textPassword"
android:key="parola"
android:negativeButtonText="Renunta"
android:positiveButtonText="Accepta"
android:summary="Introduceti parola"
android:title="Parola" />

<CheckBoxPreference
android:key="raminConectat"
android:summary="Se mentine sau nu autentificarea"
android:title="Ramin conectat" />
</PreferenceCategory>
Exemplu: activitate pentru salvarea
preferințelor (cont.)
<PreferenceCategory
android:summary="Preferinte cu privire la fonturi si
culori"
android:title="Aspect" >
<ListPreference
android:entries="@array/optiuniCulori"
android:entryValues="@array/culoriDisponibile"
android:key="listaCulori"
android:negativeButtonText="Renunta"
android:summary="Selectati culoarea de fundal"
android:title="Culoarea de fundal" />
Exemplu: activitate pentru salvarea
preferințelor (cont.)
<MultiSelectListPreference
android:entries="@array/optiuniFont"
android:entryValues="@array/setariFontDisponibile"
android:key="listaFont"
android:summary="Selectati proprietatile fontului"
android:title="Aspect text" />

<SwitchPreference
android:key="modNoapte"
android:summary="Activarea automata a modului de noapte"
android:title="Mod de noapte" />
</PreferenceCategory>

</PreferenceScreen>
Exemplu: activitate pentru salvarea
preferințelor (cont.)
Activități pentru salvarea preferințelor
SharedPreferences preferinte = PreferenceManager
.getDefaultSharedPreferences(this);

boolean modNoapte =
preferinte.getBoolean("modNoapte", false);
String user = preferinte.getString("utilizator",
"neconectat");
String [] setariFonturi = new String[5];
preferinte.getStringSet("listaFont", new
HashSet<String>()).toArray(setariFonturi);
FIȘIERE
Fișiere
• Pot fi salvate în memoria persistentă
– internă
– externă
• Fişierele salvate în spaţiul de stocare intern
sunt accesibile implicit doar la nivelul
aplicaţiei
• Vor fi şterse odată cu dezinstalarea acesteia
Clasa Environment
• Mediul extern amovibil:
– isExternalStorageRemovable()
• Stare mediu extern stocare
– getExternalStorageState()
• MEDIA_MOUNTED
• MEDIA_MOUNTED_READ_ONLY
• MEDIA_UNMOUNTED
• MEDIA_REMOVED
Directoare speciale
• Clasa Environment, metode statice, rezultat File
• Directorul radăcină
– getRootDirectory()
• Directorul date utilizator:
– getDataDirectory()
• Director cache download:
– getDownloadCacheDirectory()
• Director mediu extern stocare:
– getExternalStorageDirectory()
Directoare speciale
• Director public mediu extern stocare
– getExternalStoragePublicDirectory(tip)
• tip (membri statici)
– DIRECTORY_PICTURES
– DIRECTORY_MUSIC
– DIRECTORY_DOWNLOADS
– DIRECTORY_DCIM
– DIRECTORY_RINGTONES
– DIRECTORY_ALARMS
Directoare speciale
• Clasa Activity (Context)
• Director date extern aplicației
– getExternalFilesDir()
• Directoare de date externe aplicației (API 19)
– getExternalFilesDirs()
• Director date
– getFilesDir()
• Director cache intern
– getCacheDir()
• Director cache extern
– getExternalCacheDir()
Clasa File

• Operații la nivel de fișier și director


• Obținere și stabilire proprietăți
• Mutare/redenumire
• Creare director
• Obținere conținut director etc.
Fișiere
• InputStream și OutputStream
– clase abstracte
– suport pentru operaţii cu fluxuri de date
• FileInputStream și FileOutputStream
– fluxuri de date la nivel de octet utilizate pentru
citirea şi scrierea din fişiere;
• FileReader și FileWriter
– fluxuri de date la nivel de caracter utilizate pentru
citirea şi scrierea din fişiere;
Fișiere
• InputStreamReader şi OutputStreamWriter
– fluxuri de date la nivel de caracter
– derivate din clasele Reader, respectiv Writer
– asociate unor obiecte de tip InputStream, respectiv
OutputStream;
– operaţiile de intrare-ieşire nu sunt realizate direct din
fişiere
• BufferedReader şi BufferedWriter –
– asociate unor obiecte de tip Reader, respectiv Writer
– permit efectuarea operaţiilor de intrare/ieşire prin
intermediul zonelor de memorie tampon (buffer).
Fișiere
• Metode în clasa Context
• FileInputStream openFileInput(String numeFisier)
• FileOutputStream openFileOutput(String
numeFisier, int mod)
– Context.MODE_PRIVATE/ Context.MODE_APPEND
• boolean deleteFile(String numeFisier)
• String[] fileList()
• File getDir(String numeDir, int mod)
Fișiere externe
• android.permission.WRITE_EXTERNAL_STORAGE
• Verificare disponibilitate mediu extern de
stocare
• Verificare drepturi citire/scriere
try {

// obtinere starea mediului de stocare extern


String stareSD = Environment.getExternalStorageState();

// daca este montat


if (stareSD.equals(Environment.MEDIA_MOUNTED)) {
// obtinerm director extern asociat aplicatiei

File dir = getExternalFilesDir(null);

if (dir != null) {
// creare fisier
File fis = new File(dir, NUME_FISER2);
FileWriter os = new FileWriter(fis);
os.write("PDM 2014");
os.close();
}
}
} catch (IOException ex) {

ex.printStackTrace();
}
SERIALIZAREA ȘI DESERIALIZAREA
OBIECTELOR
Modalități de serializare
Serializable Parcelable
• Java • Android
• Stocare • Transport
• Versionare – Comunicație între procese
• Simplitate vs. viteză redusă • Parcel
de prelucrare • Eficiență vs. complexitate
– reflection
Interfața Serializable
• java.io
• ObjectOutputStream
• ObjectInputStream
• transient
– cîmpurile nu vor fi serializate
• Metodele interfeței
– void writeObject(ObjectOutputStream out)
– void readObject(ObjectInputStream in)
Clasa Parcel
• Container de date
• Transport interproces
• Tipuri simple
– writeByte(), writeDouble(), writeString() etc.
– readByte(), readDouble(), readStrin() etc.
• Tipuri complexe
– writeList(), writeBundle(), writeStringArray() etc.
– readList(), readBundle(), readStringArray() etc.
Interfața Parcelable
• android.os
• Metoda writeToParcel()
– Scrie obiectul într-un Parcel
• Constructor care primește un obiect de tip Parcel
– Inițializează obiectul dintr-un Parcel
• Metoda describeContents()
• Cîmpul static CREATOR
– Implementează interfața ParcelableCreator
– Apelează constructorul cu parametrul de tip Parcel
Interfața Parcelable
• void writeToParcel(Parcel dest, int flags)
• Clasa(Parcel in)
• public static final Parcelable.Creator<Clasa> CREATOR =
new Parcelable.Creator<Clasa>() {
public Clasa createFromParcel(Parcel pc) {
return new Clasa(pc);
}
public Clasa[] newArray(int dim) {
return new Clasa[dim];
} };
• public int describeContents()
Bibliografie
• S. Komatineni, D. MacLean – Pro Android 4, Apress,
2012
• R. Meier – Professional Android 4 Application
Development, Wiley, 2012
• P. Pocatilu, Programarea dispozitivelor mobile,
Editura ASE, 2012
• P. Pocatilu, I. Ivan ș.a. – Programarea aplicațiilor
Android, Editura, ASE, 2015
• http://developer.android.com
Programarea Dispozitivelor Mobile

Cursul 10
Sumar
• Baze de date la distanță
• Firebase
• Baze de date Firebase
BAZE DE DATE LA DISTANȚĂ
Baze de date la distanță
• Partajarea datelor
• Sincronizarea datelor
• Datele sînt stocate pe un server
Baze de date la distanță
Soluții
• Baze date + Aplicație + API
• Baze date + Aplicație Web
• Baze date + Servicii Web
• Platforme online dedicate
– Firebase
– Restdb.io
– kumulos
FIREBASE
Firebase
• Platformă proiectată să asigure integrarea soluțiilor bazate pe
cloud în aplicații
• Aplicații mobile
– Android
– iOS
• Aplicații Web
Componente Firebase
• Authentication
– Suport pentru gestiunea conturilor și autentificarea în aplicații
• Cloud Storage
– Stocarea de fișiere
• Crash Reporting
– Informații cu privire la problemele apărute în aplicații
• Hosting
– Găzduire aplicații Web
• Realtime Databases
– Stocarea și sincronizarea datelor
Componente Firebase
• Google Analytics
– Statistici cu privire la utilizarea aplicațiilor
• Dynamic Links
– Referirea dinamică a conținutului (aplicații sau Web)
• Cloud Messaging
– Transmiterea de mesaje și notificații
Firebase
• Conectarea prin intermediul unui cont Google
• https://firebase.google.com/
• Consola pentru gestiunea proiectelor
• https://console.firebase.google.com/
• Integrarea în aplicațiile Android
– Manual
– Android Studio | Tools | Firebase
FIREBASE REALTIME DATABASE
Firebase Realtime Database
• Baze de date în timp real
• NoSQL
• Date stocate în format JSON
• Autentificare
• Multiplatformă
• Găzduire în cloud
• Sincronizare
Tipuri de date suportate
• String
• Boolean
• Long
• Double
• Map<String, Object>
• List<Object>
Structura datelor
• Format JSON
• Fără vectori
• Maxim 32 nivelul de imbricare
• Aspecte de luat în considerare la proiectare
– Evitarea imbricării datelor pe foarte multe niveluri
– Date nenormalizate
Clase și interfețe
• FirebaseDatabase
• DatabaseReference
• DataSnapshot
• ValueEventListener
• ChildEventListener
Accesul la baza de date
• Referirea bazei de date
– FirebaseDatabase database = FirebaseDatabase.getInstance();
Referirea datelor
• Referință la elementul rădăcină
– DatabaseReference dbRef = database.getReference();
– DatabaseReference dbRef = database.getReference("/");
• Referință la un element specific
– DatabaseReference refCarti = database.getReference("carti");
• Referință unui sub-element
– database.getReference("carti").child(cota);
– database.getReference("/carti/cota");
• Dacă elementele nu există, acestea vor fi create
Salvarea datelor
• Adăugarea/înlocuirea unei valori
– refCarteNoua.setValue(carte);
• Generarea unei valori unice și inserarea acesteia
– databaseReference.push();
• Generarea, inserarea și obținerea unei valori unice
– String cheie = databaseReference.push().getKey();
Preluarea datelor
• Clasa DataSnapshot
• Copie nemodificabilă a datelor referite
• Metode
– child(cale)
• Obiect de tip DataSnapshot asociat căii
– getValue(Clasa.class)
• Clasa trebuie să aibă constructor implicit
– getRef()
• Referința la sursa asociată datelor
– hasChildren()
– getChildrenCount()
Preluarea datelor
• ValueEventListener
– onDataChange(DataSnapshot)
– onCancelled(DatabaseError)
• Asociere (prin DatabaseReference)
– addValueEventListener()
– addListenerForSingleValueEvent()
• Eliminare asociere
– removeEventListener()
Modificarea datelor
• Metoda updateChildren(Map)
• Obiectul de tip Map include
– Proprietățile care se modifică (sau calea)
– Valorile asociate
• Posibilitatea de modificare a mai multor valori
• refCarti.updateChildren(map)
Ștergerea datelor
• removeValue()
• setValue(null)
• updateChildren(map)
– valorile din map sînt nule
Interogarea datelor
• Clasa Query
• Sortare
– Cheie
– Valoare
– Valoare copil
• Indexare pentru îmbunătățirea performanțelor
• Operațiile returnează tot obiecte de tip Query
• Preluarea datelor se realizează prin intermediul aceluiași
mecanism
Interogarea datelor
• Sortare
– orderByChild()
– orderByKey()
– orderByValue()
• Filtrare
– equalTo()
– startAt()
– endAt()
– limitToFirst()
– limitToLast()
Monitorizarea actualizărilor
• ChildEventListener
• Metode
– abstract void onChildAdded(DataSnapshot snapshot, String
previousChildName)
– abstract void onChildChanged(DataSnapshot snapshot, String
previousChildName)
– abstract void onChildMoved(DataSnapshot snapshot, String
previousChildName)
– abstract void onChildRemoved(DataSnapshot snapshot)
– abstract void onCancelled(DatabaseError error)
AUTENTIFICARE/ÎNREGISTRARE
Autentificare/Înregistrare
• Furnizori multipli
• Definire din consola Firebase
• Clase specializate
Furnizori
• Email + parolă
• Google
• Facebook
• Twitter
• GitHub
Clase și interfețe
• FirebaseAuth
– AuthStateListener
• FirebaseUser
Înregistrare/autentificare
FirebaseAuth auth = FirebaseAuth.getInstance();
FirebaseUser user = auth.getCurrentUser();

if (user != null) {
//continuare in aplicatie
} else {
//autentificare utilizator
}
CLASE SUPORT
FirebaseUI
• https://github.com/firebase/FirebaseUI-Android
• FirebaseUI for Android — Auth
– AuthUI
• FirebaseUI for Realtime Database
– FirebaseListAdapter
– FirebaseRecyclerAdapter
Bibliografie
• Neil Smyth, Firebase Essentials Android Edition, Payload Media, 2017
• https://firebase.google.com/docs/reference/
• http://developer.android.com
Dispozitive și Aplicații Mobile

Cursul 11
Sumar
• Grafică bidimensională
– Imagini
– Culori, instrumente, suprafața de scris
– Figuri geometrice
• Preluarea imaginilor folosind camera foto
• Preluarea imaginilor din colecția de fotografii
Resurse de tip multimedia
• Fișiere
– Imagini
– Clipuri audio
– Clipuri video
• În memorie
– Grafică bi și tridimensională
– Secvențe audio
– Animații (bi și tridimensionale)
GRAFICĂ BIDIMENSIONALĂ
Grafică bidimensională
• Desenarea imaginilor în memorie
– Clasa Bitmap
• Culori și texturi
• Instrumentul de desenat
– clasa Paint
• Suprafața de desenat
– clasa Canvas
• Figuri geometrice
– ShapeDrawable
Desenare imagini în controale
• ImageView
• Drawable (clasă abstractă)
– res/drawable, res/raw
– Imagini
• Fișiere grafice
– Figuri
• Fișiere xml
• Canvas
– Desen liber/figuri
– android.graphics
Imagini
• Bitmap
• Modificabile sau nemodificabile
• Metode statice
– createBitmap(lat, inalt, config)
• Bitmap.Config
– createBitmap(srcBitmap) + alte supraîncărcări
– createScaledBitmap(src, wDest, hDest, filtru)
• Metode
– compress(format, calitate, flux_de_iesire)
– getWidth(), getHeight()
• BitmapFactory
– Creare de obiecte de tip Bitmap din diferite surse
– Metode statice de tipul decodeSURSA()
• Resource, Stream, File etc.
Imagini
int w, h;
Bitmap bmp1 = Bitmap.createBitmap(w, h,
Bitmap.Config.ARGB_8888);

Bitmap bmp2 =
BitmapFactory.decodeResource(
getResources(), R.drawable.dice);
Componente de bază
• Culori și texturi
• Instrumentul de desenat
• Suprafața de desenat
– Contururi geometrice
Culori
• Clasa Color
– Constante (RED, BLUE etc.)
– Metoda statică argb(a, r, g, b)
– Metoda statică parseColor(String)
• #RRGGBB
• #AARRGGBB
• Nume culoare
• Resurse
– Resources#getColor()
• res/values
Culori
• int culoare = getResources().getColor(R.id.fundal);
• int verde = Color.GREEN;
• int verdeSemiTransp = Color.argb(127, 0, 255, 0);
Gradienți
• Culori și sau imagini
– clasa Shader si derivate
• Modul de umplere:
– repetarea șablonului (Shader.TileMode.REPEAT)
– repetarea șablonului cu alternarea imaginii
inversate (Shader.TileMode.MIRROR)
– replicarea culorii exterioare la depășirea limitelor
(Shader.TileMode.CLAMP).
Gradienți
• clasa Shader şi subclasele acesteia
• BitmapShader – desenarea folosind imagini
• LinearGradient – gradienți liniari
• RadialGradient – gradienți circulari
• SweepGradiet – gradienți unghiulari
• ComposeShader – combinarea doi gradienți.
Gradienți
Bitmap bmpShader;

BitmapShader gradientBmp = new


BitmapShader(bmpShader,
Shader.TileMode.REPEAT,
Shader.TileMode.REPEAT );

LinearGradient gradientLinear = new


LinearGradient(0, 0, 150, 150, Color.RED,
Color.BLUE, Shader.TileMode.CLAMP);
Instrumentul de desenat
• Clasa Paint
• Gestionează proprietățile referitoare la desenarea
figurilor, textului și imaginilor
• Include metode pentru proprietăți
– culoare
– grosime
– stilul liniei
– font
– alte efecte speciale
• Majoritatea metodelor de desenare au un parametru
de tip Paint
Clasa Paint
• Stabilire culoare
– void setColor(int culoare)
– void setARGB(int a, int r, int g, int b)
• Proprietăți text
– void setTextAlign(Paint.Align align)
– void setTextSize(float textSize)
Clasa Paint
• Proprietăți linie contur/umplere:
– void setStyle(Paint.Style style)
– void setStrokeWidth(float width)
– PathEffect setPathEffect(PathEffect effect)
– void setAntialias(boolean aa)
• Inițializare gradient
– Shader setShader(Shader shader)
Clasa Paint
Paint creionGrad = new Paint(), creionNegru = new Paint(),
creionText = new Paint();

creionNegru.setColor(Color.BLACK);
creionNegru.setStyle(Paint.Style.STROKE);
creionNegru.setAntiAlias(true);

creionText.setTextAlign(Paint.Align.CENTER);
creionText.setColor(Color.GREEN);
creionText.setTextSize(24);

creionGrad.setShader(gradientBmps);
creionGrad.setStrokeWidth(30);
Suprafața de desenare
• Clasa Canvas
• Include metode pentru desenare
• Metode de tipul draw…()
• Instrumentul de scris
• Poziția
Desenarea în controale
• Clasa derivată din View
• Metoda cu apel invers onDraw()
– de evitat alocarea obiectelor grafice aici
• Metodele
– invalidate()
– postInvalidate()
Canvas
public class DesenView extends View {

protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//desenarea propriu-zisă
}
}
Desenarea în imagini (Bitmap)
• Se utilizează constructorul
– Canvas(Bitmap)
• Pași
– Crearea/Obținerea unui obiect de tip Bitmap
• Bitmap bmp = Bitmap.createBitmap(l, L, tip);
– Inițializarea obiectului de tip Canvas
• Canvas canvas = new Canvas(bmp);
Desenarea figurilor geometrice
• void drawPoint(float x, float y, Paint paint)
• void drawPoints(float[] pts, int offset, int
count, Paint paint)
• void drawLine(float startX, float startY, float
stopX, float stopY, Paint paint)
• void drawLines(float[] pts, Paint paint)
Desenarea figurilor geometrice
• void drawRect(RectF rect, Paint paint)
• void drawRoundRect(RectF rect, float rx, float
ry, Paint paint)
• void drawCircle(float cx, float cy, float radius,
Paint paint)
• void drawOval(RectF oval, Paint paint)
• void drawArc(RectF oval, float startAngle,
float sweepAngle, boolean useCenter, Paint
paint)
Afișarea imaginilor
• void drawBitmap(Bitmap bmp, float left, float
top, Paint paint)
• void drawPicture(Picture picture, RectF dst)
Modificarea fundalului
• void drawColor(int color)
• void drawRGB(int r, int g, int b)
• void drawARGB(int a, int r, int g, int b)
• void drawPaint(Paint paint)
Afișarea textului
• void drawText(String text, float x, float y,
Paint paint)
Contururi geometrice - clasa Path
• Suport pentru grafică vectorială
• Permite crearea de contururi geometrice bazate
pe linii și curbe
• Adăugarea de conturi geometrice:
– addCircle()
– addRect()
– addArc()
– etc.
• Combinarea contururilor
– addPath()
Exemplu: Canvas
//culoare fundal
canvas.drawColor(Color.YELLOW);
//linie
canvas.drawLine(10, 10, 300, 4000, creion); //----------creion este de tip Paint
//cerc
canvas.drawCircle(100, 100, 50, creion);
// dreptunghi
canvas.drawRect(rect, creion); //---------rect este de tip Rect sau RectF
//elipsa
canvas.drawOval(rect, creion);
//creare contur geometric
path.addArc(rect, 270, 90);//--------------path este de tip Path
// desenare dupa contur
canvas.drawPath(path, creion);
// scriere text dupa contur
canvas.drawTextOnPath("Contur arc", path, 0, 40, creion);
Desenare/afișare text după contururi
geometrice
• void drawPath(Path path, Paint paint)
• void drawTextOnPath(String text, Path path,
float hOffset, float vOffset, Paint paint)
Decuparea
• Zona de decupare (clip)
– stabilește suprafața care va fi desenată cu ajutorul
contextului dispozitiv (clasa Canvas)
– Inițial, zona de decupare coincide întregii ferestre.
• Modificarea zonei de decupare se realizează
prin metodele:
– clipRect()
– clipPath()
Transformări
• Scalare
– Metoda scale(sx, sy)
• Translatare (mutare)
– Metoda translate(dx, dy)
• Rotiri
– Metoda rotate(grade)
• Înclinare
– Metoda skew(x, y)
FIGURI GEOMETRICE
Figuri geometrice (Java)
• ShapeDrawable
• Construire obiecte de tip Shape
– RectShape
– OvalShape
– ArcShape
– PathShape
• Metode
– getPaint()
– draw(Canvas)
– setBounds(x1, y1, x2, y2)
Exemplu: Figuri geometrice (Java)
ShapeDrawable drawable;
Canvas canvas;
int x, y, width, height;

drawable = new ShapeDrawable(new RectShape());


drawable.getPaint().setColor(Color.RED);
drawable.setBounds(x, y, x + width, y + height);
drawable.draw(canvas);
Figuri geometrice (XML)
• Elementul shape
• Atributul android:shape reprezintă figura
– rectangle
– oval
– line
– ring
• Proprietăți (elemente XML incluse)
– stroke
– solid
– gradient
– size
Figuri geometrice (XML)
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="10dp" />
<size
android:height="@dimen/lat"
android:width="@dimen/lung" />
<solid
android:color="@android:color/transparent" />
<stroke
android:width="2dp"
android:color="#000000" />
</shape>
Figuri geometrice (XML)
• Referire XML:
– @drawable/numeFisierXMLFigura
• Referire Java
• R.drawable.numeFisierXMLFigura
• Resources#getDrawable
PRELUAREA IMAGINILOR FOLOSIND
CAMERA FOTO
Camera
• Acces prin aplicații dedicate
– Intent
• Utilizare clase specializate
– Camera
• android.permission.CAMERA
Camera: aplicații instalate
• Acces prin intermediul mesajelor (Intent)
• Captare imagini
– Acțiune MediaStore.ACTION_IMAGE_CAPTURE
• Captare video
– Acțiune MediaStore.ACTION_VIDEO_CAPTURE
Camera: aplicații instalate
• Lansare aplicație
– void startActivityForResult(Intent intent, int
codCerere)
• Preluare rezultat
– protected void onActivityResult (int codCerere, int
codRezultat, Intent intent)
Camera: aplicații instalate
final int CAPTEAZA_IMAGINE = 1;

//…
Intent capteazaImagine = new
Intent(MediaStore.ACTION_IMAGE_CAPTURE);

startActivityForResult(capteazaImagine,
CAPTEAZA_IMAGINE);
Camera: aplicații instalate
private Bitmap fotografie = null;
...
@Override
protected void onActivityResult(int codCerere,
int codRezultat, Intent data) {

if (codRezultat== Activity.RESULT_OK &&


codCerere ==CAPTEAZA_IMAGINE) {

Bundle rezultat = data.getExtras();


fotografie = (Bitmap) rezultat.get("data");
}
}
PRELUAREA IMAGINILOR DIN
COLECȚIA DE FOTOGRAFII
Preluarea imaginilor din colecția de
fotografii
final int SELECTEAZA_IMAGINE = 2;

//creare intent
Intent intent = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
//invocare activitate selectie imagine
startActivityForResult(intent, SELECTEAZA_IMAGINE);
Preluarea imaginilor din colecția de
fotografii
protected void onActivityResult(int codCerere, int codRezultat, Intent intent) {

if (codCerere == SELECTEAZA_IMAGINE && codRezultat == RESULT_OK) {


Uri uriImagine = intent.getData();
Bitmap bmp;
try {
bmp = MediaStore.Images.Media.getBitmap(
getContentResolver(), uriImagine);
//utilizare bmp

} catch (Exception e) {
e.printStackTrace();
}
}
}
Bibliografie
• S. Komatineni, D. MacLean – Pro Android 4, Apress,
2012
• R. Meier – Professional Android 4 Application
Development, Wiley, 2012
• P. Pocatilu, Programarea dispozitivelor mobile,
Editura ASE, 2012
• P. Pocatilu, I. Ivan ș.a. – Programarea aplicațiilor
Android, Editura, ASE, 2015
• http://developer.android.com
Dispozitive și aplicații mobile

Cursul 12
Sumar
• Utilizarea serviciilor Android
• Determinarea poziției geografice
• Google Maps în aplicații
SERVICII
Servicii
• Rutine care rulează în paralel cu firul principal
• Nu prezintă interfaţă grafică
• Permit derularea unor acţiuni în fundal fără a bloca firul
principal de execuţie şi interacţiunea cu aplicaţiile
• Servicii predefinite (sistem) și servicii utilizator
Servicii
• Servicii locale
– Rulează în același proces cu aplicația care a pornit serviciul
• Servicii la distanță
– Rulează în propriul proces
– Comunicare inter-proces
• RPC, AIDL (Android Interface Definition Language) etc.
Servicii de sistem
• Servicii predefinite
– Notificare
– Conectivitate
– Descărcare fișiere
– Alarme
– Localizare etc.
• Gestionate prin clase specializate
• Acces prin intermediul clasei Context
Servicii predefinite
• getSystemService(String serviciu) – clasa Context
– serviciu:
• șir de caractere cu numele acestuia, definit în clasa Context
– returnează un obiect de tipul serviciului:
• LocationManager
• AudioManager
• DownloadManager
• WiFiManager etc.
prin intermediul căruia acesta este utilizat.
Servicii predefinite

Servciu Constantă asociată (clasa Context)


Alarm ALARM_SERVICE
Bluetooth AUDIO_SERVICE
Location LOCATION_SERVICE
Notification NOTIFICATION_SERVICE
Sensor SENSOR_SERVICE
Telephony TELEPHONY_SERVICE
Wifi WIFI_SERVICE
PendingIntent
• Mesaj transmis unei aplicații pentru efectuarea unor operații
cu permisiunile aplicației sursă
• Acțiunea se execută în viitor
– Aplicația care a transmis mesajul poate să fie inactivă în momentul
execuției acestuia
PendingIntent
• Implementează interfața Parcelable
• Parametri de inițializare
– context, identificator, Intent, indicatori
• Inițializare (metode statice)
– Pentru lansarea unei activități
• getActivity()
– Pentru transmiterea unui mesaj global
• getBroadcast()
– Pentru lansarea unui serviciu
• getService()
• Indicatori
– FLAG_ONE_SHOT, FLAG_NO_CREATE,
– FLAG_CANCEL_CURRENT, FLAG_UPDATE_CURRENT
Servicii predefinite – Exemplu
private final int NOTIF_ID = 1; String url = "url valid";

//initializare manager notificari


NotificationManager notifMgr = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);

//comportamenul la click pe notficare


Intent intentNotificare = new
Intent(Intent.ACTION_VIEW, Uri.parse(url));
PendingIntent pendingIntent =
PendingIntent.getActivity(this, 0, intentNotificare, 0);
Servicii predefinite – Exemplul 1 (cont.)
Notification notif = new Notification.Builder(this)
.setContentTitle("Notificare")
.setSmallIcon(R.drawable.icon)
.setContentText("Serviciu Info")
.setContentIntent(pendingIntent).build()

//transmiterea notificarii notif


notifMgr.notify(NOTIF_ID, notif);

//Pentru oprirea notificărilor:


notifMgr.cancel(NOTIF_ID);
Servicii predefinite – Exemplul 2
DownloadManager dManager =
(DownloadManager) getSystemService(
Context.DOWNLOAD_SERVICE);

Request request = new Request(


Uri.parse(urlCurs));
request.setDescription("PDM - Curs");
long idd = dManager.enqueue(request);
Servicii predefinite – Exemplul 2 (cont.)
//asociere receptor
registerReceiver(descarcat, new IntentFilter(
DownloadManager.ACTION_DOWNLOAD_COMPLETE));

//definire receptor
BroadcastReceiver descarcat = new BroadcastReceiver() {
public void onReceive(Context ctxt, Intent intent) { //fișierul a fost
descărcat
}
//eliminare asociere receptor
unregisterReceiver(descarcat);
Servicii utilizator
• Derivare din clasa Service
• Derivare din clasa IntentService
• Declarare în fișierul manifest XML
<application ... >
<service android:name=".Serviciu" />
...
</application>
DETERMINAREA POZIȚIEI GEOGRAFICE
Poziționarea geografică
• Se utilizează serviciul de localizare identificat prin nume:
Context.LOCATION_SERVICE
– Se obține un obiect de tip LocationManager
• Localizare prin diferite surse:
– Receptorul GPS
– Rețele WiFi, celule mobile
• Permisiuni
– android.permission.ACCESS_FINE_LOCATION
– android.permission.ACCESS_COARSE_LOCATION
Poziționare geografică
• Inițializare serviciu de localizare
• Asocierea unui obiect de tip listener cu precizarea:
– Sursei utilizată la localizare
– Intervalul de timp la care se face actualizarea datelor
• Notificări în momentul apariției de modificări legate de:
– Poziția geografică
– Starea sursei de localizare
• Întreruperea asocierii cu obiectul de tip listener
• Frecvența de actualizare!
Asociere furnizori serviciu de localizare
• Metoda requestLocationUpdates() din clasa LocationManager
• Informări cu privire la modificările poziției geografice: obiecte de tip
LocationListener sau PendingIntent
• Parametri comuni:
– Intervalul minim de actualizare
– Distanța minimă de actualizare (corelată cu intervalul de actualizare)
• Alți parametri
– Sursa de localizare:
• Constanta GPS_PROVIDER sau NETWORK_PROVIDER (LocationManager)
• unui criteriu de selecție (clasa Criteria)
– Obiectul care implementează interfața LocationListener sau obiectul de tip
PendingIntent
• Metoda requestSingleUpdate()
Eliminarea asocierii
• Metoda removeUpdates() din clasa LocationManager
• Parametrul
– Obiectul de tip LocationListener
– Obiectul de tip PendingIntent
Clasa LocationManager
• Obținerea ultimei poziții cunoscute
– Location getLastKnownLocation(String sursa)
• Informații despre starea receptorului GPS
– GpsStatus getGpsStatus(GpsStatus status)
• Selectarea celui mai bun furnizor pe baza criteriilor definite
– String getBestProvider(Criteria criteriu,
boolean doarFurnizoriActivi)
Interfața LocationListener
• Recepționarea de notificări la modificarea poziției geografice
– Pe baza cerințelor de actualizare (interval și distanță)
• Metoda principală
– void onLocationChanged(Location poz)
• Coordonatele accesibile prin clasa Location
• Alte metode
– onProviderEnabled()
– onProviderDisabled()
– onStatusChanged()
Clasa Location
• Coordonate
– getLatitude(), getLongitude(), getAltitude()
• Viteza
– getSpeed()
• Timp
– getTime()
• Acuratețea localizării
– getAccuracy()
• Alte informații
Poziționare geografică - Exemplu
class LocListener implements LocationListener {
@Override
public void onLocationChanged(Location poz) {
/*poz.getLatitude(), poz.getLongitude(), poz.getAltitude(); */
}
//…
}
Poziționare geografică - Exemplu
LocListener locListener = new LocListener();

LocationManager locManager = (LocationManager)


getSystemService(Context.LOCATION_SERVICE);

//asociere furnzizor servicii localizare


locManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 0, 0, locListener);

//dezactivare asociare servicii localizare


locManager.removeUpdates(locListener);
Obținerea adreselor
• Clasa Geocoder
• Servicii de backend
• Determinare disponibilitate serviciu
– Metode statică isPresent()
• Inițializare
– Constructor cu un parametru de tip Context
• Permisiune INTERNET
Obținerea adreselor
• Metode
– getFromLocation(lat, long, nrMaxAdrese)
– getFromLocationName()
• Liste de adrese
– Clasa Address
– List<Address>
• Clasa Address
– getCountry()
– getCountryCode()
– getLocality()
– getAddressLine() etc.
Obținerea adreselor
if (Geocoder.isPresent()) {
Geocoder geocoder = new Geocoder(getApplicationContext());
try {
List<Address> adrese = geocoder.getFromLocation(lat, lon, 1);
if (adrese.size() > 0) {
//adrese.get(0).getCountryName()
//adrese.get(0).getLocality()) //etc.
}
}
catch (IOException ex) {
ex.printStackTrace();
}
}
UTILIZAREA GOOGLE MAPS
Google Maps
• Google Maps API v2
• Se bazează pe serviciul Google Maps
• Biblioteca opțională
• Inclusă în Google Play services
– Categoria Extras în SDK Manager
• Google Play services APK trebuie să fie instalat și pe dispozitivul
mobil
• Facilități
– hărți 3D, interior, satelit, teren, trafic, marcaje, plane suprapuse, trasare
linii etc.
Inițializare
• Înregistrare la Google Maps Service pentru obținerea unei chei
pentru Maps API
– https://code.google.com/apis/console
– Cheia va fi inclusă în fișierul AndroidManifest.xml
• Instalare Google Play services SDK
• Adăugarea proiectului bibliotecii Google Play services la spațiul
de lucru
• Referirea bibliotecii Google Play services în proiectul de lucru
Clase Google Maps API v2
• Pachetul com.google.android.gms.maps
• MapView
– Control care încapsulează o hartă
• MapFragment, SupportMapFragment
– Fragment care încapsulează o hartă
• UiSettings
– Control setări interfața hartă
Inițializarea hărții
• Inițializare
– Clasele MapFragment, MapView sau SupportMapFragment
– Metoda getMapAsync()
• Interfața OnMapReadyCallback
– Metoda onMapReady(GoogleMap map)
• Stabilirea tipului hărtii
– Metoda setMapType(tip_harta)
• MAP_TYPE_NORMAL, MAP_TYPE_SATELLITE, MAP_TYPE_TERRAIN
Control setări
• Clasa UiSettings
• Inițializare: getUiSettings()
• Facilități
– Controale mărire/micșorare
– Activare gesturi control
– Afișare busolă
– Buton localizare
– Bară controale
Control cameră
• Parametri vizualizare
– Locație
– Unghi înclinare
– Zoom
• Clase
– CameraUpdate
– CameraPosition
– Obținere CameraUpdate
• CameraUpdateFactory
• Metode
– moveCamera(CameraUpdate)
– animateCamera(CameraUpdate)
Clasa GoogleMap - Adăgarea de figuri geometrice
• Cerc
– Circle addCircle(CircleOptions)
• Linii
– Polyline addPolyline(PolylineOptions)
• Imagine
– GroundOverlay addGroundOverlay(GroundOverlayOptions)
• Poligon
– Polygon addPolygon(PolygonOptions)
Marcaje
• Clasa Marker
– Pictograme pe hartă
– Proprietăți
• Titlu
• Poziție (coordonate) – LatLng (latitudine și longitudine)
• Pictogramă
• etc.
– Metoda addMarker(MarkerOptions) din clasa GoogleMaps
• Clasa MarkerOptions
– Stabilire opțiuni obiect de tip Marker
Google Maps – Implementare
• Fișierul xml asociat (res/layout)
– fragment
• android:id="@+id/harta"
• android:name="com.google.android.gms.maps.MapFragment"

• Fișierul java asociat


– MapFragment mf = ((MapFragment) getFragmentManager()
.findFragmentById(R.id.harta)) ;
– mf.getMapAsync(onMapReadyCallback);
Google Maps – Implementare
@Override
public void onMapReady(GoogleMap googleMap) {
LatLng latLong = new LatLng(lat, longit);
map.setMyLocationEnabled(false);
map.moveCamera(CameraUpdateFactory.
newLatLngZoom(latLong, 18));
Marker marker = map.addMarker(new MarkerOptions().position(latLong));
marker.setTitle(locatie);
marker.showInfoWindow();
}
AndroidManifest.xml
• Permisiuni (minim):
– ACCCES_FINE_LOCATION pentru map.setMyLocationEnabled(true)
• Cheia Google Maps API
– <meta-data android:name="com.google.android.maps.v2.API_KEY"
android:value="cheia generata" />
Bibliografie
• S. Komatineni, D. MacLean – Pro Android 4, Apress, 2012
• R. Meier – Professional Android 4 Application Development,
Wiley, 2012
• P. Pocatilu, Programarea dispozitivelor mobile, Editura ASE,
2012
• P. Pocatilu, I. Ivan ș.a. – Programarea aplicațiilor Android,
Editura, ASE, 2015
• http://developer.android.com
Dispozitive și aplicații mobile

Cursul 13-14
Sumar
• Furnizori de conținut
• Receptori de mesaje
• Publicarea aplicațiilor în magazinul virtual
Play Store
• Discuții
FURNIZORI DE CONȚINUT
Partajarea datelor
• Pentru partajarea datelor între aplicaţii se
utilizează și furnizorii de conţinut
– pun la dispoziție un mecanism standardizat pentru
transferul datelor între aplicații
• Surse de date:
– fişiere
– baze de date
– alte surse
• O alternativă la furnizorii de conţinut:
comunicarea între procese
Furnizori de conținut
• Acces deseori ierarhic
• Bază de date
• Mai multe tabele
– Coloane
– Rînduri
• Referire prin URI
– tip MIME asociat conținutului
Furnizori de conținut
• Pachetul android.provider
• Predefiniți
• Definiți de utilizator
– Implementarea clasei abstracte ContentProvider
• ContentResolver
– Context#getContentResolver()
Furnizori de conținut predefiniți
• CallLog • MediaStore
– Calls – Audio
• ContactsContract – Images
– Contacts – Video
• CalendarContract • Settings
– Calendars – System
– Events – Global
– Reminders
Referirea furnizorilor de conținut
• URI
– content://furnizor/cale[/id].
• Furnizor + calea la obiect
• Constante definite în clasa furnizorului de
conținut
– Calls.CONTENT_URI = "content://call_log/calls"
Operații asupra furnizorilor
• Acces prin clasa ContentResolver
– query(Uri, String[], String, String[], String)
– insert(Uri, ContentValues)
– update(Uri, ContentValues, String, String [])
– delete(Uri, String, String [])
Interogarea unui furnizor de conținut
• Metoda query() din clasa ContentResolver
• Parametri:
– Uri asociat furnizorului de conținut
– Coloanele selectate
– Criteriul de selecție
– Valorile asociate parametrilor din criteriul de
selecție
– Ordinea de sortare
Interogarea unui furnizor de conținut
Uri uri = …

ContentResolver cr = getContentResolver();
Cursor date = cr.query(uri, null, null, null, null);

if (date != null) {
while(date.moveToNext()) {
//prelucrare linie curenta
}
}
Furnizori de conținut predefiniți –
Exemplu
ContentResolver cr = getContentResolver();

Cursor log = cr.query(CallLog.Calls.CONTENT_URI,


null,
CallLog.Calls.TYPE + "=?",
new String[]{ String.valueOf(
CallLog.Calls.OUTGOING_TYPE) },
null);
Furnizori de conținut predefiniți –
Exemplu (1) – cont.
if (log != null) {
while(log.moveToNext()) {

int iColTel = log.getColumnIndex(CallLog.Calls.NUMBER);


int iColData = log.getColumnIndex(CallLog.Calls.DATE);
int iColDurata = log.getColumnIndex(CallLog.Calls.DURATION);

String telefon = log.getString(iColTel);


Date data = new Date(Long.parseLong(log.getString(iColData)));
String durata = log.getString(iColDurata);
//utilizare telefon, data si durata
}
}
Implementarea furnizorilor de
conținut
• Implementare ContentProvider
• Metode:
– query()
• returnează un Cursor
– insert()
• Returnează un Uri asociat înregistrării inserate
– update(
– delete()
– getType()
• Tipul MIME asociat conținutului
Implementarea furnizorilor de
conținut
• Declararea în fișierul AndroidManifest.xml
//…
<provider
android:name="com.pdm.provider.FC"
android:authorities="com.pdm.provider.FC"
android:exported="true" >
</provider>
Partajarea/Transmiterea datelor între
activități
• Bundle
– Tipuri simple
– Tipuri care implementează interfața Parcelable
– Tipuri care implementează interfața Serializable
• Stocare persistentă
– Fișiere de proprietăți
– Fișiere
– Baze de date
• Membri statici
• Clasa Application
• Furnizori de conținut
RECEPTORI DE MESAJE
Transmiterea și recepționarea
mesajelor globale
• La nivel global pot fi transmite mesaje (obiecte de tip
Intent)
• Mesajele pot fi transmise din aplicații:
– de sistem
– utilizator
• Aplicațiile pot reacționa la apariția mesajelor transmise
global, la nivelul sistemului
• Exemple:
– Finalizarea descărcării unui fișier
– Identificarea unui dispozitiv (NFC, Bluetooth etc.)
– Nivelul bateriei etc.
Mesaje globale
• Intent.ACTION_BATTERY_LOW
• Intent.ACTION_BOOT_COMPLETED
• Intent.ACTION_MEDIA_MOUNTED
• Intent.ACTION_SCREEN_OFF
• Telephony.Sms.Intents.SMS_RECEIVED
Recepționarea mesajelor globale
• Se implementează clasa abstractă
BroadcastReceiver
• Receptorii nu prezintă interfață grafică
• O aplicație poate avea mai multe componente
de acest tip
• Includ filtre de mesaje
Înregistrarea receptorilor
• Receptorii sunt înregistrați:
– Static: fișierul manifest XML (elementul receiver)
– Dinamic: codul sursă
• Receptorul
– Independent (XML)
– Legat de componenta în care este definit (Java)
Înregistrarea receptorilor (XML)
• Androidmanifest.xml
<receiver android:name=".ClasaReceptor" >
<intent-filter>
<action android:name="ACTIUNE_SPECIFICA" />
</intent-filter>
</receiver>
• În fișierul Java
– Crearea clasei ClasaReceptor derivată din clasa
abstractă BroadcastReceiver
Înregistrarea receptorilor (Java)
• Creare obiect de tip IntentFilter
• Creare obiect care implementează clasa
abstractă BroadcastReceiver
• Înregistrarea unui receptor
– registerReceiver()
• Deconectarea receptorului
– unregisterReceiver()
Prelucrarea mesajelor
• Metoda onReceive(Context, Intent)
– Mesajul este primit ca parametru
– Prelucrări la recepționarea mesajului
– Reprezintă durata de viață a unui receptor
• Oprirea retransmiterii mesajului în sistem
(pentru mesajele cu priorități)
– abortBroadcast()
Transmiterea mesajelor globale
• Mesajele sînt transmise
– Fără prioritate
– Cu priorități
• sendBroadcast()
• sendOrderedBroadcast()
• Parametrul comun:
• Mesajul (Intent)
• O formă care include:
– Permisiunea necesară (String)
PUBLICAREA APLICAȚIILOR ÎN
MAGAZINUL VIRTUAL GOOGLE PLAY
Publicarea aplicațiilor în Google Play
• Necesită un cont Google
• Taxa se plătește o singură dată
• https://play.google.com/apps/publish
• Consola dezvoltare
– Listă aplicații
– Fișiere binare aplicație (APK)
– Descriere aplicație
– Statistici
– Părerea utilizatorilor și clasificări
– etc.
Publicarea aplicațiilor în Google Play
Publicarea aplicațiilor în Google Play
DIVERSE
Nu reprezintă componente ale
aplicațiilor Android

a) activitățile
b) serviciile
c) receptorii de mesaje
d) mesajele (clasa Intent)
e) furnizorii de conținut
În cadrul oricărei metode dintr-o clasă
derivată din clasa Activity, this poate fi
utilizat pentru tipul:
a) Context
b) Application
c) Intent
d) View
e) ViewGroup
În mod uzual, pictogramele asociate
unei aplicații se stochează în
directorul:
a) res/bitmaps
b) res/drawable
c) res/icons
d) res/raw
e) res/anim
Un container de tip LinearLayout
permite adăugarea componentelor:

a) doar pe verticală
b) pe verticală sau pe orizontală
c) doar pe orizontală
d) pe verticală și pe orizontală simultan
e) doar într-o singură poziție
Pentru selecția unor înregistrări dintr-o
tabelă SQLite se poate utiliza una din
metodele din clasa SQLiteDatabase:
a) rawQuery() sau query()
b) execSql() sau query()
c) rawQuery() sau select()
d) execSql() sau select()
e) rawSelect() sau select()
Bibliografie
• S. Komatineni, D. MacLean – Pro Android 4, Apress,
2012
• R. Meier – Professional Android 4 Application
Development, Wiley, 2012
• P. Pocatilu, Programarea dispozitivelor mobile,
Editura ASE, 2012
• P. Pocatilu, I. Ivan ș.a. – Programarea aplicațiilor
Android, Editura, ASE, 2015
• http://developer.android.com
07-Jan-20

Baze de date SQLITE


Biblioteca ROOM

Baze de date
• SQLite
• Baze de date relaționale
• Room

1
07-Jan-20

SQLite
• Tipuri de date suportate
• INTEGER
• REAL
• TEXT
• BLOB
• Conversii între tipuri (relații de afinitate)
• Restricții
• nu suportă anumite tipuri de asociere (join)
• restricția de referențialitate
• nu este activată implicit
• nu suportă tranzacții imbricate

Room
• Nivel de abstractizare peste SQLite
• ORM (Object Relational Mapping)
• Dependențe
• implementation "androidx.room:room-runtime:2.2.2"
• annotationProcessor "androidx.room:room-compiler:2.2.2"

2
07-Jan-20

Obiecte utilizate
• Entități
• Operații asupra datelor
• Baza de date
• Adnotări Java

Entități
• Clase Java asociate tabelelor
• Datele membre sînt asociate cîmpurilor tabelei
• Datele membre
• Publice
• Funcții accesor (set/get)
• Pot fi ignorate anumite cîmpuri
• Nu sînt incluse obiecte
• Posibilități de conversie

3
07-Jan-20

Entități
• @Entity
• clasa Java asociată unei tabele
• tableName
• Denumirea personalizată a tabelei
• @PrimaryKey – cîmp de tip cheie primară
• autogenerate
• @ColumnInfo
• name
• Denumirea personalizată a cîmpului în tabelă
• @Ignore – cîmpul nu este inclus în tabelă

Relații între entități


• Proprietatea foreignKey din @Entity
• Valoarea de tip @ForeignKey
• Atribute
• entity
• Clasa asociată entității părinte
• parentColumns
• Denumirile coloanelor din tabela părinte
• childColumns
• Denumirile coloanelor din tabela copil
• onDelete , onUpdate
• CASCADE

4
07-Jan-20

Relații între entități


• Clase non-entitate
• @Relation
• Listă de obiecte asociate unei entități
• parentColumn
• entityColumn
• entity
• @Embedded
• Includerea unei entități în cadrul clasei

Operații asupra datelor


• @Dao
• Definește interfața pentru operațiile asupra datelor
• Include metode de selecție, inserare, modificare
• Metodele trebuie adnotate
• Operațiile trebuie executate asincron

5
07-Jan-20

Operații asupra datelor


• @Query
• Metodă de tip interogare
• @Insert
• Metodă pentru inserare
• @Update
• Metodă pentru actualizare
• @Delete
• Metodă pentru ștergere

Baza de date
• Extinde clasa abstractă RoomDatabase
• Clasă abstractă
• Adnotare @Database
• Clasa asociată bazei de date
• entities
• Clasele asociate entităților
• version
• Versiunea curentă a bazei de date
• Metode care returnează obiectele de tip Dao asociate entităților
• Managementul versiunilor (migrare)

6
07-Jan-20

Inițializarea bazei de date


• O singură instanță
• databaseBuilder(context, clasa_bd, nume_bd)
• Metoda statică în clasa Room
• Clasa RoomDatabase.Builder
• Opțiuni creare
• fallbackToDestructiveMigration()
• allowMainThreadQueries()
• Metoda build()
• Returnează obiectul de tip baza de date

Cursor
• android.database
• Interfață
• permite gestiunea înregistrărilor rezultate în urma interogării unei
baze de date
• SQLiteCursor
• Implementare pentru baze de date SQLite

7
07-Jan-20

Cursor
• Parcurgere
• moveToNext()
• moveToPrevious()
• moveToFirst()
• moveToLast()
• Extragerea de valori
• getTIP(): getInt(), getString(), getFloat() etc.
• parametru: indexul coloanei

Cursor: Determinarea poziției


• isFirst()
• isLast()
• isBeforeFirst()
• isAfterLast()

8
07-Jan-20

Cursor: Obținerea de informații


• Numărul de înregistrări
• getCount()
• Numele coloanei
• getColumnName()
• Poziția coloanei
• getColumnIndex()

Adaptoare de tip Cursor


• CursorAdapter
• Coloana _id
• SimpleCursorAdapter

9
07-Jan-20

Exemplu: SimpleCursorAdapter
SimpleCursorAdapter adapter = new SimpleCursorAdapter(
this, // contextul
android.R.layout.two_line_list_item, //sablonul liniei
cursor, // cursorul
new String[] { … }// lista numelor coloanelor,
new int[] { … } //lista identificatorilor de resurse asociate
);

10

S-ar putea să vă placă și