Table of Contents
Device detection is useful when requests by mobile devices need to be handled differently from requests made by desktop browsers. The Spring Mobile Device module provides support for server-side device detection.
Add the spring-mobile-device artifact to your classpath:
<dependency> <groupId>org.springframework.mobile</groupId> <artifactId>spring-mobile-device</artifactId> <version>${org.springframework.mobile-version}</version> </dependency>
The DeviceResolverHandlerInterceptor detects the device that originated the web request before handler invocation. The detected Device is set as a request attribute named 'currentDevice' and made available to handlers during request processing. This allows handlers to vary their controller and/or presentation logic by device type.
To use, add the DeviceResolverHandlerInterceptor to the list of interceptors defined in your DispatcherServlet context configuration:
<interceptors> <!-- On pre-handle, detect the device that originated the web request --> <beans:bean class="org.springframework.mobile.device.mvc.DeviceResolverHandlerInterceptor" /> </interceptors>
By default, the interceptor will use a LiteDeviceResolver for device detection. You may plug-in your own DeviceResolver by injecting a constructor argument. See Section 2.5, “Device resolvers” for more information on the implementation options.
The DeviceWebArgumentResolver allows you to inject the detected Device into @Controller handler methods. To use, register this resolver with your DispatcherServlet's AnnotationMethodHandlerAdapter infastructure bean:
@Component public class CustomWebArgumentResolverInstaller { @Inject public CustomWebArgumentResolverInstaller(AnnotationMethodHandlerAdapter controllerInvoker) { WebArgumentResolver[] resolvers = new WebArgumentResolver[1]; resolvers[0] = new DeviceWebArgumentResolver(); controllerInvoker.setCustomArgumentResolvers(resolvers); } }
You can then inject the detect Device into your @Controllers as shown below:
@Controller public class HomeController { private static final Logger logger = LoggerFactory.getLogger(WurflShowcaseController.class); /** * Declares a {@link Device} parameter to show how you can resolve the model for the device that originated the current request. * Argument resolution is handled by the {@link DeviceWebArgumentResolver} installed by {@link CustomWebArgumentResolverInstaller}. */ @RequestMapping("/") public void home(Device device) { if (device.isMobile()) { logger.info("Hello mobile user!"); } else { logger.info("Hello desktop user!"); } }
The DeviceResolver interface is central the service API for device detection. Spring Mobile provides two DeviceResolver implementations: LiteDeviceResolver and WurflDeviceResolver. You may also implement your own.
The default DeviceResolver implementation based on the "lite" detection algorithm implemented as part of the Wordpress Mobile Pack. This resolver only detects the presence of a mobile device and does not detect specific capabilities.
A DeviceResolver implementation that delegates to WURFL for device detection. WURFL provides a large database of devices and their capabilities. It is useful when you need to know more about the Device that originated the request, such as its specific screen size, manufacturer, model, preferred markup, or other capabilities.
To use, first make sure WURFL is in your classpath:
<dependency> <groupId>net.sourceforge.wurfl</groupId> <artifactId>wurfl</artifactId> <version>${net.sourceforge.wurfl-version}</version> </dependency>
To enable the resolver, include the spring-mobile-device XML namespace and use the wurfl-device-resolver tag:
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:device="http://www.springframework.org/schema/mobile/device" xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mobile/device http://www.springframework.org/schema/mobile/device/spring-mobile-device-1.0.xsd"> <interceptors> <!-- On pre-handle, use WURFL to detect the device that originated the web request --> <beans:bean class="org.springframework.mobile.device.mvc.DeviceResolverHandlerInterceptor"> <beans:constructor-arg> <device:wurfl-device-resolver root-location="/WEB-INF/wurfl/wurfl-2.0.25.zip" patch-locations="/WEB-INF/wurfl/web_browsers_patch.xml" /> </beans:constructor-arg> </beans:bean> </interceptors> </beans:beans>
Read more about WURFL at http://wurfl.sourceforge.net. Checkout the wurfl-showcase for a live demonstration. This sample illustrates WURFL-based device detection as well as the use of the WNG tag library to perform multi-serving from common page markup.
If you implement your own DeviceResolver, please consider contributing your implementation back to the community at http://www.springsource.org/spring-mobile.
Use the SiteSwitcherHandlerInterceptor to redirect mobile users to a dedicated mobile site. Users may also indicate a site preference; for example, a mobile user may still wish to use 'normal' site. Convenient static factory methods are provided that implement standard site switching conventions.
Use the "mDot" factory method to construct a SiteSwitcher that redirects mobile users to m.${serverName}; for example, m.myapp.com:
<interceptors> <!-- Redirects mobile users to "m.myapp.com". The order of this interceptor is significant (it should be declared after the DeviceResolverHandlerInterceptor) --> <beans:bean class="org.springframework.mobile.device.switcher.SiteSwitcherHandlerInterceptor" factory-method="mDot"> <beans:constructor-arg value="myapp.com" /> </beans:bean> </interceptors>
Use the "dotMobi" factory method to construct a SiteSwitcher that redirects mobile users to ${serverName - lastDomain}.mobi; for example, myapp.mobi:
<interceptors> <!-- Redirects mobile users to "myapp.mobi". The order of this interceptor is significant (it should be declared after the DeviceResolverHandlerInterceptor) --> <beans:bean class="org.springframework.mobile.device.switcher.SiteSwitcherHandlerInterceptor" factory-method="dotMobi"> <beans:constructor-arg value="myapp.com" /> </beans:bean> </interceptors>
The user may indicate a site preference by submitting the site_preference query parameter:
Site: <a href="${currentUrl}?site_preference=normal">Normal</a> | <a href="${currentUrl}?site_preference=mobile">Mobile</a>
The indicated site preference is saved for the user in a SitePreferenceRepository, and also made available as a request attribute named 'currentSitePreference'. The default SitePreferenceRepository implementation used by the mDot and dotMobi SiteSwitcher factory methods is cookie-based. The cookie value is shared across the normal and mobile site domains.
The SitePreferenceWebArgumentResolver allows you to inject the user's indicated SitePreference into @Controller handler methods. To use, add this resolver to the list of custom WebArgumentResolvers registered with the DispatcherServlet's AnnotationMethodHandlerAdapter infastructure bean:
@Component public class CustomWebArgumentResolverInstaller { @Inject public CustomWebArgumentResolverInstaller(AnnotationMethodHandlerAdapter controllerInvoker) { WebArgumentResolver[] resolvers = new WebArgumentResolver[2] resolvers[0] = new DeviceWebArgumentResolver(); resolvers[1] = new SitePreferenceArgumentResolver(); controllerInvoker.setCustomArgumentResolvers(resolvers); } }
You can then inject the indicated SitePreference into your @Controllers as shown below:
@Controller public class HomeController { @RequestMapping("/") public String home(SitePreference sitePreference, Model model) { if (sitePreference == SitePreference.MOBILE) { // prepare mobile view for rendering return "home-mobile"; } else { // prepare normal view for rendering return "home"; } } }
See the spring-mobile samples repository for runnable SiteSwitcher examples.