[SalesForce] Navigation to VF page /Lightning component based on UIThemeDisplayed

I have this scenario where I have overridden Opportunity New button with a Visualforce page. I am trying to find a way where I need to redirect users to a Lightning App when the user is in Lightning Experience or else redirects to Visualforce page when the user is in Classic. Idea is to have compatibility on both world as we are planning to migrate users to Lightning in phased manner.

I have created Lightning Application for Opportunity. I also understood how to detect the user context based on UIThemeDisplayed. What I am not clear how to navigate user to Lightning app if a user is in Lightning experience.

    public static Boolean isSF1 {get {
        String theme = UserInfo.getUiThemeDisplayed();
        if(theme == 'Theme4t'){
            isSF1 = true;
        }else{
            isSF1 = false;
        }
        return isSF1;
} set;}

    public PageReference ContinueToNew() {
    PageReference opp = new PageReference('/apex/Opportunity_NewMode');
    if (isSF1) {
        ******* I would like to replace the following line of code to Lightning component******
        if (string.isBlank(AccountID)) {
            opp = new PageReference('/apex/SE_AccountSearchPage');
        } else {
            opp = new PageReference('/apex/SE_CompanyLookupSF1');
        }
        *****************************************************************************
    }
}

Best Answer

You can use following code
UserInfo.getUiThemeDisplayed() will identify logged in user instance, if its Lightning or classic, based on that you can form your URL to redirect user to your specific page.

String serverInstance = Utilities.getOrganizationDetails().InstanceName.toLowerCase();
if(UserInfo.getUiThemeDisplayed()=='Theme4d')
{
    this.baseUrl = 'https://' + this.serverInstance + '.lightning.force.com/one/one.app#/n/';
    this.redirectUrl = this.baseUrl+Utilities.getNamespacePrefix()+'YourExactPageNameinLEX';
}
else
{
    this.baseUrl = 'https://' + this.serverInstance + '.salesforce.com';
    this.redirectUrl = this.baseUrl+'/apex/'+Utilities.getNamespacePrefix()+'YourExactPageNameinClassic';
}

Add this Utility Class to get your org name space and organization details,if your using package with namespace, this will append the required namespace in your URL.

public with sharing class Utilities{
/**
* @description: Method To return NameSpace,
* @param: None
* @return: None.
**/
public static String getNamespacePrefix() {
    Integer indexOfToken = -1;
    String namespace = '';
    for (Schema.SObjectType type : Schema.getGlobalDescribe().values()) {
        String sobjName = String.valueOf(type);
        if (null != sobjName) {
          indexOfToken = sobjName.indexOf('YourOrgCustomObject');
        }//if
        if (indexOfToken != -1) {
            namespace = sobjName.substring(0, indexOfToken);
            break;
        }//if
    }//for
    return namespace;
}//getNamespacePrefix

/**
* @description method to get the Organization Details
* @param None
* @return Organization
*/
public static Organization getOrganizationDetails()
{
    if(orgDetails != null)
    {
        return orgDetails;
    }
    else
    {
        orgDetails = [SELECT
            id, 
            name, 
            InstanceName, 
            IsSandbox, 
            OrganizationType
        FROM
            Organization
        limit 1];
        return orgDetails;
    }
}
}//Utilities

ap5 = Server Instance which will be returned by following code, which will vary with different orgs.

String serverInstance = Utilities.getOrganizationDetails().InstanceName.toLowerCase();

In Lightning:-
Final URL:- https://ap5.lightning.force.com/one/one.app#/n/NAMESPACE__YOURPAGE

In Classic:-
Final URL: https://NAMESPACE.ap5.visual.force.com/apex/Your_Classic_Page