Developing Cross-Platform Compatible Pages

It can be challenging to build Visualforce Mobile pages that look good and perform well in both the BlackBerry and iPhone embedded browsers. Salesforce recommends using one of the following approaches:

Separation and Redirection
Build pages separately for BlackBerry and iPhone. When you create the tab for your Visualforce Mobile page, point the tab to the BlackBerry-optimized page. At the top of that Visualforce Mobile page, include JavaScript that automatically redirects to the iPhone page if the connecting device is not a BlackBerry smartphone:
<apex:page>
<language="javascript" type="text/javascript">
     if(!window.blackberry){
         window.location.href='{!$Page.iPhoneOptimizedVersion}';
     }
</script>
</apex:page>
This approach offers the best user experience for all devices with the fewest long-term development headaches. However, it does require you to maintain two separate applications—one for each device type.
Lowest Common Denominator
Build to the lowest common denominator and include only minimal, unobtrusive JavaScript, avoiding scripts with inline events in the tags. Depending on the devices in the customer's organization, you might need to avoid JavaScript all together. On older BlackBerry smartphones, using any JavaScript at all can cause the page to malfunction.
Conditional Code
Build device-conditional code and styles. The user agent string, contained in the header passed by the browser to the server, identifies the connecting device as BlackBerry or iPhone. The code in your Visualforce Mobile page evaluates the user agent string and displays the content appropriate for the connecting device. The benefit of Visualforce is that the markup is interpreted server-side, and the client only receives the markup it can render based on the assessment of the conditional statements. Building with conditional code is the most sophisticated approach, but not necessarily the best long-term solution due to the added code complexity.
Note

Note

Dynamic References to Static Resources Using $Resource illustrates an alternative approach to dynamically displaying different graphics based on characteristics of the request.

For example, the following markup creates a custom component named mobileSample that simply displays an image stored within the mobileImages static resource. However, it determines which image to display at runtime based on the browser's reported user agent value as inspected in the component’s controller.
<apex:component controller="mobileSampleCon">
<apex:image value="{!URLFOR($Resource.mobileImages, deviceType + '.jpg')}"/>
</apex:component>
// mobileSampleCon Controller code snippet
...
public class mobileSampleCon {

    public String deviceType { get; set; }

    public MobileSampleCon() {
        String userAgent = ApexPages.currentPage().getHeaders().get('USER-AGENT');

        if(userAgent.contains('iPhone')) {
							deviceType = 'iPhone';
					} 
        else if(userAgent.contains('BlackBerry')) {
							deviceType = 'BlackBerry';
					}
    }
}
The following example loads different stylesheets based on the connecting application. First, you can create the page that you want displayed across multiple devices:
<!-- Visualforce code snippet -->
...
<head>
<linkrel="stylesheet" type="text/css" href="{!URLFOR($Resource.Global, '/inc/css/global.css')}"/>
<c:conditionalStylesheets resource="{!$Resource.Global}" />
<linkrel="stylesheet" type="text/css" href="{!URLFOR($Resource.SendEmail, '/inc/css/local.css')}"/>
<c:conditionalStylesheets resource="{!$Resource.SendEmail}" />
</head>
...
The Global.zip and SendEmail.zip files are static resources that contain the referenced CSS files. For the conditionalStylesheets custom component, you can define multiple CSS declarations that are rendered based on the browser type:
// Visualforce component code
<apex:component controller="myConditionalController">

<apex:attribute name="resource" description="The resource name" type="String" required="true"/>

// for a BlackBerry standard browser, e.g., Bold
<apex:outputPanel layout="none" rendered="{!browserName = 'BlackBerry'}">
<linkrel="stylesheet" type="text/css" href="{!URLFOR(resource, '/inc/css/BBBrowser.css')}"/>
</apex:outputPanel>

// for a BlackBerry embedded browser in Salesforce Classic
// the Apex code distinguished between the regular and embedded browsers
<apex:outputPanel layout="none" rendered="{!browserName = 'Salesforce'}">
<linkrel="stylesheet" type="text/css" href="{!URLFOR(resource, '/inc/css/BBEmbedded.css')}"/>
</apex:outputPanel>

// for the iPhone Safari browser (inside Salesforce Classic or not)
<apex:outputPanel layout="none" rendered="{!browserName = 'iPhone-Safari'}">
<meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0;  user-scalable=0;">
</meta>
<linkrel="stylesheet" type="text/css" href="{!URLFOR(resource, '/inc/css/IPhone.css')}"/>
</apex:outputPanel>

</apex:component>
Finally, the browserName value is determined in an Apex controller in a manner similar to the preceding example:
Note

Note

Salesforce Classic Mobile appends the text "Salesforce" to the end of the string for the embedded BlackBerry browser. Additionally, the user can change the user agent string on some BlackBerry smartphones.

// Apex code snippet
...
public static String getBrowserName()
{
String userAgent = ApexPages.currentPage().getHeaders().get('User-Agent');
    if (userAgent.contains('iPhone'))
        return 'iPhone-Safari';
    if (userAgent.contains('Salesforce'))
        return 'Salesforce';
    if (userAgent.contains('BlackBerry'))
        return 'BlackBerry';
    return 'other';
}
...
Note

Note

Commands in the JavaScript library for Salesforce Classic Mobile can be used for both iPhone and BlackBerry devices.

Previous
Next