Sådan begynder du at bruge C ++ - kode i dit Android-projekt

Sidste år holdt jeg en tale på GDG DevFest i Ankara, Tyrkiet. Jeg har planlagt at dele den samtale her lige siden. Nu hvor jeg er ph.d.-kandidat og har lidt mere tid, lægger jeg stillingen hernede.

Hvis du gerne vil have præsentationen, er den tilgængelig på mit drev.

Opvarmning

Jeg vil gerne starte med at forklare byggeprocessen for en app i Android. Fordi du har brug for at kende nogle grundlæggende interne ting, er dette emne noget teknisk.

Du behøver ikke at vide alt vist på billedet ovenfor - men det er en god reference.

Sig nu, at du skriver en applikation til Android ved hjælp af Java. Du får:

  • kildekoden til den applikation
  • en slags ressourcefiler (som billeder eller xml-filer til arrangementet af GUI)
  • og måske nogle AIDL-filer, som er Java-grænseflader, der får processer til at tale med hinanden.

Du vil sandsynligvis også bruge yderligere biblioteker og deres relaterede filer i dit projekt.

Når du bygger en fungerende app, kompilerer du først disse kildekoder sammen. En kompilator giver en DEX-fil, som derefter kan læses af en virtuel maskine. Denne maskinlæsbare fil og nogle yderligere oplysninger om appen pakkes sammen af ​​en pakkehåndtering. Den endelige pakke - kaldet en APK-pakke - er den endelige app.

Dette er byggeprocessen for en Android-pakke i de enkleste termer.

Android Run Time

Lad os nu tale om kørselstiden. Du har en app, og når den begynder at køre, læses den af ​​en maskine. Android har to slags virtuelle maskiner til at køre en app. Jeg introducerer ikke den gamle, kaldet Dalvik, da de fleste Android-enheder i dag kører en virtuel maskine kaldet Android Run Time, ART - så det er det, vi vil tale om her.

ART er en virtuel maskine i forvejen (AOT). Så hvad betyder det? Lad mig forklare. Når din app begynder at køre for første gang, kompileres dens kode til maskinkode, som derefter kan læses af den rigtige maskine. Dette betyder, at koden ikke kompileres del for del i løbetid. Dette forbedrer installationstiden for appen, samtidig med at batteriforbruget reduceres.

Alt i alt skriver du en app og kompilerer den derefter til binær kode, som læses af ART. Derefter konverterer ART den kode til native-kode, som kan læses af selve enheden.

ART & C ++

Hvad hvis du skriver en Android-app ved hjælp af Java, men der er en C ++ -kode, der er i kontakt med Java? Hvad er effekten af ​​denne C ++ - kode på din apps byggeproces eller driftstid? Ikke for meget.

C ++ - koden kompileres direkte til den rigtige maskinkode af sin kompilator. Så hvis du bruger C ++ - kode, pakkes den som maskinlæsbar kode i din pakke. ART behandler den ikke igen, mens den konverterer den ART-læselige kode til maskinlæsbar kode ved første brug. Du behøver ikke bekymre dig om denne proces. Du er kun ansvarlig for at skrive en grænseflade, der lader Java tale med C ++. Vi taler snart om det.

C ++ byggeproces

Vi er nu nødt til at tale om C ++ - byggeprocessen. Kildekoden (.cpp- og .h-filerne) omdannes til en udvidet kildekode af en forprocessor i det allerførste trin. Denne kildekode indeholder en hel masse kode. Mens du kan få den endelige eksekverbare fil ved hjælp af en kommando som ovenfor, er det muligt at klippe byggetrinene med relaterede flag. Du kan få den udvidede kilde ved at give -E- flag til g ++ compileren. Jeg har en 40867 linjefil til en 4 linjers 'hej verden' .cpp kildekode.

Brug g ++ -E hello.cpp -o hello.ii for at få den udvidede kildekode.

Den anden er det egentlige kompileringstrin. Compileren kompilerer vores kode for at få en assembler-fil. Så den virkelige kompilering giver en samlerfil, ikke den eksekverbare. Denne fil samles af en samler. Den resulterende kode kaldes objektkode. Når vi har flere biblioteker, der sigter mod at blive knyttet til hinanden, har vi mange objektkoder. Disse objektkoder er linket af en linker. Så får vi en eksekverbar.

Der er to slags forbindelser: dynamisk og statisk.

Så nu er det tid til at gå lidt dybere, når vi diskuterer rene C ++ ting.

Den vigtige ting: Du kan overveje statiske tilknyttede biblioteker som en del af din kode. Så vær forsigtig, når du linker et bibliotek til dit projekt. Fordi det bibliotek, du bruger, muligvis ikke har en passende licens til at blive statisk knyttet. De fleste open source-biblioteker er begrænset til at blive brugt som dynamisk forbundet.

Fra et teknisk synspunkt er et statisk linket bibliotek knyttet til projektet ved byggetid af compileren. På den anden side er et dynamisk linket bibliotek forbundet med operativsystemet ved kørselstid. Så du behøver ikke distribuere dit projekt med den bibliotekskode, du bruger. Du kan også bruge et andet projekts bibliotek eller systembibliotek.

På grund af dette faktum kan dynamisk link forårsage sårbarhed i dit projekt. Mens sikkerhedssagen ikke er omfattet af dette indlæg.

Nogle begreber

CMake og Gradle

Hvis vi vil tilføje C ++ - kode i vores Android-projekt, er det godt at bruge CMake til at håndtere buildoperationer. Husk den byggeproces, jeg lige har introduceret ovenfor? Når du har en masse C ++ - biblioteker og kildekode, bliver det mere kompliceret at håndtere dem alle. Et værktøj som CMake gør det lettere at udføre byggeprocessen.

CMake vil være tilgængelig som standard, når du vælger at medtage C ++ support i starten af ​​dit projekt. Du skal også bruge en Gradle-lukning for at pakke biblioteker til din APK.

ABI

Som du ved, distribueres Android til en række forskellige enheder. Hver enhed kan have en anden CPU-arkitektur. Når du udvikler en Android-applikation, der indeholder C ++ -kode, skal du være opmærksom på de platforme, som din applikation kører på.

Kan du huske C ++ - byggemekanismen, jeg introducerede ovenfor? C ++ - koden skal kompileres som et bibliotek for hver platform, du målretter mod. Du kan kompilere biblioteket til alle understøttede platforme, eller du kan vælge at kompilere det til kun en platform.

Bemærk, at 64-bit ABI-support er obligatorisk med Android Pie-udgivelse, hvis du vil placere din app i Google Play Butik.

JNI

Dette er den sidste ting, jeg gerne vil introducere dig til angående C ++ brug i Android. Som jeg nævnte tidligere introducerer jeg dig disse begreber i betragtning af at du vil udvikle en app ved hjælp af Java.

JNI er en forkortelse for Java Native Interface. Det giver C ++ og Java-dele mulighed for at tale med hinanden på de enkleste vilkår. For eksempel, hvis du vil kalde en funktion fra C ++ i Java, skal du skrive et JNI-interface til dette formål.

Den native-lib.cpp er grænsefladen, og den forbinder C ++ -koden til Java-koden. I ovenstående eksempel er den eneste C ++ - kode selve JNI. Du kan dog inkludere de biblioteker, du vil bruge, og implementere en funktion, der kalder dem. Denne nye funktion kan kaldes fra Java-delen. Så det fungerer som en bro på den måde.

Ting at gøre, hvis du vil prøve det

Her har du al den nødvendige og grundlæggende viden til at bruge C ++ i dit Android-projekt. Hvis du vil prøve, kan du oprette et simpelt Android-projekt med C ++ - kode.

Nedenstående billeder viser trinene for at starte et sådant projekt. Når du er færdig med dem, kan du måske læse dette indlæg for at ændre og forstå mekanismen dybere.

Dette indlæg var kun en introduktion. Glem ikke, at der er mange flere ting at lære. Imidlertid havde jeg til formål at introducere dig til de vigtigste ting ved begrebet at bruge C ++.