39

PDF Slides, 4.2MB - Wolf Paulus

Embed Size (px)

Citation preview

Page 1: PDF Slides, 4.2MB - Wolf Paulus
Page 2: PDF Slides, 4.2MB - Wolf Paulus

Writing a Web Service Client App for Android© 2010 http://wolfpaulus.com

Page 3: PDF Slides, 4.2MB - Wolf Paulus

Agenda

Server Side (e.g. Tomcat)

Hessian, Binary Protocol

Http-Session Support

Client

hessdroid

remote calls / async

Page 4: PDF Slides, 4.2MB - Wolf Paulus

Quick Tips

Use Android’s R.class

Auto-Launch an Intent at boot time

Client

Things that can will go wrong

Agenda

Page 5: PDF Slides, 4.2MB - Wolf Paulus
Page 6: PDF Slides, 4.2MB - Wolf Paulus

Switch Activity

Switch Activity

Remote call

reload users

Remote Call to getNext

Four item main menu

Page 7: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

Exposing a Service Class: Hessian Binary Web Service Protocol

Page 8: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

Page 9: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

Java Hessian

Page 10: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

Java Hessian

Page 11: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

package com.carlsbadcubes.api;

import java.util.Collection;

public interface CommService { Collection<Message> getMessages();

Collection<User> getUsers();}

Copyright © 2010 http://wolfpaulus.com

Page 12: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

<?xml version="1.0" encoding="UTF-8"?><web-app>

<servlet> <servlet-name>myservice</servlet-name> <servlet-class>com.caucho.hessian.server.HessianServlet</servlet-class>

<init-param> <param-name>service-class</param-name> <param-value>com.carlsbadcubes.impl.CommServiceImpl</param-value> </init-param>

<init-param> <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

Interface

Implementation

defined in hessian.jar

Page 13: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

Roles <security-role> <role-name>HessianService</role-name> </security-role> <login-config> <auth-method>BASIC</auth-method> <realm-name>default</realm-name> </login-config> <security-constraint> <web-resource-collection> <web-resource-name>SecureConnection</web-resource-name> <url-pattern>/service/*</url-pattern> <url-pattern>/comm/*</url-pattern>

... <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <role-name>HessianService</role-name> </auth-constraint> <user-data-constraint> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint> </security-constraint>

Groups or Principals

Communication

Components

Access Privileges

Realm

Copyright © 2010 http://wolfpaulus.com

Page 14: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

Servlet

Thread

Thread

Thread

m_var

http requests

ServiceClassimpl.

ServiceAPI

created in servlet.init()

(1)

(1)

(1)

(n)

::

Page 15: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

http response

JSESSIONID = 123

JSESSIONID = 789

JSESSIONID = 357

SessionMap

123

789357

Servlet

Thread

Thread

Thread

m_var

ServiceClassimpl.

ServiceAPI

::

request.getSession()

Page 16: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

http response

JSESSIONID = 123

JSESSIONID = 789

JSESSIONID = 357

SessionMap

123

789357

http request Servlet

Thread

Thread

Thread

m_var

ServiceClassimpl.

ServiceAPI

::

123ThreadLocal

789ThreadLocal

357ThreadLocal

Page 17: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

The ThreadLocal Class:

public class ThreadLocal<T> {   public void set( T newValue ); public T get(); public void remove();  protected T initialValue();}

Page 18: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

HessianHttpServlet extends HessianServlet implements HessianHttpService {

... }

... not in hessian.jar

Page 19: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

.. all of HessianServlet

Discovery Service for Android Clients

Map<String, String> getServices()

puts HttpSession Map into ThreadLocal

memory

HessianHttpServlet extends HessianServlet implements HessianHttpService

Page 20: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

HessianHttpServlet@Overrideinit() .. // // 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."); } }

@Overrideservice() ..

if (this.requiresSessionSupport) { HttpServletRequest req = (HttpServletRequest) request; ThreadLocalAttrMap.set( req.getSession( true ) ); }

Page 21: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

= Client

Page 22: PDF Slides, 4.2MB - Wolf Paulus
Page 23: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

String url = “http://hostname.domain:port/service”;

ServiceProxyFactory factory = new HessianProxyFactory();factory.set ..(..);factory.set ..(..).

CommService cs = factory.create( CommService.class, url , getClassLoader());

hessdroidhttp://code.google.com/p/hessdroid/

Page 24: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

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 );

hessdroidhttp://code.google.com/p/hessdroid/

Page 25: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

Creates a Cookie Map,Maintains HttpSessions

HessianHttpProxyFactory extends HessianProxyFactory {

... }

hessdroidhttp://code.google.com/p/hessdroid/

Page 26: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

Service Discovery:maps Interfaces to URLs

HessianFactory.initialize( )

... not in hessdroid.jar

Page 27: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

Hessian Client

CommService cs = HessianFactory.create( CommService.class, getClassLoader() )

Page 28: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

DemoTomcat Server with a Hessian Service and a Hessian based Android Client

Page 29: PDF Slides, 4.2MB - Wolf Paulus

Async ....

Don’t run HessionFactory.create(..) in the main threadDon’t run remote method calls in the main thread either.

Copyright © 2010 http://wolfpaulus.com

Page 30: PDF Slides, 4.2MB - Wolf Paulus

Interface Garage { void openDoor();

Car getCar();}

Interface Car {void openDoor();Color getColor();

}

Copyright © 2010 http://wolfpaulus.com

Page 31: PDF Slides, 4.2MB - Wolf Paulus

Copyright © 2010 http://wolfpaulus.com

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 callgarage.getCar().openDoor(); // local call

Page 32: PDF Slides, 4.2MB - Wolf Paulus

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

Page 33: PDF Slides, 4.2MB - Wolf Paulus

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

Page 34: PDF Slides, 4.2MB - Wolf Paulus

Auto-Launch after boot (1 of 2)

Copyright © 2010 http://wolfpaulus.com

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"/>

Page 35: PDF Slides, 4.2MB - Wolf Paulus

Auto-Launch after boot (2 of 2)

Copyright © 2010 http://wolfpaulus.com

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));

} }}

Page 36: PDF Slides, 4.2MB - Wolf Paulus

Things that can will go wrongwrong classloader:java.lang.IllegalArgumentException: com.pss.api.Service is not visible from class loaderUse AppContext.getClassLoader()

app doesn’t have Internet permission:com.caucho.hessian.client.HessianRuntimeException: java.net.SocketException: Permission deniedAndroidManifest.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

Page 37: PDF Slides, 4.2MB - Wolf Paulus

Unlocking Android

Android Wireless Application Development

Page 38: PDF Slides, 4.2MB - Wolf Paulus

Thanks For Coming!

http://twitter.com/wolfpaulus