PDF Slides, 4.2MB - Wolf Paulus

1,097 views

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
1,097
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
16
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

PDF Slides, 4.2MB - Wolf Paulus

  1. 1. Writing a Web Service Client App for Android © 2010 http://wolfpaulus.com
  2. 2. Server Side (e.g. Tomcat) Hessian, Binary Protocol Http-Session Support Client hessdroid remote calls / async Agenda
  3. 3. Quick Tips Use Android’s R.class Auto-Launch an Intent at boot time Client Things that can will go wrong Agenda
  4. 4. Switch Activity Remote call reload Switch users Activity Four item main menu Remote Call to getNext
  5. 5. Exposing a Service Class: Hessian Binary Web Service Protocol Copyright © 2010 http://wolfpaulus.com
  6. 6. Copyright © 2010 http://wolfpaulus.com
  7. 7. Java Hessian Copyright © 2010 http://wolfpaulus.com
  8. 8. Hessian Java Copyright © 2010 http://wolfpaulus.com
  9. 9. package com.carlsbadcubes.api; import java.util.Collection; public interface CommService { Collection<Message> getMessages(); Collection<User> getUsers(); } Copyright © 2010 http://wolfpaulus.com
  10. 10. <?xml version="1.0" encoding="UTF-8"?> <web-app> <servlet> defined in hessian.jar <servlet-name>myservice</servlet-name> <servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class> <init-param> Implementation <param-name>service-class</param-name> <param-value>com.carlsbadcubes.impl.CommServiceImpl</param-value> </init-param> <init-param> Interface <param-name>api-class</param-name> <param-value>com.carlsbadcubes.api.CommService</param-value> </init-param> </servlet> <servlet-mapping> <servlet-name>myservice</servlet-name> <url-pattern>/service/*</url-pattern> </servlet-mapping> </web-app> Copyright © 2010 http://wolfpaulus.com
  11. 11. Roles <security-role> <role-name>HessianService</role-name> </security-role> Realm <login-config> <auth-method>BASIC</auth-method> <realm-name>default</realm-name> </login-config> Access Privileges <security-constraint> <web-resource-collection> <web-resource-name>SecureConnection</web-resource-name> <url-pattern>/service/*</url-pattern> <url-pattern>/comm/*</url-pattern> ... Components <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> Groups or Principals <role-name>HessianService</role-name> </auth-constraint> <user-data-constraint> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint> </security-constraint> Communication Copyright © 2010 http://wolfpaulus.com
  12. 12. (1) Thread Thread Servlet http requests : (1) : m_var created in servlet.init() (n) (1) Thread ServiceClass impl. ServiceAPI Copyright © 2010 http://wolfpaulus.com
  13. 13. JSESSIONID = 123 Thread 357 request. 789 JSESSIONID = 789 getSession() Thread 123 Servlet Session http response : Map : m_var JSESSIONID = 357 Thread ServiceClass impl. ServiceAPI Copyright © 2010 http://wolfpaulus.com
  14. 14. JSESSIONID = 123 123 Thread ThreadLocal 357 789 JSESSIONID = 789 789 Thread 123 ThreadLocal Servlet Session http request : Map http response : m_var JSESSIONID = 357 357 Thread ServiceClass ThreadLocal impl. ServiceAPI Copyright © 2010 http://wolfpaulus.com
  15. 15. The ThreadLocal Class: public class ThreadLocal<T> {   public void set( T newValue ); public T get(); public void remove();   protected T initialValue(); } Copyright © 2010 http://wolfpaulus.com
  16. 16. ... not in hessian.jar HessianHttpServlet extends HessianServlet implements HessianHttpService { ... } Copyright © 2010 http://wolfpaulus.com
  17. 17. .. all of HessianServlet HessianHttpServlet extends HessianServlet implements HessianHttpService puts HttpSession Discovery Service for Map into ThreadLocal Android Clients memory Map<String, String> getServices() Copyright © 2010 http://wolfpaulus.com
  18. 18. @Override HessianHttpServlet init() .. // // introspect service implementation to find out if we have to put the servlet into a session // if ( getInitParameter("service-class") != null ) { String className = getInitParameter("service-class"); if (className != null) { this.requiresSessionSupport = StateKeeper.class.isAssignableFrom(loadClass(className)); } if (this.requiresSessionSupport) { System.out.println(className + " has been registered for session support."); } } @Override service() .. if (this.requiresSessionSupport) { HttpServletRequest req = (HttpServletRequest) request; ThreadLocalAttrMap.set( req.getSession( true ) ); } Copyright © 2010 http://wolfpaulus.com
  19. 19. = Client Copyright © 2010 http://wolfpaulus.com
  20. 20. hessdroid http://code.google.com/p/hessdroid/ String url = “http://hostname.domain:port/service”; ServiceProxyFactory factory = new HessianProxyFactory(); factory.set ..(..); factory.set ..(..). CommService cs = factory.create( CommService.class, url , getClassLoader()); Copyright © 2010 http://wolfpaulus.com
  21. 21. hessdroid http://code.google.com/p/hessdroid/ HessDroid Generified ... HessianProxyFactory: public <T>T create( Class<T> api, String urlName, ClassLoader loader); Clientside code without casting: Service s = (Service) factory.create( Service.class, url, cl ); Copyright © 2010 http://wolfpaulus.com
  22. 22. hessdroid http://code.google.com/p/hessdroid/ Creates a Cookie Map, Maintains HttpSessions HessianHttpProxyFactory extends HessianProxyFactory { ... } Copyright © 2010 http://wolfpaulus.com
  23. 23. ... not in hessdroid.jar HessianFactory.initialize( ) Service Discovery: maps Interfaces to URLs Copyright © 2010 http://wolfpaulus.com
  24. 24. Hessian Client CommService cs = HessianFactory.create( CommService.class, getClassLoader() ) Copyright © 2010 http://wolfpaulus.com
  25. 25. Demo Tomcat Server with a Hessian Service and a Hessian based Android Client Copyright © 2010 http://wolfpaulus.com
  26. 26. Async .... Don’t run HessionFactory.create(..) in the main thread Don’t run remote method calls in the main thread either. Copyright © 2010 http://wolfpaulus.com
  27. 27. Interface Garage { void openDoor(); Car getCar(); } Interface Car { void openDoor(); Color getColor(); } Copyright © 2010 http://wolfpaulus.com
  28. 28. Garage garage = HessianFactory.create( Garage.class, getClassLoader() ); // The interface Garage and the class CarImpl // need to be available on the client to make this work: garage.openDoor(); // remote call garage.getCar().openDoor(); // local call Copyright © 2010 http://wolfpaulus.com
  29. 29. Use Android’s R. XML: <TextView android:textColor = "@color/ink" android:background= "@android:color/darker_gray" /> Code: int c0 = getResources().getColor( R.color.ink ); int c1 = getResources().getColor( android.R.color.darker_gray ); Copyright © 2010 http://wolfpaulus.com
  30. 30. Use Intent flags to control the flow. XML: (Activity) <activity .. android:taskAffinity=” ” launchMode, allowTaskReparenting, clearTaskOnLaunch, alwaysRetainTaskState, finishOnTaskLaunch ..> Code: (Intent) myIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) Copyright © 2010 http://wolfpaulus.com
  31. 31. Auto-Launch after boot (1 of 2) AndroidManifest: .. <receiver android:name=".BootNotificationReceiver"> <intent-filter> <action android:name= "android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> <service android:name=".HessianService"/> </application> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED "/> Copyright © 2010 http://wolfpaulus.com
  32. 32. Auto-Launch after boot (2 of 2) Code: public class BootNotificationReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if (Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { context.startService( new Intent(context, HessianService.class)); } } } Copyright © 2010 http://wolfpaulus.com
  33. 33. Things that can will go wrong wrong classloader: java.lang.IllegalArgumentException: com.pss.api.Service is not visible from class loader Use AppContext.getClassLoader() app doesn’t have Internet permission: com.caucho.hessian.client.HessianRuntimeException: java.net.SocketException: Permission denied AndroidManifest.xml <uses-permission android:name="android.permission.INTERNET"/> app cannot be debugged: need to add the debuggable attribute to the application tag in the AndroidManifest <application android:icon="@drawable/msg" android:debuggable="true"> wrong server URL (localhost doesn’t work.) com.caucho.hessian.client.HessianRuntimeException: java.net.ConnectException: / 192.168.200.120:80 - Connection refused Copyright © 2010 http://wolfpaulus.com
  34. 34. Unlocking Android Android Wireless Application Development
  35. 35. http://twitter.com/wolfpaulus Thanks For Coming!
  36. 36. Slides & Sources Slides: http://wolfpaulus.com/bio/talks/androidws.pdf Code: http://wolfpaulus.com/bio/talks/androidws.zip Email: wolf@wolfpaulus.com

×