31

I have a Visualforce page that is used in both Salesforce1 and the desktop. On that page is a button. That button should only display if the user is loading the page on the desktop. It should be hidden on Salesforce1. Any suggestions?

Essentially I am just looking for a way to detect if the Visualforce page is loaded in Salesforce1 or not. I can handle the logic of displaying the button, I just don't know if it is possible to tell if it is Salesforce1 or not.

1
  • 2
    New feature in Spring 16 for this question! See the new answer below from @DougAyers.
    – pchittum
    Feb 23, 2016 at 21:35

5 Answers 5

23

In the Salesforce Spring 16 release, there will be global variables and apex methods you can call to detect the user's UI theme context. This may make it easier for developers to detect the user's experience without relying on the existence of certain javascript objects or URL parameters.

http://docs.releasenotes.salesforce.com/en-us/spring16/release-notes/rn_vf_uitheme.htm#rn_vf_uitheme

The User.UITheme and User.UIThemeDisplayed global variables and the UserInfo.getUiTheme() and UserInfo.getUiThemeDisplayed() Apex utility methods are improved to support the Salesforce1 mobile app and Lightning Experience.

These existing variables and system calls have expanded the range of return values to support the new user experience contexts. Possible return values include the following.

  • Theme1—Obsolete Salesforce theme

  • Theme2—Salesforce Classic 2005 user interface theme

  • Theme3—Salesforce Classic 2010 user interface theme

  • Theme4d—Modern “Lightning Experience” Salesforce theme

  • Theme4t—Salesforce1 mobile Salesforce theme

  • PortalDefault—Salesforce Customer Portal theme

  • Webstore—Salesforce AppExchange theme

These global variables and system calls can replace other, more fragile methods of detecting the user experience context, such as testing for the presence of the sforce.one JavaScript global. Use them to write Visualforce pages and apps that adapt to the user experience context in which they’re running.

30

If you can make due with JavaScript checking you can use the method outlined in this documentation that looks for the sforce JavaScript object, and just adapt it to do your work.

if( (typeof sforce != 'undefined') && (sforce != null) ) {
    // do your SF1 mobile button stuff
}
else {
    // do your desktop stuff
}

There isn't an official way to do a server side check. See this twitter conversation for more, where the following gist by TehNrd (Jason Venable) is referenced which checks for the presence of certain parameters.

//Determine if this is SF1 app
public static Boolean isSF1(){
    if(String.isNotBlank(ApexPages.currentPage().getParameters().get('sfdcIFrameHost')) ||
        String.isNotBlank(ApexPages.currentPage().getParameters().get('sfdcIFrameOrigin')) ||
        ApexPages.currentPage().getParameters().get('isdtp') == 'p1' ||
        (ApexPages.currentPage().getParameters().get('retURL') != null && ApexPages.currentPage().getParameters().get('retURL').contains('projectone') )
    ){
        return true;
    }else{
        return false;
    }
}

There is also an Idea,"Provide a supported url param to determine if page is in SF1", on the Idea Exchange.

4
  • Peter - would the best/simplest way to make a non-SF1 page compatible be to use the If/Else to split the page into two paths? One that has the legacy VF page details with the other being the SF1 view?
    – 44f
    May 29, 2014 at 10:26
  • @44f - It would depend on the requirements for me. It could be cleaner to do something like two includes or just redirects and share the controller from the two different views (i.e., pages). May 30, 2014 at 11:29
  • 1
    Reusing same VF page in desktop and s1 is fine, but what about too many tabs issue i.e. if a VF page is meant for mobile only and has no utility in desktop. I think we can promote an idea, to hide all such mobile only tabs from desktop. Plus, an option to make a tab available in both mobile + desktop would be nice. Jul 31, 2014 at 13:02
  • For javascript you should really be using the !== operator to check for exact equivalence (which is what you want in this case). It's a bit faster since it doesn't attempt to do any type coercion.
    – Akrikos
    Mar 13, 2015 at 14:49
6

In addition to the officially sanctioned methods above, I wanted to add a way to check if the user is on a mobile device using user agent detection in apex:

public static boolean isMobile(String userAgentString) {
    //Using RegEx, figure out if the user is on a mobile device based on the user-agent string
    if (userAgentString == null)  return false;
    Pattern p = Pattern.compile('Mobile|iP(hone|od|ad)|Android|BlackBerry|IEMobile|Kindle|NetFront|Silk-Accelerated|(hpw|web)OS|Fennec|Minimo|Opera M(obi|ini)|Blazer|Dolfin|Dolphin|Skyfire|Zune');
    Matcher pm = p.matcher( userAgentString );

    return pm.find();

}
5

Try this:

var isSF1=typeof sforce === 'undefined'?false:true;

isSF1 will be a boolean indicating whether you're loaded in SF1.

1
public static string isLightningExperience()
 {
        boolean isLightningExperience = false;
        string id = UserInfo.getUserId();
        for (User u: [SELECT Id, UserPreferencesLightningExperiencePreferred FROM User WHERE Id =: id LIMIT 1])
        {
            isLightningExperience = u.UserPreferencesLightningExperiencePreferred;
        }
        return string.valueOf(isLightningExperience);
 }
2

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .