{"id":1530,"date":"2013-02-21T09:24:09","date_gmt":"2013-02-21T08:24:09","guid":{"rendered":"http:\/\/www.tupperclub.de\/blog\/?p=1530"},"modified":"2020-01-06T23:58:00","modified_gmt":"2020-01-06T22:58:00","slug":"android-entwicklung-der-google-playstore-lvl-lizenzierung","status":"publish","type":"post","link":"https:\/\/www.tupperclub.de\/blog\/?p=1530","title":{"rendered":"Android Entwicklung \u2013 Der Google Playstore &#038; LVL-Lizenzierung"},"content":{"rendered":"<p>Im Gegensatz zu iOS muss man sich um den Schutz der App vor unerw\u00fcnschten Kopien komplett selbst k\u00fcmmern. Bei iOS besteht der Schutz vor allem darin, dass man Apps nur aus dem iTunes Store installieren kann. Dieser Mechanismus ist nicht perfekt und kann mit dem Jailbreak des Ger\u00e4tes ausgehebelt werden &#8211; aber er ist einfach. Auf Android wird es f\u00fcr Entwickler wesentlich komplizierter, einen grundlegenden Schutz zu realisieren.<\/p>\n<p>Dort k\u00f6nnen auf jedem Telefon ohne Aufwand beliebige APK-Files installiert werden. Das erweitert den m\u00f6glichen Kreis der &#8222;App-Cracker&#8220; sogar auf Leute, die nicht mal merken, dass eine App kostenpflichtig w\u00e4re, wenn Sie von jemanden per Mail geschickt wurde.<\/p>\n<p>Wenn man kostenpflichtige Apps auf Android verkaufen will,<!--more--> sollte man also f\u00fcr eine Lizenz\u00fcberpr\u00fcfung oder einen vergleichbaren Mechanismus ausw\u00e4hlen und diesen umsetzen. Wir haben entschieden, die App \u00fcber den Google Playstore zu verteilen und die dort verf\u00fcgbare <a href=\"https:\/\/developer.android.com\/google\/play\/licensing\/adding-licensing.html\">LVL-Schnittstelle<\/a> zu verwenden. Damit pr\u00fcft man, ob der Benutzer eine lizensierte Kopie der Anwendung verwendet. Damit dies etwas bringt muss man die Anwendung zus\u00e4tzlich mit einem Obfuscator sch\u00fctzen, damit diese Lizenzpr\u00fcfung nicht einfach wieder ausgebaut werden kann.<\/p>\n<p>W\u00e4hrend der Entwicklung kann man den Lizenzserver von Google anweisen bestimmte Antworten (lizensiert, nicht lizensiert, usw.) zur\u00fcck zu liefern. Leider kann man die G\u00fcltigkeit dieser Antworten nicht konfigurieren und auch nicht einsehen, warum welche Anfragen mit welcher Antwort beantwortet wurden. Verwendet man beispielsweise auf dem Ger\u00e4t eine andere Version als in der im Play-Store hochgeladenen Version, liefert der Play Store immer zur\u00fcck, dass die Anwendung lizensiert ist. Greift man dann beim Debuggen zu oft auf den Play Store zu, um diesen Problemen auf den Grund zugehen, kann es schon mal passieren dass der Lizenzserver den entsprechenden Account sperrt (f\u00fcr einen durch Google nicht n\u00e4her spezifizierten Zeitraum von 2h bis 3 Wochen), ohne dass man dar\u00fcber informiert wird.<br \/>\nAu\u00dferdem scheint die Play Store Anwendung ab und an nicht richtig zu funktionieren (Workaround: Ger\u00e4t neu starten oder <a href=\"https:\/\/stackoverflow.com\/questions\/9892922\/google-license-validation-suddenly-failing-on-development-device?rq=1\">Lizensierungsdaten<\/a> <a href=\"https:\/\/stackoverflow.com\/questions\/10751910\/lvl-testing-not-working-clear-cache?rq=1\">zur\u00fccksetzen<\/a>). Dies f\u00fchrt zu extrem undurchsichtigem Verhalten des Lizenzservers, das zu vielen Stunden frustrierendem Debugging f\u00fchrt. Am ersten Tag waren wir nach 18h Arbeit im wesentlichen genauso weit wie am Morgen. Mehr Infos dazu gibt es \u00fcbrigens auch <a href=\"https:\/\/ttlnews.blogspot.de\/2010\/11\/my-experience-with-android-market.html\">hier<\/a>.<\/p>\n<p>Ein weiteres Detail war f\u00fcr uns zwar kein Problem, f\u00fcr gr\u00f6\u00dfere Teams mag das aber dennoch unangenehm sein: die Lizenzantwort kann man nur global f\u00fcr **alle** Anwendungen eines Accounts einstellen.<\/p>\n<p>Der Playstore ist nicht nur beim Entwickeln etwas unberechenbar, sondern auch sp\u00e4ter f\u00fcr die K\u00e4ufer. Wir hatten einige Supportanfragen dazu &#8211; auf manchen Handys beendeten sich neu gekaufte Anwendungen wegen einer fehlenden Lizenz. Diesen Fehler scheint ein Neustart des Ger\u00e4ts zu beheben, was das Vertrauen in den Store nicht gerade st\u00e4rkt. Etwas Vergleichbares ist in vier Jahren iOS \u00fcbrigens nie passiert.<\/p>\n<p>Aber auch die zweite Herausforderung, die Anwendung gegen dekompilieren zu sch\u00fctzen, ist verh\u00e4ltnism\u00e4\u00dfig aufwendig. Google setzt hier auf das OpenSource Tool <a href=\"https:\/\/proguard.sourceforge.net\/\">Proguard<\/a>, zu dem es im Internet immerhin eine Menge Dokumentation gibt. Leider braucht man die auch, da die initiale Konfiguration extrem kompliziert ist. Viele Fehler treten erst zur Laufzeit in Kombination mit den verschiedenen Android Versionen, Action Bar Sherlock und <a href=\"https:\/\/code.google.com\/p\/roboguice\/wiki\/ProGuard\">Roboguice<\/a> auf. Tipp am Rande: Maven kann \u00fcbrigens unter OS X keine Release Versionen mit Proguard bauen. Man muss hier <a href=\"https:\/\/groups.google.com\/forum\/#!msg\/maven-android-developers\/OB4428e4LxI\/qzbiG-QZGJkJ\">manuell nachhelfen<\/a>.<\/p>\n<p>Zur\u00fcck zu <a href=\"https:\/\/www.tupperclub.de\/blog\/?p=1528\">Teil 1: Das Tooling<\/a><br \/>\nWeiter zu <a href=\"https:\/\/www.tupperclub.de\/blog\/?p=1534\">Teil 3: Finanzielles und Fazit<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Im Gegensatz zu iOS muss man sich um den Schutz der App vor unerw\u00fcnschten Kopien komplett selbst k\u00fcmmern. Bei iOS besteht der Schutz vor allem darin, dass man Apps nur aus dem iTunes Store installieren kann. Dieser Mechanismus ist nicht perfekt und kann mit dem Jailbreak des Ger\u00e4tes ausgehebelt werden &#8211; aber er ist einfach. [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17],"tags":[],"class_list":["post-1530","post","type-post","status-publish","format-standard","hentry","category-java"],"_links":{"self":[{"href":"https:\/\/www.tupperclub.de\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1530","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tupperclub.de\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tupperclub.de\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tupperclub.de\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tupperclub.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1530"}],"version-history":[{"count":9,"href":"https:\/\/www.tupperclub.de\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1530\/revisions"}],"predecessor-version":[{"id":3253,"href":"https:\/\/www.tupperclub.de\/blog\/index.php?rest_route=\/wp\/v2\/posts\/1530\/revisions\/3253"}],"wp:attachment":[{"href":"https:\/\/www.tupperclub.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1530"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tupperclub.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1530"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tupperclub.de\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1530"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}