Salesforce Integration with Mobile Application
Salesforce—a mature CRM platform with well-documented REST API and several SDKs for mobile. Unlike 1C or Bitrix24, fewer unexpected API limitations, but more concepts to learn: Connected App, OAuth 2.0 flows, SOQL, SOSL, Apex REST, Platform Events.
Connected App and OAuth
Everything starts with creating Connected App in Salesforce Setup: App Manager → New Connected App. Specify Callback URL (app deeplink), enable OAuth scopes: api, refresh_token offline_access.
Mobile app uses OAuth 2.0 Authorization Code Flow or JWT Bearer Flow for server-to-server. For user context — Authorization Code.
On Android—AppAuth library:
val serviceConfig = AuthorizationServiceConfiguration(
Uri.parse("https://login.salesforce.com/services/oauth2/authorize"),
Uri.parse("https://login.salesforce.com/services/oauth2/token")
)
val request = AuthorizationRequest.Builder(
serviceConfig,
clientId,
ResponseTypeValues.CODE,
Uri.parse("myapp://oauth/callback")
).setScope("api refresh_token offline_access").build()
authService.performAuthorizationRequest(request, pendingIntent)
After code-token exchange, save access_token, refresh_token, and instance_url—base URL for all API calls (each Salesforce org has its own subdomain).
REST API and SOQL
Salesforce REST API — the main interface. Base URL: {instance_url}/services/data/v60.0/. Choose API version matching minimum supported version at client.
Query via SOQL (Salesforce Object Query Language):
GET /services/data/v60.0/query/?
q=SELECT+Id,Name,Amount,StageName,CloseDate,Account.Name
+FROM+Opportunity
+WHERE+OwnerId='{userId}'+AND+IsClosed=false
+ORDER+BY+CloseDate+ASC+LIMIT+50
SOQL—SQL-like language with limitations: no JOIN in traditional sense, related objects via relationship query (Account.Name). LIMIT maximum 2000. For larger sets — queryMore with nextRecordsUrl from response.
Create record — POST /services/data/v60.0/sobjects/Opportunity/ with JSON body. Update — PATCH /services/data/v60.0/sobjects/Opportunity/{id}. Important: Salesforce uses PATCH, not PUT for updates.
Platform Events for Real-time
Salesforce Platform Events—publish/subscribe mechanism. Server publishes event (OpportunityUpdated__e), clients receive via CometD (Bayeux protocol, long polling).
On mobile — Salesforce Mobile SDK or custom CometD implementation. Mobile SDK includes ready SFRestAPI and StreamingAPI client. But SDK is heavy—15+ MB, critical for some projects.
Light alternative: custom CometD client on OkHttp:
val cometdClient = BayeuxClient(
"${instanceUrl}/cometd/60.0",
LongPollingTransport.create(null, okHttpClient)
)
cometdClient.handshake()
cometdClient.getChannel("/event/OpportunityUpdated__e")
.subscribe { message ->
val payload = message.dataAsMap
handleOpportunityUpdate(payload)
}
On Salesforce opportunity update → Platform Event → CometD → mobile client updates screen. Latency: 1-3 seconds.
Salesforce Mobile SDK vs Custom Integration
| Salesforce Mobile SDK | Custom Integration | |
|---|---|---|
| OAuth | Built-in | AppAuth / custom |
| Offline | SmartStore (SQLCipher) | Room / Core Data |
| Push | Built-in | FCM/APNs directly |
| Size | +15 MB | Minimal |
| Flexibility | SDK-limited | Full |
SDK justified if app is predominantly Salesforce-oriented. For apps where Salesforce is one of several integrations—custom approach better.
Salesforce Files and Attachments
Files in Salesforce—ContentDocument and ContentVersion. Upload file from mobile:
POST /services/data/v60.0/sobjects/ContentVersion/
Content-Type: multipart/form-data
{
"Title": "Customer Photo",
"PathOnClient": "photo.jpg",
"FirstPublishLocationId": "{opportunityId}"
}
+ binary data
FirstPublishLocationId — object the file links to. Limitation: one file per request. For multiple uploads—sequential requests or Salesforce Bulk API.
Timeline
Basic integration (OAuth, SOQL queries, CRUD for Opportunity/Contact): 1-2 weeks. Platform Events, offline cache, push notifications: plus 1-2 weeks. Full app with Salesforce Mobile SDK, SmartStore and sync: 1.5-2 months. Cost calculated individually.







