Moderne App-Entwicklung am Beispiel waipu.tv

Ähnliche Dokumente
Oliver Paulus, 7. Februar Spring Framework Einführung. Oliver Paulus, Was ist Spring?

Frontend Migration from JSP to Eclipse Scout

Überleben im Funkloch

FORTGESCHRITTENE ANDROID ENTWICKLUNG Max Wielsch

Christian Meder inovex. Sauberes Grün QS für Android

Skalierbare Enterprise Architekturen für Universal Windows Platform Apps

Projektgruppe. Thomas Kühne. Komponentenbasiertes Software Engineering mit OSGi

Interface. So werden Interfaces gemacht

Application Frameworks

Web-Anwendungsentwicklung mit dem Delivery Server

VON MVC ZU MODEL-VIEW-VIEWMODEL

! 1. Unterklassen und Vererbung! 2. Abstrakte Klassen und Interfaces! 3. Modularität und Pakete. II.4.2 Abstrakte Klassen und Interfaces - 1 -

Moderne Web- Anwendungen mit

Eclipse Equinox als Basis für Smart Client Anwendungen. Christian Campo, compeople AG, Java Forum Stuttgart 2007

Web-Anwendungen mit Arquillian testen

Einstieg in die Informatik mit Java

Thomas Schissler MVP Visual Studio ALM, artiso AG

Testen von graphischen Benutzeroberflächen. 26. Juni 2013

Bluewin TV meets Android

Algorithmen und Datenstrukturen Musterlösung 5

Richard Bubel & Martin Hentschel

Struts 2 Das Imperium schlägt zurück?

Naviki GPS-Anwendungsentwicklung für Mobiltelefone

Java-Schulung Grundlagen

Introduction to Python. Introduction. First Steps in Python. pseudo random numbers. May 2016

The app the crashes, before the breakpoint is reached: Code to the event:

WebApps in spezieller Umgebung

Dennis Schulte / Tobias Flohre codecentric AG. Enterprise Java Batch mit Spring

Einführung in Google Web Toolkit

Integration von Web Services in J EE Anwendungen mit XFire. 1/26 André Janus - Integration von Web Services in J EE Anwendungen mit XFire

Die S.O.L.I.D-Prinzipien für C# Entwickler Thomas Claudius

Wie ich lernte die API zu lieben. 19. März sic[!]sec GmbH Industriestraße Gröbenzell

Java Batch Der Standard für's Stapeln

Objektorientierte Programmierung

Android Apps. Mentoring SS 16. Nicolas Lehmann, Sönke Schmidt, Alexander Korzec, Diane Hanke, Toni Draßdo

Webentwicklung mit Vaadin 7. Theoretische und praktische Einführung in Vaadin 7. Christian Dresen, Michael Gerdes, Sergej Schumilo

MVVM in Windows 8 und Windows Phone 8

Android GUI Entwicklung

Javakurs FSS Lehrstuhl Stuckenschmidt. Tag 3 - Objektorientierung

Entwurfsmuster. Die Entwurfsmuster Observer, State und Singleton am Beispiel einer Digital-Uhr

Hivemind Ein leichtgewichteter Container

BPMN 2.0 gehört in den Werkzeugkasten JEDES Java Entwicklers!

Übungen zur Android Entwicklung

12 Abstrakte Klassen, finale Klassen und Interfaces

Java Tools JDK. IDEs. Downloads. Eclipse. IntelliJ. NetBeans. Java SE 8 Java SE 8 Documentation

Fortgeschrittenes Programmieren mit Java. Test Driven Development

Annotation based presentation models for view rendering and data binding with Linkki and Vaadin

Konsequent agile Entwicklung mit funk4onaler Programmierung. Michael Sperber

JUnit. Software-Tests

Multimedia im Netz Wintersemester 2012/13

Inhalt. Design patterns Kernbereiche Creational patterns Factory method Abstract Factory Builder Structural patterns Adapter Facade Decorator

Programmiermethodik 3. Klausur Lösung

Benutzerauthentifizierung und Zugriffsschutz mit JAAS

SEMINARVORTRAG ANDROID ENTWICKLUNG ETIENNE KÖRNER EMBEDDED SYSTEMS SS HSRM

RAP vs. GWT vs. GAE/J + jquery. Web Technologien im Verlgeich

Schritt 5: Session Beans

Erste Erfahrungen mit NSASJ anhand der OmnivoBase Portierung. September 2013

Dezentrale Kontrolle: Aktive Objekte. Aktive Objekte Die Klasse AnimatorThread Aktivierung Objekte beobachten Die Java-Klasse Thread

Andreas Mösching Senior IT Architekt Hewlett-Packard (Schweiz) GmbH HP Banking Service Center Bern

Allgemeine Hinweise:

Javadoc. Programmiermethodik. Eva Zangerle Universität Innsbruck

Prozessautomatisierung mit BPMN 2.0 und Java.

Echte Cross-Plattform Anwendungen mit Angular 2 in Action!

Gebundene Typparameter

Dynamische Plug-ins mit Eclipse 3. Martin Lippert Tammo Freese

Neue Wege mit Contao 4

39 Object Request Brokers. 40 Components of an ORB Stubs and Skeletons Stub

UML / Fujaba. Generierung von Java-Quellcode aus UML-Diagrammen. Marcel Friedrich

JOGGA Der Jogging-Companion

Algorithmen und Datenstrukturen

II.4.5 Generische Datentypen - 1 -

Moderne Web-Anwendungen mit Vaadin

Cross-Platform Mobile mit.net

Model-View-ViewModel (MVVM)

versus Christian Grobmeier

Android Processes & Services

Karlsruhe Institute of Technology Die Kooperation von Forschungszentrum Karlsruhe GmbH und Universität Karlsruhe (TH)

Abgabe: keine Pflichtabgabe (vor 12 Uhr) Aufgabe 10.1 (P) Vererbung Gegeben seien folgende Java-Klassen:

Instrumentierung und Dekodierung

Session 1: Classes and Applets

TDD. mit JUnit & Mockito. Tobias Trelle, codecentric

Java Concurrency Utilities

Entwicklungsumgebungen. Packer, Vagrant, Puppet. Alexander Pacnik Mannheim,

Institut für Informatik. Endterm Klausur zu Informatik I 20. Februar 2010

Einführung in C# Teil 3. Matthias Nübling

OSGI DECLARATIVE SERVICES

Objektorientierung II & die Java Klassenbibliothek. Kristian Bergmann und Arthur Lochstampfer

JavaBeans Property-Editoren und Customizer

07. November, Zürich-Oerlikon

14 Abstrakte Klassen, finale Klassen, Interfaces

JUnit a Cook s Tour. Framework in Java Automatisierter Ablauf von Testfällen Testläufe kombinieren. Unterlagen als PDF auf der Übungsseite!

Technische Hochschule Georg Agricola WORKSHOP TEIL 3. IKT (Informations- und Kommunikationstechnik) an einer MorseApp erklärt

Bean-Mapping mit MapStruct

Wo sind wir? Übersicht lexikale Struktur von Java

Vorausgesetzte Grundkenntnisse. Inhalt. Klassenhierarchie und Vererbung. Vererbung. Klassenhierarchie und Vererbung. Einführung in C# Teil 3

Oracle Data Integrator Ein Überblick

14 Abstrakte Klassen, finale Klassen, Interfaces. Auswertung von Ausdrücken. Beispiel. Abstrakte Methoden und Klassen

Teil I Augmented Learning - Vortragender: Krischan Udelhoven. Teil II Android - Vortragender: Folker Hoffmann

System.out.println("TEXT");

Lambda Expressions in Java 8

Transkript:

Moderne App-Entwicklung am Beispiel waipu.tv Andreas Bauer 10.11.2016 Johannes Schamburger

Informationen zur inovex GmbH - IT-Dienstleister in Pforzheim, Karlsruhe, Köln, München und Hamburg - Application Development, Datamanagement & Analytics, Consulting und IT Engineering & Operations - ca. 250 Mitarbeiter 2

Informationen zu waipu.tv - Projekt der Firma EXARING AG - Freenet ist Investor - Vermarktung u.a. in Mobilcom Debitel Läden - Entwicklung gestartet im letzten Herbst - Android Entwicklung seit Anfang des Jahres mit einer Teamgröße von 3-5 Entwicklern - Launch von waipu.tv zum 1.10.2016 3

Was ist waipu.tv? - TV Live-Streams - Aufnehmen von TV-Streams - Zeitversetzte TV-Streams - Wiedergabe in der App und auf dem TV (Chromecast, Amazon Fire TV) - App als (Next Generation) Fernbedienung 4

Streaming 5

Weitere Funktionen 6

Motivation Typische Probleme in der Android App Architektur - Gott-Klassen - Testbarkeit - Wartbarkeit - Abhängigkeit vom Framework / Lifecycle 7

Überlegungen - Welches Architekturmodell? - Welche Libraries? - Dependency Injection? - Reactive Programming? 8

Clean Architecture (Uncle Bob) http://fernandocejas.com/2014/09/03/architecting-android-the-clean-way/ 9

Eigenschaften Die Architektur ist - unabhängig von der UI - unabhängig von der Datenbank - unabhängig von Frameworks - testbar 10

Architektur Beispiel EPG Daten 11

Architektur Beispiel EPG Daten 12

MVP - Model View Presenter 13

MVP Beispiel Kanalwechsel 14

MVP Beispiel Kanalwechsel 15

Presenter Beispiel public interface StreamingPresenter<T> extends BasePresenter<T> { void onstop(); void ondestroy(); void oncastdevicedisconnected(); void oncaststarted(); void oncaststopped(); void onmutetoggled(boolean muted); void onjumptostart(); 16

View Beispiel public interface StreamingView<T> extends BaseView<T> { void setpreviewimage(string previewimagehref); void showerrormessageforstream(); void hideerrormessageforstream(); void setchannel(channel channel); void updatecastoverlaymessage(string castdevicename); void showfullscreenloadingindicator(); void hidefullscreenloadingindicator(); 17

Pros und Cons von MVP + Separation of Concerns + Kleinere, übersichtlichere Klassen + Testbarkeit - Klassen Overhead - Mehraufwand in der Entwicklung - saubere Umsetzung erzeugt teilweise lange Callstrecken 18

Beispiel Presenter Unit-Test @Test public void select_channel_should_start_stream() throws Exception { String streamurl = "streamurl"; doreturn(observable.just(streamurl)).when(streamusecase).getstreamurl(anystring(), anystring(), anystring(), anystring(), anystring(), anylong()); presenter.onlocalchannelselected("ard"); verify(livetvview).hideerrormessageforstream(); verify(livetvview).setupvideoplayer(any(videoplayer.class), any(eventlogger.class)); verify(livetvview).setstream(streamurl, VideoPlayerView.StreamType.TYPE_DASH); verify(livetvview).startdeviceplayback(); verify(livetvview).updatecastviewstate(); verifynomoreinteractions(livetvview); 19

Beispiel lange Callstrecke Szenario: Sender wird gewechselt, Sendungsdetails werden aktualisiert. Container Fragment -> LiveTvFragment -> LiveTvPresenter -> LiveTvFragment -> TvDetailsView -> TvDetailsPresenter -> TvDetailsView 20

Reactive Programming In reactive programming the consumer reacts to the data as it comes in. This is the reason why asynchronous programming is also called reactive programming. Reactive programming allows to propagates event changes to registered observers. - Lars Vogel 21

RxJava - Java VM Implementierung der ReactiveExtensions - Portiert von.net zu JVM von Netflix 2014 - leichtgewichtig - Open Source - Seit 2014 im ReactiveX Repository auf GitHub 22

Einfaches Beispiel Observable Observable<String> simpleobservable = Observable.create( new Observable.OnSubscribe<String>() { @Override public void call(subscriber<? super String> subscriber) { subscriber.onnext("simple Value"); subscriber.oncompleted(); ); 23

Einfaches Beispiel Subscriber Subscriber<String> simplesubscriber = new Subscriber<String>() { @Override public void onnext(string value) { println(value); @Override public void oncompleted() { @Override public void onerror(throwable e) { ; simpleobservable.subscribe(simplesubscriber); 24

Operatoren manipulieren emittierte Items Observable<String> simpleobservable = Observable.just("Simple Value").map(new Func1<String, String>() { @Override public String call(string value) { return value + " now modified"; ); simpleobservable.subscribe (new Subscriber<String>() { @Override public void onnext(string value) { println(value); // prints Simple Value now modified" 25

Rx bei waipu.tv public Observable<List<Channel>> getchannels() { Observable<List<Channel>> apicall = authorization..getauthorizationstringasobservable().flatmap(new Func1<String, Observable<? extends List<Channel>>>() { @Override public Observable<? extends List<Channel>> call(string auth) { return businesssystemsapi.getchanneldata(auth); ); - Authentifizierung - BS - Aufruf return authorization.loginwhenrequired(apicall).doonnext(new Action1<List<Channel>>() { @Override public void call(list<channel> channels) { dbhelper.insertchannellist(channels); ).subscribeon(schedulers.io()).observeon(androidschedulers.mainthread()); - Zusätzlicher Login - Retry - Datenbankoperation - Thread Handling 26

Rx bei waipu.tv remotedatasubject.observeon(androidschedulers.mainthread()).map(new Func1<Void, Boolean>() { @Override public Boolean call(void avoid) { // get Current Remote Program Information // if program is still valid return false // else return true ).distinctuntilchanged().observeon(schedulers.io()).flatmap(new Func1<Boolean, Observable<List<EPGData>>>() { @Override public Observable<List<EPGData>> call(boolean value) { // Return Observable which emits Program Data for a timespan ) 27

Rx bei waipu.tv.flatmap(new Func1<List<EPGData>, Observable<ProgramInformation>>() { @Override public Observable<ProgramInformation> call(list<epgdata> epg) { // Get Current Timestamp // return ProgramOverview for channel ).retry(new Func2<Integer, Throwable, Boolean>() { @Override public Boolean call(integer retrycount, Throwable t) { return retrycount < 3; ).subscribe(new DefaultSubscriber<ProgramInformation>("NotificationModelUpdater") { @Override public void onnext(programinformation programinformation) { // Update Program Information ); 28

Problematiken private Subscription statussubscription; private void listentostatuschanges() { statussubscription = someobject.listentostatuschanges().subscribe(new Subscriber<StatusObject>() {... @Override public void onnext(statusobject o) { //do Stuff ); private void unsubscribetostatuschanges() { if(statussubscription!= null &&!statussubscription.isunsubscribed()) { statussubscription.unsubscribe(); 29

Dependency Injection - Klassen verwalten ihre Abhängigkeiten nicht selbst - Single Responsibility - komfortable Möglichkeit, Singletons zu verwenden - einfaches Austauschen von konkreten Implementierungen (z.b. für Tests) 30

Dependency Injection - Dagger Inject @Inject StreamUseCase streamusecase; 31

Dependency Injection - Dagger Module, Provides, Singleton @Module public class UseCaseModule { @Provides @Singleton public StreamUseCase providestreamusecase(businesssystemsapi businesssystemsapi, AuthUseCase authusecase, EPGUseCase epgusecase) { return new StreamUseCase(businessSystemsApi, authusecase, epgusecase); 32

Dependency Injection - Dagger Component @Component(modules = {AppModule.class, CastModule.class, UseCaseModule.class) public interface AppComponent { void inject(waipuapplication application); StreamUseCase streamusecase(); 33

Dependency Injection - Dagger Component @Component(modules = {AppModule.class, CastModule.class, UseCaseModule.class) public interface AppComponent { void inject(waipuapplication application); StreamUseCase streamusecase(); @Component(dependencies = AppComponent.class, modules = {LiveTvModule.class) public interface LiveTvComponent { void inject(livetvfragment fragment); void inject(livetvpresenterimpl livetvpresenter); 34

Dependency Injection - Dagger Injection public class LiveTvFragment implements LiveTvView { @Override public void oncreate(bundle savedinstancestate) { appcomponent = WaipuApplication.get(getActivity()).getAppComponent(); livetvcomponent = DaggerLiveTvComponent.builder().appComponent(appComponent).liveTvModule(new LiveTvModule(this)).build(); livetvcomponent.inject(this); 35

Pros and Cons + Instanziierung und Konfiguration gut nachvollziehbar + Singletons + Testing - Klassen-Overhead - Boilerplate Code 36

Singletons @Inject protected AudioStateManager audiostatemanager; CastManager VideoPlayerControl AudioStateManager... VideoPlayer StreamingPresenter 37

Klassen-Overhead & Boilerplate Code 38

Klassen-Overhead & Boilerplate Code LiveTvComponent: @FragmentScope @Component(dependencies = AppComponent.class, modules = {LiveTvModule.class) public interface LiveTvComponent { void inject(livetvfragment fragment); void inject(livetvpresenterimpl livetvpresenter); 39

Klassen-Overhead & Boilerplate Code LiveTvComponent: @FragmentScope @Component(dependencies = AppComponent.class, modules = {LiveTvModule.class) public interface LiveTvComponent { void inject(livetvfragment fragment); void inject(livetvpresenterimpl livetvpresenter); LiveTvFragment: @Override public void setupcomponent(appcomponent appcomponent) { livetvcomponent = DaggerLiveTvComponent.builder().appComponent(appComponent).liveTvModule(new LiveTvModule(this)).build(); livetvcomponent.inject(this); 40

Fazit und Erkenntnisse - Mehraufwand zahlt sich langfristig aus - Herausforderung: konsequente Umsetzung - automatisiertes Testen bei Android nach wie vor umständlich - RxJava - easy to learn, hard to master - Gefahr von sehr großen Klassen ist nicht gebannt 41

Vielen Dank Unser Dank gilt besonders der EXARING AG, die uns diesen Vortrag ermöglicht hat.