APDE GSoC ’18: Android Mode 4.0-integrationer

Når du kører en skitse med urskive-målet, bliver skitsen bygget og sendt til uret. Derefter indlæser APDE wear companion-appen automatisk skitsen og lancerer urskivevælgeren:

VR-skitser installeres ligesom almindelige apps. De understøtter Googles VR-platform, som omfatter Cardboard- og Daydream-headsets:

Hvis du ønsker at få fingrene i disse nye funktioner, skal du tilmelde dig APDE Preview Channel og følge instruktionerne øverst for at tilmelde dig testerlisten.

I skrivende stund er v0.5.0-pre2 er tilgængelig og indeholder wallpapers og VR, men ikke urskiver.

Hvordan fungerer det hele?

Nøglen til at understøtte disse nye mål var at opgradere til at bruge desktop Processing’s Android Mode 4.0, som tilføjede understøttelse af wallpapers, urskiver og VR. Mit arbejde bestod blot i at portere disse fede nye funktioner over til APDE, hvilket ikke i sig selv var en let opgave.

Jeg besluttede tidligt, at jeg vil have, at hver skitse skal kunne køres til hvert mål. Jeg vil have, at brugerne skal kunne tage enhver skitse eller eksempel og problemfrit transplantere den fra et miljø til et andet, uanset om det er en app, et tapet, en urskive eller VR. På den måde er der maksimal fleksibilitet og kapacitet til at udforske det fulde potentiale af Processing-skitser. Den eneste undtagelse fra denne regel er, at VR-skitser skal være 3D-skitser (2D-skitser fungerer bare ikke på grund af VR’s karakter).

Denne fremgangsmåde adskiller sig fra fremgangsmåden i Android-tilstand. På skrivebordet er VR f.eks. pakket som et bibliotek, så kun skitser, der udtrykkeligt importerer VR-biblioteket, kan køres for VR-målet. I APDE kan alle 3D-skitser køres til VR, og den korrekte import tilføjes automatisk.

Buildsystemet bruger nu et sæt skabeloner til at holde styr på alle buildfiler som f.eks. aktiviteter, manifester og layouts. Denne metode er langt at foretrække frem for den hard-coding, der tidligere blev foretaget. Skabelonerne er taget stort set ordret fra Android-tilstand, men der er et par ændringer, f.eks. understøttelse af Daydream VR-headsets.

Live wallpapers og VR-skitser installeres ligesom almindelige apps-skitser, men VR kræver Google VR-bibliotekerne. På samme måde kræver urskiverne biblioteket til understøttelse af wearable, men de installeres ikke på samme måde, fordi de skal installeres på et ur.

Watch Face Woes

Jeg havde brug for at installere skitsen på uret.

Det første, jeg prøvede, var at skubbe skitsen til uret og installere den der. Det viser sig, at side-loading af en APK på et Wear OS-ur (tidligere Android Wear) ikke er så let, som det kan se ud. På en Android-telefon skal du blot aktivere installation fra ukendte kilder i indstillingerne, og så er du klar. På wear er denne installation imidlertid blokeret af systemet, og der er ingen vej udenom uden at roote enten telefonen eller uret eller tilslutte uret til en computer. Ingen af disse er muligheder for et mobiludviklingsmiljø på begynderniveau.

Næst prøvede jeg at pakke appen som en Wear 1.x-app og installere den på telefonen. Før Android Wear 2.0 blev alle Wear-apps distribueret ved at blive pakket i telefonapps, også selv om telefonappen blot var en tom skal. Dette ændrede sig alt sammen i 2.0, da Wear-apps blev selvstændige apps. Håbet var, at jeg kunne udnytte det gamle system til at installere ur-appen via telefonen, men det var forgæves. Jeg ved stadig ikke, om den gamle installationsmetode understøttes på nyere ure, men det lykkedes mig ikke at få et proof of concept til at virke.

Sluttelig tyede jeg til en sidste udvej: class loading, som er en slags sort magi. Ideen er, at i stedet for at installere skitsen som en selvstændig app kan jeg indlæse skitsens klasse i en app, der allerede kører på uret, hvilket fjerner behovet for at installere skitsen, hver gang den køres. Dette er en fundamentalt anderledes model end den måde, APDE fungerer på i øjeblikket. APDE bygger en skitse, og det er en selvstændig app, der installeres. App-skærmen samler en række skitser, efterhånden som brugeren kører dem, og de bliver hængende, når APDE afinstalleres. Uret er anderledes. Nu bliver skitser ikke installeret, de bliver bare indlæst. Der er altid kun én skitse tilgængelig som urskive, og den forsvinder, når APDE afinstalleres.

Det viser sig, at denne fremgangsmåde virker. Brugeren installerer en bridge-app på sit ur fra Play Store (ikke tilgængelig endnu) kaldet “APDE Wear Companion”. Når APDE opbygger en skitse, sender den den til wear companion. Wear Companion pakker skitsen ud og beder brugeren om at vælge en urskive, der er indbygget i Wear Companion. Derefter indlæser denne urskive skitsen og viser den. Dette er overraskende problemfrit.

Der var et par udfordringer.

Når skitsen crasher, kører den i wear companion, så hele wear companion-appen crasher også. Jeg forsøger i øjeblikket at begrænse skaden, men nogle gange går wear companion i stykker og skal genstartes, fordi skitsen er styrtet ned for mange gange. APDE kan heller ikke se stack-traces fra nedbrudte urskiver i øjeblikket, fordi processen dør, før stack-trace kan blive sendt ud. (Print statements virker dog.)

Der er ikke kun én watch face; der er faktisk to. Processing har to basisklasser for watch faces: en for standardrendereren (JAVA2D) og en for OpenGL-baserede renderere (P2D og P3D). Der er således to watch faces, en for hver renderer. Når wear companion udpakker en skitse, kontrollerer den, hvilken renderer den bruger. Derefter bliver den tilsvarende urskive synliggjort, og den anden bliver skjult. Dette er endnu en form for sort magi, fordi brugeren ikke engang burde lægge mærke til det, men det ser ud til at virke ret godt.

Jeg løj lige. Der er faktisk fire urskiver. Det viser sig, at når du indlæser en ny urskive, hvis den nye urskive er den samme som den gamle (og alle skitser bruger de samme to urskiver), så “kortslutter” systemet (det er det tekniske udtryk for det) og indlæser ikke urskiven igen. Dette er fint nok til almindelige urskiver, men APDE-urskiverne skal genindlæses for at få den nye skitse. Løsningen er beskidt, men effektiv: man skal bare have to urskiver for hver renderer (fire i alt) og veksle mellem dem, når man indlæser nye skitser, så urskiverne tvinges til at genindlæse.

Trods alle disse vanskeligheder er jeg glad for at kunne sige, at urskiverne ser ud til at fungere ret godt, i hvert fald på de to sæt enheder, jeg har testet dem på. De andre, mere sandsynlige mål – baggrunde og VR – var betydeligt nemmere at implementere.

Synet fremad

Den næste store funktion, der er planlagt til sommer, er en “preview”-tilstand. I øjeblikket skal APDE-skitser installeres hver gang, de køres. Denne ordning er ikke ideel, fordi installationsprogrammet fordobler tiden mellem det tidspunkt, hvor man trykker på “run” og ser skitsen på nogle telefoner. Desuden kan alle skitserne, som beskrevet ovenfor, fylde meget på app-skærmen. Ikke at skulle installere skitser er nok APDE’s mest efterspurgte funktion.

Jeg havde oprindeligt to løsningsforslag til dette problem. For det første skal du bruge Processing.js til at konvertere skitsen til JavaScript og køre den i et WebView. For det andet at drage fordel af Instant Apps til at køre en skitse uden at installere den. Begge disse løsninger er stadig ufuldstændige. Processing.js er forældet og understøtter ikke nogen native Android-API’er, f.eks. accelerometeret. Instant Apps er i bedste fald en vakkelvorn idé, fordi jeg ikke engang ved, om det vil være muligt at forfalske debuggeren til at hoste skitserne lokalt og køre dem, eller om det vil være hurtigere end blot at installere dem.

Godt nok har knækningen af urskive-nødden givet mig en ny tilgang. APDE behøver ikke at konvertere en skitse til JavaScript eller bygge en øjeblikkelig app. Den skal bare tage den eksisterende skitse og indlæse den i klasser i stedet for at installere den.

Med denne tilgang behøver APDE kun at bygge ressourcerne med AAPT, kompilere klasserne med ECJ og dex-klasserne. På min telefon tager hele denne proces mindre end to sekunder (selv om mange telefoner er betydeligt langsommere), hvilket er en stor forbedring i forhold til at skulle bygge APK’en og installere den.

Med henblik på endnu længere fremadrettet planlægger jeg at implementere inkrementel kompilering til sommer, dvs. at lade kompileren køre i baggrunden for at vise fejlene i realtid. Med dette system på plads vil skitsen sandsynligvis være kompileret, endnu før brugeren trykker på run-knappen, hvilket betyder, at det eneste, der er tilbage, er dexing. Med andre ord kan class loaders tænkes at kunne skrumpe byggeprocessen til mindre end et sekund, afhængigt af telefonens hardware selvfølgelig.

Der er meget spændende endnu denne sommer!

Fin

Hvis du vil udforske de ændringer, jeg har foretaget, mere detaljeret, kan du tjekke android-mode-4-grenen på GitHub. Jeg har efterladt detaljerede commit-meddelelser (for det meste), og al koden er der.

Hold øje med preview-mode!