L'emulatore Android Studio non viene fornito con Play Store per API 23


92

Ho selezionato questo emulatore dalla versione più recente di Android Studio AVD.

API di Google

Ho selezionato l'ultima versione dell'API 23 di Android. Poiché dice "con API di Google", ho pensato che avrebbe effettivamente incluso tutte le app di Google, incluso Play Store, in modo da poter installare app come Facebook.

Ho visto altri thread su SO che ora sembrano essere obsoleti ( come installare l'app Google Play nell'emulatore Android Studio? ), Questo fornisce istruzioni per l'installazione di app Google basate su pacchetti universali ma va solo fino ad Android 4.3 API 18: http://wiki.rootzwiki.com/Google_Apps#Universal_Packages_2

Vorrei quello per API 23. C'è un modo per installare il pacchetto Google Apps sull'emulatore?

Sembra strano che l'emulatore Android ufficiale non venga fornito di serie con tutte le app di Google in primo luogo ... Questo non sembra molto favorevole a Google e potrebbe significare che gli sviluppatori dovranno acquistare dispositivi reali per sviluppare per API 23 ?


Grazie Sig.ra Yvette. Penso che sia importante ottenere una risposta a questa domanda per la comunità Android. Ci sono molti sviluppatori Android là fuori senza accesso ai dispositivi Android effettivi e mi chiedo come faranno a sviluppare per Android quando non hanno accesso a tutti gli strumenti.
Simon

1
Non ho abbastanza credito per commentare sopra. Ri: la partizione di sola lettura / di sistema, assicurati di passare l'argomento "-writable-system" quando chiami emulator.exe. Ad esempio: START / B emulator.exe @ Nexus_7-2012_API_22 -no-boot-anim -writable-system
pjl

@pjl - grazie per questo commento! L'ho aggiunto alla mia risposta.
Dev-iL

Google dice che stanno lavorando per aggiungere il supporto del Play Store all'emulatore. Nel frattempo, ci sono alcune soluzioni alternative tra cui puoi scegliere. L'utilizzo di Amazon Appstore è un'opzione, ma non è l'unica. Vedi qui .
indimenticabileidSupportsMonica

Risposte:


56

Ho dovuto farlo di recente sull'emulatore API 23 e ho seguito questa guida . Funziona con l'emulatore API 23, quindi non dovresti avere problemi.

Nota: tutto il merito va all'autore del post del blog collegato (pyoor). Lo sto solo postando qui nel caso in cui il collegamento si interrompa per qualsiasi motivo.

....

Scarica il pacchetto GAPPS

Successivamente dobbiamo estrarre il pacchetto Google Apps appropriato che corrisponde alla nostra versione AVD di Android. In questo caso utilizzeremo il pacchetto "gapps-lp-20141109-signed.zip". Puoi scaricare quel file da BasketBuild qui .

[pyoor@localhost]$ md5sum gapps-lp-20141109-signed.zip
367ce76d6b7772c92810720b8b0c931e gapps-lp-20141109-signed.zip

Per installare Google Play, dovremo inviare i seguenti 4 APK al nostro AVD (che si trova in ./system/priv-app/):

GmsCore.apk, GoogleServicesFramework.apk, GoogleLoginService.apk, Phonesky.apk

[pyoor@localhost]$ unzip -j gapps-lp-20141109-signed.zip \
system/priv-app/GoogleServicesFramework/GoogleServicesFramework.apk \
system/priv-app/GoogleLoginService/GoogleLoginService.apk \
system/priv-app/Phonesky/Phonesky.apk \
system/priv-app/GmsCore/GmsCore.apk -d ./

Esegui il push degli APK nell'emulatore

Con i nostri APK estratti, lanciamo il nostro AVD utilizzando il seguente comando.

[pyoor@localhost tools]$ ./emulator @<YOUR_DEVICE_NAME> -no-boot-anim

La prima volta che viene creato l'AVD potrebbero essere necessari diversi minuti. Una volta avviato, dobbiamo rimontare la partizione di sistema AVD in lettura / scrittura in modo da poter inviare i nostri pacchetti sul dispositivo.

[pyoor@localhost]$ cd ~/android-sdk/platform-tools/
[pyoor@localhost platform-tools]$ ./adb remount

Quindi, invia gli APK al nostro AVD:

[pyoor@localhost platform-tools]$ ./adb push GmsCore.apk /system/priv-app/
[pyoor@localhost platform-tools]$ ./adb push GoogleServicesFramework.apk /system/priv-app/
[pyoor@localhost platform-tools]$ ./adb push GoogleLoginService.apk /system/priv-app/
[pyoor@localhost platform-tools]$ ./adb push Phonesky.apk /system/priv-app

Profitto!

Infine, riavvia l'emualatore utilizzando i seguenti comandi:

[pyoor@localhost platform-tools]$ ./adb shell stop && ./adb shell start

Una volta riavviato l'emulatore, dovremmo vedere il pacchetto Google Play apparire nel menu di avvio. Dopo aver associato un account Google a questo AVD, ora abbiamo una versione completamente funzionante di Google Play in esecuzione con il nostro emulatore.


29
Ricevo l'errore "ReadOnly file system" e nessuno di questi file apk è installato.
wmac

6
Purtroppo BasketBuild sembra non essere più disponibile. s.basketbuild.com indica che è in calo da almeno 9/3, senza ETA da aumentare. C'è un'altra fonte che consigli per le app Google?
Chad Schultz

1
Se hai ricevuto l'errore "File system di sola lettura", esegui il comando: "adb remount". Quindi prova di nuovo i comandi "adb push ...".
Shangwu

4
Tutti i collegamenti sono morti
Mooing Duck

1
chiunque non riesca a ottenere gapps: f.lomakuit.com/download/gapps-lp-20141109-signed.zip
Manny265

51

Di seguito è riportato il metodo che ha funzionato per me sugli emulatori API 23-25 . La spiegazione è fornita per API 24 ma funziona in modo quasi identico per altre versioni.

Crediti : Jon Doe , zaidorx , pjl .

Consiglio caloroso per i lettori: per favore, ripeti i passaggi prima di seguirli, poiché alcuni sono automatizzati tramite script forniti.


  1. Nel gestore AVD di Android Studio (testato su v2.2.3), crea un nuovo emulatore con il target "Android 7.0 (Google API)": Schermata AVD dopo aver creato l'emulatore.

  2. Scarica l'ultimo pacchetto Open GApps per l'architettura dell'emulatore (CPU / ABI). Nel mio caso lo era x86_64, ma può essere qualcos'altro a seconda della scelta dell'immagine durante la procedura guidata di creazione del dispositivo. È interessante notare che l'architettura sembra più importante della corretta versione di Android (cioè gapps per 6.0 funziona anche su un emulatore 7.0).

  3. Estrai i .apkfile utilizzando dai seguenti percorsi (relativi a open_gapps-x86_64-7.0-pico-201#####.zip):

    .zip\Core\gmscore-x86_64.tar.lz\gmscore-x86_64\nodpi\priv-app\PrebuiltGmsCore\
    .zip\Core\gsfcore-all.tar.lz\gsfcore-all\nodpi\priv-app\GoogleServicesFramework\
    .zip\Core\gsflogin-all.tar.lz\gsflogin-all\nodpi\priv-app\GoogleLoginService\
    .zip\Core\vending-all.tar.lz\vending-all\nodpi\priv-app\Phonesky\

    Nota che l'Open Gapps usa la compressione Lzip, che può essere aperto utilizzando lo strumento disponibile sul sito web Lzip 1 , 2 , o su Mac utilizzando homebrew: brew install lzip. Quindi ad es lzip -d gmscore-x86_64.tar.lz.

    Fornisco un file batch che utilizza 7z.exee lzip.exeper estrarre .apkautomaticamente tutti i messaggi richiesti (su Windows):

    @echo off
    echo.
    echo #################################
    echo Extracting Gapps...
    echo #################################
    7z x -y open_gapps-*.zip -oGAPPS
    
    echo Extracting Lzips...
    lzip -d GAPPS\Core\gmscore-x86_64.tar.lz
    lzip -d GAPPS\Core\gsfcore-all.tar.lz
    lzip -d GAPPS\Core\gsflogin-all.tar.lz
    lzip -d GAPPS\Core\vending-all.tar.lz
    
    move GAPPS\Core\*.tar
    
    echo. 
    echo #################################
    echo Extracting tars...
    echo #################################
    
    7z e -y -r *.tar *.apk
    
    echo.
    echo #################################
    echo Cleaning up...
    echo #################################
    rmdir /S /Q GAPPS
    del *.tar
    
    echo.
    echo #################################
    echo All done! Press any key to close.
    echo #################################
    pause>nul

    Per usarlo, salva lo script in un file (ad esempio unzip_gapps.bat) e metti tutto ciò che è rilevante in una cartella, come mostrato di seguito: Come dovrebbe essere ...

  4. Aggiorna il subinario per poter modificare i permessi dei file che caricheremo successivamente. Un nuovo subinario può essere trovato nel pacchetto SuperSU by Chainfire "Recovery flashable"zip . Ottieni lo zip, estrailo da qualche parte, crea un file batch con i seguenti contenuti nella stessa cartella e infine eseguilo:

    adb root
    adb remount
    
    adb push eu.chainfire.supersu_2.78.apk /system/app/
    adb push x64/su /system/xbin/su
    adb shell chmod 755 /system/xbin/su
    
    adb shell ln -s /system/xbin/su /system/bin/su
    adb shell "su --daemon &"
    adb shell rm /system/app/SdkSetup.apk
  5. Metti tutti i .apkfile in una cartella e crea un file batch con questi contenuti 3 :

    START /B E:\...\android-sdk\tools\emulator.exe @Nexus_6_API_24 -no-boot-anim -writable-system
    adb wait-for-device
    adb root
    adb shell stop
    adb remount
    adb push PrebuiltGmsCore.apk /system/priv-app/PrebuiltGmsCore
    adb push GoogleServicesFramework.apk /system/priv-app/GoogleServicesFramework
    adb push GoogleLoginService.apk /system/priv-app/GoogleLoginService
    adb push Phonesky.apk /system/priv-app/Phonesky/Phonesky.apk
    adb shell su root "chmod 777 /system/priv-app/**"
    adb shell su root "chmod 777 /system/priv-app/PrebuiltGmsCore/*"
    adb shell su root "chmod 777 /system/priv-app/GoogleServicesFramework/*"
    adb shell su root "chmod 777 /system/priv-app/GoogleLoginService/*"
    adb shell su root "chmod 777 /system/priv-app/Phonesky/*"
    adb shell start

    Si noti che il percorso E:\...\android-sdk\tools\emulator.exedeve essere modificato in base alla posizione di Android SDK sul sistema.

  6. Esegui il file batch sopra (la console dovrebbe apparire così in seguito):

    O:\123>START /B E:\...\android-sdk\tools\emulator.exe @Nexus_6_API_24 -no-boot-anim -writable-system
    
    O:\123>adb wait-for-device
    Hax is enabled
    Hax ram_size 0x60000000
    HAX is working and emulator runs in fast virt mode.
    emulator: Listening for console connections on port: 5554
    emulator: Serial number of this emulator (for ADB): emulator-5554
    
    O:\123>adb root
    
    O:\123>adb shell stop
    
    O:\123>adb remount
    remount succeeded
    
    O:\123>adb push PrebuiltGmsCore.apk /system/priv-app/PrebuiltGmsCore/
    [100%] /system/priv-app/PrebuiltGmsCore/PrebuiltGmsCore.apk
    
    O:\123>adb push GoogleServicesFramework.apk /system/priv-app/GoogleServicesFramework/
    [100%] /system/priv-app/GoogleServicesFramework/GoogleServicesFramework.apk
    
    O:\123>adb push GoogleLoginService.apk /system/priv-app/GoogleLoginService/
    [100%] /system/priv-app/GoogleLoginService/GoogleLoginService.apk
    
    O:\123>adb push Phonesky.apk /system/priv-app/Phonesky/Phonesky.apk
    [100%] /system/priv-app/Phonesky/Phonesky.apk
    
    O:\123>adb shell su root "chmod 777 /system/priv-app/**"
    
    O:\123>adb shell su root "chmod 777 /system/priv-app/PrebuiltGmsCore/*"
    
    O:\123>adb shell su root "chmod 777 /system/priv-app/GoogleServicesFramework/*"
    
    O:\123>adb shell su root "chmod 777 /system/priv-app/GoogleLoginService/*"
    
    O:\123>adb shell su root "chmod 777 /system/priv-app/Phonesky/*"
    
    O:\123>adb shell start
  7. Quando l'emulatore viene caricato , chiudilo, elimina il dispositivo virtuale e creane un altro utilizzando la stessa immagine di sistema . Questo risolve l'app Play Store che non risponde, "Google Play Services si è interrotto" e problemi simili. Funziona perché nei passaggi precedenti abbiamo effettivamente modificato l'immagine del sistema stesso (dai un'occhiata alla Data modificata su android-sdk\system-images\android-24\google_apis\x86_64\system.img). Ciò significa che ogni dispositivo creato d'ora in poi con l'immagine di sistema avrà delle gapp installate!

  8. Avvia il nuovo AVD. Se il caricamento impiega un tempo insolitamente lungo, chiudilo e avvialo invece utilizzando:

    START /B E:\...\android-sdk\tools\emulator.exe @Nexus_6_API_24
    adb wait-for-device
    adb shell "su --daemon &"

    Dopo l'avvio di AVD vedrai l'immagine qui sotto: nota l'icona del Play Store nell'angolo!

Primo avvio con Play Store installato.


3 - Non sono sicuro che tutti questi comandi siano necessari, e forse alcuni di essi sono eccessivi ... sembra funzionare - che è ciò che conta. :)


2
Invece dei file .xz, Open Gapps sembra contenere file .lz (come gsfcore-all.tar.lz). Ho provato più strumenti, nessuno dei quali è in grado di decomprimere i file .lz in modo da poter accedere agli APK. Eventuali suggerimenti?
Chad Schultz

2
@Chad Schultz ecco il link per lo strumento download.savannah.gnu.org/releases/lzip se sei su Windows scarica "lzip-1.11-w32.zip" e usa il seguente comando per convertirlo in un file .tar e usarne un altro strumento per estrarlo finalmente.
f4b

1
@ Dev-iL PlayStore viene installato sul mio emulatore, ma non si apre. Sto usando un'immagine di sistema x86_64 API 23 di Nexus 5. Qualche idea?
ARK

3
Questo ha funzionato per me sull'ultimo emulatore 25 / 7.1. L'unica cosa strana era che /system/app/SdkSetup.apknon esisteva nella mia immagine. Grazie mille, stavo impazzendo cercando di risolverlo!
wilsonpage

1
Come fai esattamente a "crearne un altro utilizzando la stessa immagine di sistema"?
gavsiu

42

Ora non è necessario caricare lateralmente alcun pacchetto di eseguire script per ottenere il Play Store sull'emulatore. A partire da Android Studio 2.4 ora puoi creare un AVD su cui è preinstallato Play Store. Attualmente è supportato solo sugli AVD che eseguono immagini di sistema Android 7.0 (API 24).

Fonte ufficiale

AVD con Play Store

Nota: i dispositivi compatibili sono indicati dalla nuova colonna Play Store.


6
Nota: è necessario installare un'immagine di sistema che dice Target:, Android 7.0 (Google Play)non solo le API di Google. Attualmente è disponibile solo per API 24, non per API 25. Una volta installata l'immagine di sistema, apparirà nella scheda Consigliati, non nella scheda Immagini x86.
antoine

2
Android Studio 2.3.3 su Linux ora supporta gli AVD del Play Store, ma vale anche la pena notare che il Play Store sembra essere disponibile solo su target x86 al momento, quindi dovrai comunque utilizzare un altro metodo se vuoi ottenere il Play Memorizza su un ARM AVD.
NullColaShip

Ora ci sono anche immagini per le API 25, 26 e 27 oltre a 24.
arekolek

25

Volevo commentare l'ultima risposta, ma senza login è possibile solo dare una risposta:

Per eliminare l '"errore di sola lettura" è sufficiente arrestare il dispositivo immediatamente dopo che è pronto. Il mio script appare come segue:

#!/bin/bash 
~/bin/AndroidSdk/tools/emulator @Nexus_6P_API_23 -no-boot-anim &
adb wait-for-device
adb shell stop
adb remount
adb push GmsCore.apk /system/priv-app
adb push GoogleServicesFramework.apk /system/priv-app
adb push GoogleLoginService.apk /system/priv-app
adb push Phonesky.apk /system/priv-app
adb shell start

1
Questo mi aiuta a risolvere l'errore del file system di sola lettura. dato che lavoro in Windows, ho semplicemente ignorato la prima riga dello script e ho sostituito la seconda con questo "START / B / tools / emulator @ Nexus_6P_API_23 -no-boot-anim", l'ho salvato con estensione .bat ed eseguito dalla riga di comando.
zaidorx

1
È fantastico, ho appena rimosso le prime due righe e avviato l'emulatore da solo e poi ho eseguito il file BAT ... ha funzionato a meraviglia
Im Rick James

metti adb root all'inizio se hai adb shell stop stop: deve essere root error.
nutella_eater

adb rootla riga deve essere aggiunta immediatamente dopo la adb wait-for-deviceriga per evitare Read-only file systemerrori.
efkan

1
Ha funzionato una volta che ho aggiunto -writable-system al comando del mio emulatore in questo modo, ~ / android-sdk / tools / emulator @ Nexus_5X_API_23 -no-boot-anim -writable-system
riassemblatore

2

Ecco lo script che ho usato su Linux per un'istanza Nexus 5 API 24 x86 SENZA GoogleApis.

#!/bin/sh

~/Android/Sdk/tools/emulator @A24x86 -no-boot-anim -writable-system & #where A24x86 is the name i gave to my instance
~/Android/Sdk/platform-tools/adb wait-for-device
~/Android/Sdk/platform-tools/adb root
~/Android/Sdk/platform-tools/adb shell stop
~/Android/Sdk/platform-tools/adb remount
~/Android/Sdk/platform-tools/adb push ~/gapps/PrebuiltGmsCore.apk /system/priv-app/PrebuiltGmsCore/PrebuiltGmsCore.apk
~/Android/Sdk/platform-tools/adb push ~/gapps/GoogleServicesFramework.apk /system/priv-app/GoogleServicesFramework/GoogleServicesFramework.apk
~/Android/Sdk/platform-tools/adb push ~/gapps/GoogleLoginService.apk /system/priv-app/GoogleLoginService/GoogleLoginService.apk
~/Android/Sdk/platform-tools/adb push ~/gapps/Phonesky.apk /system/priv-app/Phonesky/Phonesky.apk
~/Android/Sdk/platform-tools/adb shell "chmod 777 /system/priv-app/PrebuiltGmsCore /system/priv-app/GoogleServicesFramework"
~/Android/Sdk/platform-tools/adb shell "chmod 777 /system/priv-app/GoogleLoginService /system/priv-app/Phonesky"
~/Android/Sdk/platform-tools/adb shell "chmod 777 /system/priv-app/PrebuiltGmsCore/PrebuiltGmsCore.apk"
~/Android/Sdk/platform-tools/adb shell "chmod 777 /system/priv-app/GoogleServicesFramework/GoogleServicesFramework.apk"
~/Android/Sdk/platform-tools/adb shell "chmod 777 /system/priv-app/GoogleLoginService/GoogleLoginService.apk"
~/Android/Sdk/platform-tools/adb shell "chmod 777 /system/priv-app/Phonesky/Phonesky.apk"
~/Android/Sdk/platform-tools/adb shell start

Questo l'ha fatto per me.

IMPORTANTE: per evitare che l'app si arresti in modo anomalo ricordati di concedere i permessi di localizzazione di Google Play Services.

Configurazione-> App-> Configurazione (icona a forma di ingranaggio) -> Autorizzazioni app-> Posizione -> (menu in alto a destra) -> Mostra sistema-> Abilita servizi Google Play


2

Vai su http://opengapps.org/ e scarica la versione pico della tua piattaforma e la versione Android. Decomprimere la cartella scaricata per ottenere
1. GmsCore.apk
2.
GoogleServicesFramework.apk 3. GoogleLoginService.apk
4. Phonesky.apk

Quindi, individua il tuo emulator.exe. Probabilmente lo troverai in
C: \ Users \ <YOUR_USER_NAME> \ AppData \ Local \ Android \ sdk \ tools

Esegui il comando:
emulator -avd <YOUR_EMULATOR'S_NAME> -netdelay none -netspeed full -no-boot-anim -writable-system

Nota: usa -writable-system per avviare l'emulatore con un'immagine di sistema scrivibile.

Quindi,
adb root
adb remount
adb push <PATH_TO GmsCore.apk> / system / priv-app
adb push <PATH_TO GoogleServicesFramework.apk> / system / priv-app
adb push <PATH_TO GoogleLoginService.apk> / system / priv-app
adb push <PATH_TO Phonesky.apk> / system / priv-app

Quindi, riavvia l'emulatore
adb shell stop
adb shell start

Per verificare l'esecuzione,
adb shell pm elenca i pacchetti e troverai il pacchetto com.google.android.gms per google


2

Quello che devi fare è aggiornare il config.inifile per il dispositivo e scaricare nuovamente l'immagine del sistema.

Aggiorna i seguenti valori in C:\Users\USER\.android\avd\DEVICE_ID\config.ini(su Windows) o ~/.android/avd/DEVICE_ID/config.ini(su Linux)

PlayStore.enabled = true
image.sysdir.1=system-images\android-27\google_apis_playstore\x86\
tag.display=Google Play
tag.id=google_apis_playstore

Quindi scarica nuovamente l'immagine di sistema per il dispositivo da Android Studio> Strumenti> AVD Manager

Questo è tutto. Riavvia il tuo dispositivo e avrai il Play Store installato.

Anche qui è stata data una risposta: come installare l'app Google Play nell'emulatore Android Studio?


2

Risolto in modo semplice: dovresti creare un nuovo emulatore, prima di aprirlo per la prima volta segui questi 3 semplici passaggi:

1- vai a "C: \ Users [utente] .android \ avd [cartella del tuo dispositivo virtuale]" apri "config.ini" con un editor di testo come il blocco note

2- cambiare

"PlayStore.enabled = false" a "PlayStore.enabled = true"

3- cambiamento

"mage.sysdir.1 = system-images \ android-30 \ google_apis \ x86"

per

"image.sysdir.1 = system-images \ android-30 \ google_apis_playstore \ x86"


1

A partire da ora, l'installazione degli apk nella /systemdirectory sembra funzionare utilizzando il adb pushcomando.

Alcuni servizi nascosti stavano rimontando automaticamente la /systemdirectory in read-onlymodalità.

Ad ogni modo, sono stato in grado di installare il Play Store in una normale macchina virtuale (cioè, macchina virtuale non Google-Api) semplicemente montando il system.imgfile dal mio sistema operativo e copiando i file.

# To be executed as root user in your Unix based OS
mkdir sys_temp
mount $SDK_HOME/system-images/android-23/default/x86/system.img sys_temp -o loop
cp Phonesky.apk GmsCore.apk GoogleLoginService.apk GoogleServicesFramework.apk ./sys_temp/priv-app/
umount sys_temp
rmdir sys_temp

I file APK possono essere estratti da qualsiasi dispositivo Android reale che esegue Google Apps utilizzando il adb pullcomando

[Per ottenere il percorso esatto degli apk, possiamo usare il comando pm list packages -fall'interno della shell adb]


Non sono convinto che ci sia un servizio "misterioso" in esecuzione .. piuttosto, c'era un bug nell'emulatore (o nelle immagini di sistema) che sembra essere stato corretto, che permetteva l' apkesistenza di diverse copie di s nella /systemdirectory. Ho notato che spingere ciascuno dei messaggi apkin una cartella corretta non provoca errori di scrittura. Ho aggiornato la mia risposta: potresti provare se funziona per te ora?
Dev-iL

Sto affrontando lo stesso problema, non sono riuscito a passare il file system di sola lettura quando si spinge apk, penso che l'unico modo sia modificare l'immagine del sistema Android dell'emulatore e quindi come modificare l'immagine Android da Windows 8, grazie. Ho bisogno di installare l'ultimo servizio Google Play e Google Play Game sull'emulatore Android 6.0.
noname.cs

2
Ho installato linux e copiato gli apk su un system.img 6.0 con Google API, ma quando ho creato un nuovo emulatore, non aveva il servizio Google Play o Google Play Store. Proverò di nuovo con rom apis non google.
noname.cs

0

Voglio solo aggiungere un'altra soluzione per gli utenti React Native che hanno solo bisogno dell'app Expo.

  1. Installa l' app Expo
  2. Apri il tuo progetto
  3. Fai clic su Dispositivo -> Apri su Android - In questa fase Expo installerà l'app Android di Expo e sarai in grado di aprirla.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.