{"id":16370,"date":"2019-07-01T08:00:17","date_gmt":"2019-07-01T06:00:17","guid":{"rendered":"https:\/\/www.inovex.de\/blog\/?p=16370"},"modified":"2022-11-21T15:32:36","modified_gmt":"2022-11-21T14:32:36","slug":"android-ar-arcore-poly","status":"publish","type":"post","link":"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/","title":{"rendered":"Augmented Reality to-go mit ARCore und Poly f\u00fcr Android"},"content":{"rendered":"<p>Ans\u00e4tze f\u00fcr AR auf Mobilger\u00e4ten sind kein neuer Trend, in den letzten Jahren hat sich jedoch einiges getan: Durch technische Innovationen wie bessere Kameras und leistungsf\u00e4higere Hardware sind die Grenzen des machbaren weiter verschoben worden. Auch Spiele wie Pok\u00e9mon GO haben dem Thema eine medial Aufmerksamkeit beschert, in deren Zug weitere Hersteller AR Apps entwickeln. Um diesem Trend gerecht zu werden, hat Google im M\u00e4rz 2018 ARCore ver\u00f6ffentlicht. Mit diesem SDK lassen sich Augmented Reality Apps f\u00fcr Android und iOS erstellen, die auf einer definierten Liste von <a href=\"https:\/\/developers.google.com\/ar\/discover\/supported-devices\">unterst\u00fctzen Ger\u00e4ten<\/a>\u00a0lauff\u00e4hig sind. ARCore ist dabei nicht der einzige Ansatz f\u00fcr AR auf Mobilger\u00e4ten: Bereits im Vorjahr hatte Apple, gleichzeitig mit der Ank\u00fcndigung von iOS 11, das ARKit f\u00fcr iOS vorgestellt.<\/p>\n<p>Im Rahmen meines Praxissemesters habe ich mit ARCore eine Android-Anwendung entwickelt, mit der 3D-Modelle im Raum platziert und dargestellt werden k\u00f6nnen. Zus\u00e4tzlich kann der User auf verschiedenen Wegen mit den Modellen interagieren. Die 3D-Modelle kommen dabei von Poly, Googles Datenbank f\u00fcr 360-Grad-Fotos, VR-Szenen und 3D-Modelle.<!--more--><\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_79_2 counter-hierarchy ez-toc-counter ez-toc-custom ez-toc-container-direction\">\n<div class=\"ez-toc-title-container\"><p class=\"ez-toc-title\" style=\"cursor:inherit\"><\/p>\n<\/div><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#Poly-API\" >Poly API<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#ARCore\" >ARCore<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#Fazit\" >Fazit<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#Mitmachen\" >Mitmachen!<\/a><\/li><\/ul><\/nav><\/div>\n<h2><span class=\"ez-toc-section\" id=\"Poly-API\"><\/span>Poly API<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Zu Poly geh\u00f6ren neben einer Website und einer RESTful API auch verschiedene Plugins und Toolkits. Mit diesen k\u00f6nnen 3D-Modelle entweder direkt aus Blender, Maya, Cinema 4D oder 3Ds Max exportiert und zu der Poly-Datenbank hinzugef\u00fcgt werden oder in Unity oder Unreal importiert werden. In der Beispielanwendung nutze ich die RESTful API, um die Datenbank zu durchsuchen und Modelle herunterzuladen.<\/p>\n<p>\u00dcber die API k\u00f6nnen diverse Informationen zu \u00f6ffentlichen Assets abgefragt werden. Der Server antwortet dabei im JSON-Format. Au\u00dferdem kann bis ins Detail differenziert werden, welche Felder der Assets in den JSON-Objekten enthalten sein sollen. Die Strukturierung der JSON-Objekte kann in der Dokumentation nachgelesen werden und ist meiner Meinung nach \u00fcbersichtlich und nachvollziehbar. Neben einzelnen Assets kann auch eine Liste von Assets angefordert werden. Auch hierbei kann pr\u00e4zise definiert werden, welche Informationen in der Antwort enthalten sind und vor allem, wonach bei der Auswahl der Assets gefiltert werden sollen. Beispiele f\u00fcr m\u00f6gliche Filter sind: Kategorie, Dateiformat, Lizenz, Komplexit\u00e4t der 3D-Modelle, Keyw\u00f6rter. Eine komplette Liste der Filterkriterien kann der Dokumentation entnommen werden. Bei jeder Abfrage muss zus\u00e4tzlich ein g\u00fcltiger API-Key enthalten sein, der auf der Poly-Webeite generiert wird.<\/p>\n<p><em>Ein n\u00fctzliches Tool beim Zusammenbasteln der GET-Request ist Googles <a href=\"https:\/\/developers.google.com\/apis-explorer\/#search\/poly\/poly\/v1\/\">apis-explorer<\/a>. Dort findet man eine \u00dcbersicht von allen von der API bereitgestellten Services und kann Feld f\u00fcr Feld seine eigenen Kriterien angeben, die fertige GET-Request und die entsprechende Antwort einsehen.\u00a0<\/em><\/p>\n<div>In der Beispielanwendung verwende ich Retrofit als REST Client. Der folgende Code zeigt einen Ausschnitt aus dem von Retrofit implementierten Interface f\u00fcr die http-Requests. Die Methode <em>getAssetList()<\/em>\u00a0bekommt eine <em>Map<\/em> \u00fcbergeben, die alle gew\u00fcnschten Query-Parameter enth\u00e4lt und liefert ein <em>Data Class-<\/em>Objekt <em>Assets<\/em> zur\u00fcck. <em>Assets<\/em>\u00a0wiederum enth\u00e4lt eine Liste von <em>Asset<\/em>-Objekten, die alle angefragten Informationen enthalten.<\/div>\n<pre class=\"lang:default decode:true \" title=\"Interface f\u00fcr die PolyApi\">interface PolyApi {\r\n\r\n    companion object Factory {\r\n\r\n        private const val BASE_URL = \"https:\/\/poly.googleapis.com\/v1\/\"\r\n\r\n        fun create(): PolyApi {\r\n\r\n            val retrofit = retrofit2.Retrofit.Builder()\r\n\r\n                .baseUrl(BASE_URL)\r\n\r\n                .addConverterFactory(GsonConverterFactory.create())\r\n\r\n                .build()\r\n\r\n            return retrofit.create(PolyApi::class.java)\r\n\r\n        }\r\n\r\n    }\r\n\r\n    @GET(\"assets\")\r\n\r\n    fun getAssetList(@QueryMap(encoded = true) options: Map&lt;String, String&gt;): Call&lt;Assets&gt;\r\n\r\n    @Streaming\r\n\r\n    @GET\r\n\r\n    fun get3DModel(@Url fileUrl:String): Call&lt;ResponseBody&gt;\r\n\r\n}<\/pre>\n<p>Da die Query aus teils statischen und teils dynamischen Feldern zusammengef\u00fcgt werden soll, verpacke ich den Funktionsaufruf von oben in einer Wrapper-Klasse <em>UseCasePolyApi<\/em>. In dieser sind alle statischen Teile der Query definiert. Beim Funktionsaufruf von <em>getAssetList()<\/em>\u00a0werden die vom User verwendeten Keyw\u00f6rter und\/oder die Kategorie zu der QueryMap hinzugef\u00fcgt und anschlie\u00dfend an die Implementierung des Interface durchgereicht.<\/p>\n<pre class=\"lang:default decode:true\" title=\"Kopf der Klasse UseCasePolyApi\">class UseCasePolyApi(private val polyApi: PolyApi) {\r\n\r\n    companion object {\r\n\r\n        private const val FORMAT = \"GLTF2\"\r\n\r\n        private const val FIELDS =\r\n\r\n            \"assets(authorName%2Cdescription%2CdisplayName%2Cformats%2Cname%2Cthumbnail)\"     \/\/ determine the necessary fields\r\n\r\n        private const val API_KEY = \"Insert key here\"\r\n\r\n        private const val PAGESIZE = \"50\"\r\n\r\n    }\r\n\r\n    private val queryMap = mutableMapOf(\r\n\r\n        \"format\" to FORMAT,\r\n\r\n        \"fields\" to FIELDS,\r\n\r\n        \"key\" to API_KEY,\r\n\r\n        \"pageSize\" to PAGESIZE\r\n\r\n    )\r\n\r\n    fun getAssetList(\r\n\r\n        category: AssetRepository.AssetCategory = AssetRepository.AssetCategory.none,\r\n\r\n        keywords: String? = null\r\n\r\n    ): Call&lt;Assets&gt; {\r\n\r\n        if (category.name != \"none\") {\r\n\r\n            queryMap[\"category\"] = category.name\r\n\r\n        }\r\n\r\n        if (keywords != null) {\r\n\r\n            queryMap[\"keywords\"] = keywords\r\n\r\n        }\r\n\r\n        return polyApi.getAssetList(queryMap)\r\n\r\n    }\r\n\r\n...<\/pre>\n<p>Nach Erhalt der Antwort k\u00f6nnen die Ergebnisse nach Bedarf entsprechend weiterverarbeitet werden. In meinem Fall verwende ich von jedem Asset Titel, Autor und Thumbnail, um dem User verf\u00fcgbare 3D-Modelle in einer Liste zu pr\u00e4sentieren.<\/p>\n<figure id=\"attachment_16371\" aria-describedby=\"caption-attachment-16371\" style=\"width: 491px\" class=\"wp-caption alignnone\"><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-16371\" src=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/Startbild-App-576x1024.png\" alt=\"Eine zweispaltige Liste von 3D-Modellen: Vending Machine, Schneemann, Fuchs, ...\" width=\"491\" height=\"873\" srcset=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/Startbild-App-576x1024.png 576w, https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/Startbild-App-169x300.png 169w, https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/Startbild-App-768x1365.png 768w, https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/Startbild-App-864x1536.png 864w, https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/Startbild-App-400x711.png 400w, https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/Startbild-App-360x640.png 360w, https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/Startbild-App.png 1080w\" sizes=\"auto, (max-width: 491px) 100vw, 491px\" \/><figcaption id=\"caption-attachment-16371\" class=\"wp-caption-text\">Screenshot des Startbildschirms der App<\/figcaption><\/figure>\n<h2><span class=\"ez-toc-section\" id=\"ARCore\"><\/span>ARCore<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Das wichtigste Feature von ARCore ist, dass das Telefon seine Position im Raum versteht und verfolgt. Durch die Kombination der optischen Daten der Kamera und den Daten der Lage- und Beschleunigungssensoren gelingt dies bei entsprechenden Umgebungsverh\u00e4ltnissen erstaunlich gut. Je mehr optisch-markante Punkte in der Umgebung sind, desto besser funktioniert das Positions-Tracking. In einem leeren Raum mit wei\u00dfen W\u00e4nden und einfarbigem Teppich sollte man also nicht zu viel erwarten. W\u00e4hrend der Vorg\u00e4nger Tango noch einen Tiefensensor ben\u00f6tigte, braucht ARCore diesen nicht.<\/p>\n<p>Weitere Features von ARCore sind Oberfl\u00e4chenerkennung (egal ob horizontal, vertikal oder schr\u00e4g), Lichtverh\u00e4ltnisse absch\u00e4tzen und Augmented Images. ARCore kann bis zu 20 Bilder gleichzeitig erkennen und Feedback geben, dass Bilder erkannt wurden und wo diese sich befinden. Was der Entwickler aus diesen Informationen macht, liegt bei ihm. Welche Bilder erkannt werden sollen, muss vorher definiert werden. Dabei gibt es bestimmte Kriterien, die die Bilder erf\u00fcllen m\u00fcssen. Diese Kriterien werden ausf\u00fchrlich in der <a href=\"https:\/\/developers.google.com\/ar\/develop\/java\/augmented-images\/\">Dokumentation<\/a> erl\u00e4utert.<\/p>\n<p>Wer vor allem dieses Feature nutzen m\u00f6chte, sollte kl\u00e4ren, ob er dazu ARCore einsetzen will. Denn der Schwerpunkt von ARCore liegt nicht auf Augmented Images. Bei einer App, die ausschlie\u00dflich dieses Feature verwendet, lohnt es sich einen Blick auf zum Beispiel <a href=\"https:\/\/www.vuforia.com\/\">vuforia<\/a> zu werfen. Vuforia kann in Bezug auf Augmented Images deutlich mehr und dies vor allem besser als ARCore.<\/p>\n<p>Mit ARCore ist es m\u00f6glich seine Augmented-Reality-Erfahrungen auch mit anderen zu teilen,\u00a0selbst zwischen Android- und iOS-Ger\u00e4ten. Bei sogenannten CloudAnchorn werden visuell-markante Punkte in die Cloud hochgeladen und \u00fcber einen Key zug\u00e4nglich gemacht. Jeder mit Zugang zu diesem Key kann den Ankerpunkt herunterladen. Wenn ARCore diesen Punkt lokal wiedererkennt, wird dieser zur Szene hinzugef\u00fcgt. CloudAnchor liefert dabei nur die Position des Punktes. Um eine Szene auf mehreren Ger\u00e4ten aufzubauen ist es daher notwendig, Informationen \u00fcber 3D-Asset an dieser Position getrennt zu kommunizieren.<\/p>\n<p>Da nicht jeder, der eine Augmented Reality App schreiben will, auch gleichzeitig hervorragende Kenntnisse im Bereich OpenGL mitbringt, hat Google zus\u00e4tzlich <a href=\"https:\/\/developers.google.com\/ar\/develop\/java\/sceneform\/\">Sceneform<\/a> ver\u00f6ffentlicht. Denn mit dem Rendern von 3DModellen hat ARCore zun\u00e4chst nichts zu tun. Sceneform enth\u00e4lt eine high-level Scenen-Graph-API, einen physikbasierten Renderer sowie ein Plugin f\u00fcr Android Studio zum importieren und ansehen von 3D-Modellen. Die g\u00e4ngigsten 3D-Formate wie OBJ, FBX und GLTF2 werden von Sceneform unterst\u00fctzt. Mit dem Plugin wird f\u00fcr jedes importierte Modell eine SFA- und eine SFB-Datei erzeugt. Diese beiden Dateien sind speziell f\u00fcr Mobile optimiert und werden von Sceneform verarbeitet.<\/p>\n<p>Der eigentliche Arbeitsablauf mit Sceneform ist folgender: Vor dem Erstellen der APK ist bekannt, welche 3D-Modelle in der Applikation gerendert werden sollen. Entsprechende Modelle werden in Android Studio importiert und SFA- und SFB-Dateien werden erzeugt. Die Applikation wird gebaut und ben\u00f6tigte Dateien werden in die APK integriert.<\/p>\n<p>Meine Anwendung hat jedoch folgende Pr\u00e4misse: Der User w\u00e4hlt zur Laufzeit aus, welche Modelle er darstellen m\u00f6chte. Anschlie\u00dfend werden die entsprechenden Modelle heruntergeladen und zuletzt gerendert. Dieser Ansatz f\u00fchrt dazu, dass ausschlie\u00dflich 3D-Modelle im GLTF2-Format f\u00fcr die Applikation interessant sind, da Sceneform diese als einzige auch zur Laufzeit verarbeiten kann.<\/p>\n<pre class=\"lang:default decode:true\" title=\"makeModelFromUrl-Methode aus MyArFragment\">...\r\n\r\nprivate fun makeModelFromUrl(key: Int, path: String) {\r\n\r\n        val uri = Uri.parse(path)\r\n\r\n        ModelRenderable.builder()\r\n\r\n            .setSource(\r\n\r\n                this.context, RenderableSource.builder().setSource(\r\n\r\n                    this.context,\r\n\r\n                    uri,\r\n\r\n                    RenderableSource.SourceType.GLTF2\r\n\r\n                ).build()\r\n\r\n            )\r\n\r\n            .setRegistryId(uri)\r\n\r\n            .build()\r\n\r\n            .thenAccept {\r\n\r\n                val model = it\r\n\r\n                if (model != null) {\r\n\r\n                    modelBlueprintsMap[key] = model\r\n\r\n                }\r\n\r\n            }\r\n\r\n            .exceptionally {\r\n\r\n                Log.e(TAG, it.message)\r\n\r\n                val toast = Toast.makeText(this.context, \"Unable to load renderable\", Toast.LENGTH_LONG)\r\n\r\n                toast.setGravity(Gravity.CENTER, 0, 0)\r\n\r\n                toast.show()\r\n\r\n                null\r\n\r\n            }\r\n\r\n    }\r\n\r\n...<\/pre>\n<p>Die abgebildete Methode erzeugt ein <em>ModelRenderable<\/em>\u00a0und f\u00fcgt es einer <em>Map<\/em> an. Das Objekt kann dann zu beliebig vielen Knoten hinzugef\u00fcgt werden und wird an diesen gerendert.<\/p>\n<p>Das Platzieren von Modellen in der AR-Szene ist dank Sceneform sehr einfach. Ein von Sceneform bereitgestelltes <em>ARFragment<\/em>\u00a0enth\u00e4lt alles notwendige, um Oberfl\u00e4chen zu erkennen und Ankerpunkte auf diesen zu platzieren. An diese Ankerpunkte k\u00f6nnen dann die ModelRenderables geh\u00e4ngt werden. Au\u00dferdem liefert Sceneform die Klasse <em>TransformableNode<\/em>. Objekte dieser Klasse k\u00f6nnen \u00fcber verschiedene Touch-Gesten verschoben, skaliert oder rotiert werden.<\/p>\n<pre class=\"lang:default decode:true \" title=\"Ausschnitt aus MyArFragment.kt\">...\r\n\r\noverride fun onCreate(savedInstanceState: Bundle?) {\r\n\r\n        super.onCreate(savedInstanceState)\r\n\r\n        mainActivity = activity as MainActivity\r\n\r\n        activity?.window?.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)\r\n\r\n        walletViewModel.isArActive = true       \/\/ to disable the remove button and to enable selection in wallet\r\n\r\n        this.setOnTapArPlaneListener { hitResult: HitResult, _, _ -&gt;\r\n\r\n            val anchor = hitResult.createAnchor()\r\n\r\n            val anchorNode = AnchorNode(anchor)\r\n\r\n            anchorNode.setParent(this.arSceneView.scene)\r\n\r\n            placeAndSelectModel(anchorNode)\r\n\r\n        }\r\n\r\n    }\r\n\r\n...\r\n\r\nprivate fun placeAndSelectModel(anchorNode: AnchorNode) {\r\n\r\n        val transformableNode = AdvancedTransformableNode(this.transformationSystem, this)\r\n\r\n        transformableNode.renderable = modelBlueprintsMap[walletViewModel.currentEntry]\r\n\r\n        transformableNode.resize()\r\n\r\n        transformableNode.setParent(anchorNode)\r\n\r\n        nodesList.add(transformableNode)\r\n\r\n        transformableNode.select()\r\n\r\n        onTabSelect(transformableNode)\r\n\r\n    }\r\n\r\n...<\/pre>\n<p>Der Codeausschnitt stammt aus meiner von<em>\u00a0ARFragment<\/em>\u00a0erbenden Klasse. In der onCreate-Methode setzte ich einen <em>OnTabArPlaneListener<\/em>. Dieser sorgt daf\u00fcr, dass ein neuer Knoten erzeugt wird, wenn auf eine gefundene Oberfl\u00e4che getippt wird. An diesem Knoten wird dann ein <em>AdvancedTransformableNode<\/em>\u00a0erzeugt. Dieser bekommt ein ModelRenderable zugewiesen, wird neu skaliert und dann an den ganz am Anfang erzeugten Ankerpunkt geh\u00e4ngt.<\/p>\n<p>Um ein paar m\u00f6gliche Interaktionen mit <em>TransformableNode<\/em>\u00a0zu zeigen, habe ich die Klasse <em>AdvancedTransformableNode<\/em>\u00a0erstellt. Diese erbt von <em>TransformableNode<\/em>. Jeder Knoten speichert seine Position und Rotation. Diese Felder k\u00f6nnen nach Belieben ge\u00e4ndert werden, woraufhin Sceneform das gerenderte Model dementsprechend anpasst. Mit ein bisschen linearer Algebra (Position repr\u00e4sentiert durch 3-dimensionalen Vektor und Rotationen repr\u00e4sentiert durch Quaternion) lassen sich allerlei Spielerein mit den 3D-Modellen anstellen.<\/p>\n<p>Jeder Knoten besitzt eine <em>onUpdate<\/em>-Methode, die jeden Frame aufgerufen wird. Diese kann \u00fcberschrieben werden, um zum Beispiel zu \u00fcberpr\u00fcfen wie weit ein anderer Knoten entfernt ist, das Model zu verschieben oder zu rotieren.<\/p>\n<pre class=\"lang:default decode:true \" title=\"Ausschnitt aus der AdvancedTransformableNode.kt\">...\r\n\r\nprivate val rotationSpeed = 1f\r\n\r\nprivate val interactionRangeCam = 1.1f\r\n\r\noverride fun onUpdate(frameTime: FrameTime) {\r\n\r\n    if(isLocked) {\r\n\r\n        lookAtCamera()\r\n\r\n    } else if (cameraInRange()) {\r\n\r\n        rotateAroundY()\r\n\r\n    }\r\n\r\n}\r\n\r\n...\r\n\r\nprivate fun cameraInRange(): Boolean {\r\n\r\n    return (worldPosition.distance(scene.camera.worldPosition) &lt;= interactionRangeCam)\r\n\r\n}\r\n\r\nprivate fun lookAtCamera() {\r\n\r\n    val cameraPosition = scene.camera.worldPosition\r\n\r\n    val direction = Vector3.subtract(worldPosition,cameraPosition )\r\n\r\n    val lookRotation = Quaternion.lookRotation(direction, Vector3.up())\r\n\r\n    worldRotation = lookRotation\r\n\r\n}\r\n\r\nprivate fun rotateAroundY() {\r\n\r\n    val rotation = Quaternion.axisAngle(Vector3.up(), rotationSpeed)\r\n\r\n    worldRotation = Quaternion.multiply(worldRotation, rotation)\r\n\r\n}\r\n\r\nfun Vector3.distance(v2: Vector3): Float {\r\n\r\n    val x = (v2.x - this.x) * (v2.x - this.x)\r\n\r\n    val y = (v2.y - this.y) * (v2.y - this.y)\r\n\r\n    val z = (v2.z - this.z) * (v2.z - this.z)\r\n\r\n    return Math.sqrt((x + y + z).toDouble()).toFloat()\r\n\r\n}\r\n\r\n...<\/pre>\n<p>Der Codeabschnitt zeigt einen Auszug aus <em>AdvancedTransformableNode<\/em>. Wenn zum Beispiel ein bestimmter Schwellenwert bei der Entfernung zwischen Kamera und Knoten unterschritten wird, beginnt das Model sich um die eigene Y-Achse zu drehen. Oder wenn ein Boolean entsprechend gesetzt wird, dreht sich das Model kontinuierlich mit seiner Vorderseite zur Kamera.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Fazit\"><\/span>Fazit<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Meine Erfahrungen bei der Arbeit mit der Poly API sind insgesamt gut. Die Dokumentation ist sehr ausf\u00fchrlich und beinhaltet anschauliche Beispiele, die den Einstieg erleichtern. Zus\u00e4tzlich hat Googles <em>APIs Explorer<\/em>\u00a0beim Erstellen der Querys geholfen. Jedoch ist die Poly API noch nicht optimal umgesetzt. So bin ich auf einen Bug in den GLTF2-Dateien von Poly gesto\u00dfen, der dazu f\u00fchrt, dass Dateien mit einem Leerzeichen im Namen der Ressource-Datei nicht von Sceneform verarbeitet werden k\u00f6nnen.\u00a0 Hier scheitert es daran, dass die Poly API URIs innerhalb dieser Datei nicht korrekt enkodiert. Nachdem dieser Bug von mir gemeldet wurde, gab es bisher noch keine R\u00fcckmeldung. Es ist zu hoffen, dass Poly diesen und andere Bugs angeht und eine stabile API anbietet.<\/p>\n<p>Auch f\u00fcr ARCore ist die Dokumentation sehr ausf\u00fchrlich. Man kann au\u00dferdem verschiedene Beispielprojekte herunterladen und die Features des SDK damit erkunden. Dieses Vorgehen habe ich adaptiert, was sich als sehr n\u00fctzlich erwiesen hat. Das Positions-Tracking funktioniert in meinen Tests gut. Selbst wenn das Smartphone zwischendurch die Position verliert, zum Beispiel wenn der Finger die Kamera verdeckt, schafft es ARCore meistens, sich wieder zu orientieren.<\/p>\n<p>Sceneform stehe ich mit gemischten Gef\u00fchlen gegen\u00fcber. Die Dokumentation enth\u00e4lt kaum n\u00fctzliche Beispiele und Erl\u00e4uterungen zu wichtigen Komponenten fehlen oft ganz. Bei dem Github Repository von Sceneform sind jede Menge offene Issues und es gibt kaum Feedback von den Entwicklern. Auch ist der Feature-Umfang von Sceneform sehr begrenzt. Es kann keine Animationen abspielen und beim Debuggen ist es nicht m\u00f6glich <em>einen Schritt zur\u00fcckzutreten<\/em> und die Szene von au\u00dferhalb der Kamera zu betrachten. Solche n\u00fctzlichen Features bieten andere Programme wie zum Beispiel Unity. Auch gibt es keine M\u00f6glichkeit, seine Szene au\u00dferhalb der Laufzeit zu betrachten.<\/p>\n<p>F\u00fcr einfache Anwendungsf\u00e4lle von Augmented Reality reicht Sceneform aber auf jeden Fall aus. Man ben\u00f6tigt keine zus\u00e4tzlichen Technologien (sofern man Zugang zu 3D-Modellen hat) und die Entwicklung kann komplett in Android Studio erfolgen. Will man jedoch komplexere Anwendungsf\u00e4lle von Augmented Reality umsetzen, so empfehle ich auf Unity\/Unreal zur\u00fcckzugreifen. Beide Umgebungen sind daf\u00fcr gemacht, in 3D-Szenen zu arbeiten und bieten unz\u00e4hlige Features und Debug-Mechanismen f\u00fcr 3D-Welten. Auch Animationen sind hier im Gegensatz zu Sceneform m\u00f6glich.<\/p>\n<p>Um dies zu verdeutlichen habe ich testweise eines der Beispielprojekte von ARCore in Unity importiert. In diesem Projekt habe ich das zu rendernde Modell durch eine Figur mit mehreren Animationen ausgetauscht und konnte auf Anhieb eine tanzende Figuren bei mir im B\u00fcro platzieren. Dass dies nur etwa 20 Minuten Zeit gekostet hat zeigt, dass Unity hier in kurzer Zeit Ergebnisse erzeugen kann, die so in Sceneform gar nicht m\u00f6glich sind. Selbst den OpenGL-Code daf\u00fcr zu schreiben dauert wahrscheinlich deutlich l\u00e4nger.<\/p>\n<p>Meine App ist auf <a href=\"https:\/\/github.com\/FloriJann\/MultiAR\">Github<\/a> zu finden. Der interessierte Tester sei jedoch gewarnt: Gelegentlich st\u00fcrzt Sceneform ohne Vorwarnung oder Fehlermeldung ab. Wie oben erw\u00e4hnt, gibt es hier noch einiges zu tun in der Bibliothek. Auch der Beispielcode ist noch nicht ganz fehlerfrei. An der ein oder anderen Stelle findet man, wenn man genauer hinsieht, sicherlich noch einen Bug. Als <em>Proof of Concept<\/em> funktioniert die App meiner Meinung nach jedoch sehr gut.<\/p>\n<p>Viel Spa\u00df beim Ausprobieren!<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Mitmachen\"><\/span>Mitmachen!<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Wer noch mehr Infos \u00fcber <a href=\"https:\/\/www.inovex.de\/de\/leistungen\/apps\/\">unser Mobile-Portfolio<\/a> m\u00f6chte, findet dazu alles auf unserer Website. Dar\u00fcber hinaus besch\u00e4ftigen wir uns mit <a href=\"https:\/\/www.inovex.de\/de\/leistungen\/smart-devices-robotics\/\">Smart Devices &amp; Robotics<\/a>. Wer schon Erfahrung mit Augmented Reality hat, findet vielleicht unter <a href=\"https:\/\/www.inovex.de\/de\/karriere\/stellenangebote\/\">unseren Stellenangeboten<\/a> etwas passendes.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ans\u00e4tze f\u00fcr AR auf Mobilger\u00e4ten sind kein neuer Trend, in den letzten Jahren hat sich jedoch einiges getan: Durch technische Innovationen wie bessere Kameras und leistungsf\u00e4higere Hardware sind die Grenzen des machbaren weiter verschoben worden. Auch Spiele wie Pok\u00e9mon GO haben dem Thema eine medial Aufmerksamkeit beschert, in deren Zug weitere Hersteller AR Apps entwickeln. [&hellip;]<\/p>\n","protected":false},"author":115,"featured_media":16490,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"ep_exclude_from_search":false,"footnotes":""},"tags":[74],"service":[420,712],"coauthors":[{"id":115,"display_name":"Florian Jann","user_nicename":"fjann"}],"class_list":["post-16370","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","tag-iot","service-apps","service-internet-of-things-iot"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Augmented Reality to-go mit ARCore und Poly f\u00fcr Android - inovex GmbH<\/title>\n<meta name=\"description\" content=\"Im Rahmen meines Praxissemesters habe ich mit ARCore eine Android-Anwendung entwickelt, mit der 3D-Modelle im Raum platziert und dargestellt werden k\u00f6nnen. Hier stelle ich den Entwicklungsprozess vor.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/\" \/>\n<meta property=\"og:locale\" content=\"de_DE\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Augmented Reality to-go mit ARCore und Poly f\u00fcr Android - inovex GmbH\" \/>\n<meta property=\"og:description\" content=\"Im Rahmen meines Praxissemesters habe ich mit ARCore eine Android-Anwendung entwickelt, mit der 3D-Modelle im Raum platziert und dargestellt werden k\u00f6nnen. Hier stelle ich den Entwicklungsprozess vor.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/\" \/>\n<meta property=\"og:site_name\" content=\"inovex GmbH\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/inovexde\" \/>\n<meta property=\"article:published_time\" content=\"2019-07-01T06:00:17+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-11-21T14:32:36+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/augmented-reality-arcore.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1920\" \/>\n\t<meta property=\"og:image:height\" content=\"1080\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Florian Jann\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/augmented-reality-arcore-1024x576.png\" \/>\n<meta name=\"twitter:creator\" content=\"@inovexgmbh\" \/>\n<meta name=\"twitter:site\" content=\"@inovexgmbh\" \/>\n<meta name=\"twitter:label1\" content=\"Verfasst von\" \/>\n\t<meta name=\"twitter:data1\" content=\"Florian Jann\" \/>\n\t<meta name=\"twitter:label2\" content=\"Gesch\u00e4tzte Lesezeit\" \/>\n\t<meta name=\"twitter:data2\" content=\"13\u00a0Minuten\" \/>\n\t<meta name=\"twitter:label3\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data3\" content=\"Florian Jann\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/\"},\"author\":{\"name\":\"Florian Jann\",\"@id\":\"https:\/\/www.inovex.de\/de\/#\/schema\/person\/b1134cd8726bb5387a31d8e4eeae0800\"},\"headline\":\"Augmented Reality to-go mit ARCore und Poly f\u00fcr Android\",\"datePublished\":\"2019-07-01T06:00:17+00:00\",\"dateModified\":\"2022-11-21T14:32:36+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/\"},\"wordCount\":2018,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.inovex.de\/de\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/augmented-reality-arcore.png\",\"keywords\":[\"IoT\"],\"articleSection\":[\"Applications\",\"General\"],\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/\",\"url\":\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/\",\"name\":\"Augmented Reality to-go mit ARCore und Poly f\u00fcr Android - inovex GmbH\",\"isPartOf\":{\"@id\":\"https:\/\/www.inovex.de\/de\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/augmented-reality-arcore.png\",\"datePublished\":\"2019-07-01T06:00:17+00:00\",\"dateModified\":\"2022-11-21T14:32:36+00:00\",\"description\":\"Im Rahmen meines Praxissemesters habe ich mit ARCore eine Android-Anwendung entwickelt, mit der 3D-Modelle im Raum platziert und dargestellt werden k\u00f6nnen. Hier stelle ich den Entwicklungsprozess vor.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#breadcrumb\"},\"inLanguage\":\"de\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#primaryimage\",\"url\":\"https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/augmented-reality-arcore.png\",\"contentUrl\":\"https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/augmented-reality-arcore.png\",\"width\":1920,\"height\":1080,\"caption\":\"Ein Smartphone projiziert eine ARcore Blume in einen Blumentopf\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.inovex.de\/de\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Augmented Reality to-go mit ARCore und Poly f\u00fcr Android\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.inovex.de\/de\/#website\",\"url\":\"https:\/\/www.inovex.de\/de\/\",\"name\":\"inovex GmbH\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/www.inovex.de\/de\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.inovex.de\/de\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"de\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.inovex.de\/de\/#organization\",\"name\":\"inovex GmbH\",\"url\":\"https:\/\/www.inovex.de\/de\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png\",\"contentUrl\":\"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png\",\"width\":1921,\"height\":1081,\"caption\":\"inovex GmbH\"},\"image\":{\"@id\":\"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/inovexde\",\"https:\/\/x.com\/inovexgmbh\",\"https:\/\/www.instagram.com\/inovexlife\/\",\"https:\/\/www.linkedin.com\/company\/inovex\",\"https:\/\/www.youtube.com\/channel\/UC7r66GT14hROB_RQsQBAQUQ\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.inovex.de\/de\/#\/schema\/person\/b1134cd8726bb5387a31d8e4eeae0800\",\"name\":\"Florian Jann\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"de\",\"@id\":\"https:\/\/www.inovex.de\/de\/#\/schema\/person\/image\/5594bf9adb53abec2fa311e22a301fd3\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/c83a6769664d0166a1d7d0b2faf20921eedf8a8446191cdc530b92a2f6298cb8?s=96&d=retro&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/c83a6769664d0166a1d7d0b2faf20921eedf8a8446191cdc530b92a2f6298cb8?s=96&d=retro&r=g\",\"caption\":\"Florian Jann\"},\"description\":\"Ehemaliger Praktikant, Bachelorand, Werkstudent und Masterand und nun endlich Softwareentwickler bei inovex\",\"url\":\"https:\/\/www.inovex.de\/de\/blog\/author\/fjann\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Augmented Reality to-go mit ARCore und Poly f\u00fcr Android - inovex GmbH","description":"Im Rahmen meines Praxissemesters habe ich mit ARCore eine Android-Anwendung entwickelt, mit der 3D-Modelle im Raum platziert und dargestellt werden k\u00f6nnen. Hier stelle ich den Entwicklungsprozess vor.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/","og_locale":"de_DE","og_type":"article","og_title":"Augmented Reality to-go mit ARCore und Poly f\u00fcr Android - inovex GmbH","og_description":"Im Rahmen meines Praxissemesters habe ich mit ARCore eine Android-Anwendung entwickelt, mit der 3D-Modelle im Raum platziert und dargestellt werden k\u00f6nnen. Hier stelle ich den Entwicklungsprozess vor.","og_url":"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/","og_site_name":"inovex GmbH","article_publisher":"https:\/\/www.facebook.com\/inovexde","article_published_time":"2019-07-01T06:00:17+00:00","article_modified_time":"2022-11-21T14:32:36+00:00","og_image":[{"width":1920,"height":1080,"url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/augmented-reality-arcore.png","type":"image\/png"}],"author":"Florian Jann","twitter_card":"summary_large_image","twitter_image":"https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/augmented-reality-arcore-1024x576.png","twitter_creator":"@inovexgmbh","twitter_site":"@inovexgmbh","twitter_misc":{"Verfasst von":"Florian Jann","Gesch\u00e4tzte Lesezeit":"13\u00a0Minuten","Written by":"Florian Jann"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#article","isPartOf":{"@id":"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/"},"author":{"name":"Florian Jann","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/b1134cd8726bb5387a31d8e4eeae0800"},"headline":"Augmented Reality to-go mit ARCore und Poly f\u00fcr Android","datePublished":"2019-07-01T06:00:17+00:00","dateModified":"2022-11-21T14:32:36+00:00","mainEntityOfPage":{"@id":"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/"},"wordCount":2018,"commentCount":0,"publisher":{"@id":"https:\/\/www.inovex.de\/de\/#organization"},"image":{"@id":"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#primaryimage"},"thumbnailUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/augmented-reality-arcore.png","keywords":["IoT"],"articleSection":["Applications","General"],"inLanguage":"de","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/","url":"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/","name":"Augmented Reality to-go mit ARCore und Poly f\u00fcr Android - inovex GmbH","isPartOf":{"@id":"https:\/\/www.inovex.de\/de\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#primaryimage"},"image":{"@id":"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#primaryimage"},"thumbnailUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/augmented-reality-arcore.png","datePublished":"2019-07-01T06:00:17+00:00","dateModified":"2022-11-21T14:32:36+00:00","description":"Im Rahmen meines Praxissemesters habe ich mit ARCore eine Android-Anwendung entwickelt, mit der 3D-Modelle im Raum platziert und dargestellt werden k\u00f6nnen. Hier stelle ich den Entwicklungsprozess vor.","breadcrumb":{"@id":"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#breadcrumb"},"inLanguage":"de","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/"]}]},{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#primaryimage","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/augmented-reality-arcore.png","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2019\/06\/augmented-reality-arcore.png","width":1920,"height":1080,"caption":"Ein Smartphone projiziert eine ARcore Blume in einen Blumentopf"},{"@type":"BreadcrumbList","@id":"https:\/\/www.inovex.de\/de\/blog\/android-ar-arcore-poly\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.inovex.de\/de\/"},{"@type":"ListItem","position":2,"name":"Augmented Reality to-go mit ARCore und Poly f\u00fcr Android"}]},{"@type":"WebSite","@id":"https:\/\/www.inovex.de\/de\/#website","url":"https:\/\/www.inovex.de\/de\/","name":"inovex GmbH","description":"","publisher":{"@id":"https:\/\/www.inovex.de\/de\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.inovex.de\/de\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"de"},{"@type":"Organization","@id":"https:\/\/www.inovex.de\/de\/#organization","name":"inovex GmbH","url":"https:\/\/www.inovex.de\/de\/","logo":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/","url":"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png","contentUrl":"https:\/\/www.inovex.de\/wp-content\/uploads\/2021\/03\/inovex-logo-16-9-1.png","width":1921,"height":1081,"caption":"inovex GmbH"},"image":{"@id":"https:\/\/www.inovex.de\/de\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/inovexde","https:\/\/x.com\/inovexgmbh","https:\/\/www.instagram.com\/inovexlife\/","https:\/\/www.linkedin.com\/company\/inovex","https:\/\/www.youtube.com\/channel\/UC7r66GT14hROB_RQsQBAQUQ"]},{"@type":"Person","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/b1134cd8726bb5387a31d8e4eeae0800","name":"Florian Jann","image":{"@type":"ImageObject","inLanguage":"de","@id":"https:\/\/www.inovex.de\/de\/#\/schema\/person\/image\/5594bf9adb53abec2fa311e22a301fd3","url":"https:\/\/secure.gravatar.com\/avatar\/c83a6769664d0166a1d7d0b2faf20921eedf8a8446191cdc530b92a2f6298cb8?s=96&d=retro&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c83a6769664d0166a1d7d0b2faf20921eedf8a8446191cdc530b92a2f6298cb8?s=96&d=retro&r=g","caption":"Florian Jann"},"description":"Ehemaliger Praktikant, Bachelorand, Werkstudent und Masterand und nun endlich Softwareentwickler bei inovex","url":"https:\/\/www.inovex.de\/de\/blog\/author\/fjann\/"}]}},"_links":{"self":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/16370","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/users\/115"}],"replies":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/comments?post=16370"}],"version-history":[{"count":3,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/16370\/revisions"}],"predecessor-version":[{"id":38434,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/posts\/16370\/revisions\/38434"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/media\/16490"}],"wp:attachment":[{"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/media?parent=16370"}],"wp:term":[{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/tags?post=16370"},{"taxonomy":"service","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/service?post=16370"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.inovex.de\/de\/wp-json\/wp\/v2\/coauthors?post=16370"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}