Skip to content

Commit

Permalink
W-16171426: [Android] Update Native Login Sample App to include QR Co…
Browse files Browse the repository at this point in the history
…de Login Flow (Comment Out Log In Via UI Bridge API Generated QR Codes)
  • Loading branch information
JohnsonEricAtSalesforce committed Jul 22, 2024
1 parent 33b5536 commit 3049445
Show file tree
Hide file tree
Showing 8 changed files with 180 additions and 176 deletions.
4 changes: 2 additions & 2 deletions AndroidNativeKotlinTemplate/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ plugins {
dependencies {
implementation("com.salesforce.mobilesdk:MobileSync:12.1.0")
// Uncomment when enabling log in via Salesforce UI Bridge API generated QR codes
implementation("com.google.zxing:core:3.4.1")
implementation("com.journeyapps:zxing-android-embedded:4.3.0")
// implementation("com.google.zxing:core:3.4.1")
// implementation("com.journeyapps:zxing-android-embedded:4.3.0")
}

android {
Expand Down
45 changes: 28 additions & 17 deletions AndroidNativeKotlinTemplate/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,25 +23,36 @@
</activity>

<!-- Login activity -->
<!-- Use `android:name="com.salesforce.androidnativekotlintemplate.QrCodeEnabledLoginActivity"` when enabling log in via Salesforce UI Bridge API generated QR codes -->
<activity
android:name="com.salesforce.androidnativekotlintemplate.QrCodeEnabledLoginActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/SalesforceSDK">
<!--
To enable browser based authentication, uncomment the lines below and replace
'scheme', 'host' and 'path' with their corresponding values from your connected app.
<!-- Uncomment when enabling log in via Salesforce UI Bridge API generated QR codes -->
<intent-filter>
<data
android:host="android"
android:path="/login/qr"
android:scheme="mobileapp" />
<action android:name="android.intent.action.VIEW" />
For example, if the callback URL of your connected app is
"testsfdc:///mobilesdk/detect/oauth/done",
'scheme' would be "testsfdc", 'host' would be "*" since it doesn't exist, and
'path' would be "/mobilesdk/detect/oauth/done".
<category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
If the callback URL is "sfdc://login.salesforce.com/oauth/done",
'scheme' would be "sfdc", 'host' would be "login.salesforce.com",
and 'path' would be "/oauth/done".
-->
<!-- Use `android:name="com.salesforce.androidnativekotlintemplate.QrCodeEnabledLoginActivity"` when enabling log in via Salesforce UI Bridge API generated QR codes -->
<!-- <activity-->
<!-- android:name="com.salesforce.androidsdk.ui.LoginActivity"-->
<!-- android:exported="true"-->
<!-- android:launchMode="singleTop"-->
<!-- android:theme="@style/SalesforceSDK">-->

<!-- &lt;!&ndash; Uncomment when enabling log in via Salesforce UI Bridge API generated QR codes &ndash;&gt;-->
<!-- &lt;!&ndash; <intent-filter>&ndash;&gt;-->
<!-- &lt;!&ndash; <data&ndash;&gt;-->
<!-- &lt;!&ndash; android:host="android"&ndash;&gt;-->
<!-- &lt;!&ndash; android:path="/login/qr"&ndash;&gt;-->
<!-- &lt;!&ndash; android:scheme="mobileapp" />&ndash;&gt;-->
<!-- &lt;!&ndash; <action android:name="android.intent.action.VIEW" />&ndash;&gt;-->
<!-- &lt;!&ndash; <category android:name="android.intent.category.BROWSABLE" />&ndash;&gt;-->
<!-- &lt;!&ndash; <category android:name="android.intent.category.DEFAULT" />&ndash;&gt;-->
<!-- &lt;!&ndash; </intent-filter>&ndash;&gt;-->
<!-- </activity>-->
</application>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class MainApplication : Application() {
*
*/
// Uncomment when enabling log in via Salesforce UI Bridge API generated QR codes
QrCodeEnabledLoginActivity::class.java)
/*QrCodeEnabledLoginActivity::class.java*/)
MobileSyncSDKManager.getInstance().registerUsedAppFeature(FEATURE_APP_USES_KOTLIN)

/*
Expand All @@ -69,6 +69,6 @@ class MainApplication : Application() {

// Enable login via Salesforce UI Bridge API generated QR code.
// Uncomment when enabling log in via Salesforce UI Bridge API generated QR codes
MobileSyncSDKManager.getInstance().isQrCodeLoginEnabled = true
// MobileSyncSDKManager.getInstance().isQrCodeLoginEnabled = true
}
}
Original file line number Diff line number Diff line change
@@ -1,72 +1,72 @@
package com.salesforce.androidnativekotlintemplate

import android.content.Intent
import android.os.Bundle
import android.view.View
import android.view.View.VISIBLE
import android.widget.Button
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import com.journeyapps.barcodescanner.ScanContract
import com.journeyapps.barcodescanner.ScanIntentResult
import com.journeyapps.barcodescanner.ScanOptions
import com.salesforce.androidnativekotlintemplate.R.id.qr_login_button
import com.salesforce.androidsdk.ui.LoginActivity

/**
* A subclass of Salesforce Mobile SDK's login activity that enables log in via
* a Salesforce UI Bridge API generated QR code. If an app wishes not to use
* this feature, this class can be removed and use the superclass directly.
*
*/
// Uncomment when enabling log in via Salesforce UI Bridge API generated QR codes
class QrCodeEnabledLoginActivity : LoginActivity() {

// region Activity Implementation

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

findViewById<Button>(qr_login_button).visibility = VISIBLE
prepareQRReader()
}

// endregion
// region User Interface Events

/**
* An action for the "Log In With QR" button.
* @param view The button that the user tapped
*/
fun onQRLoginClick(@Suppress("UNUSED_PARAMETER") view: View?) = startQrCodeReader()

// endregion
// region Private Implementation For QR Code Log In

private var qrCodeReaderActivityResultLauncher: ActivityResultLauncher<Intent>? = null

private fun prepareQRReader() {
qrCodeReaderActivityResultLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { resultData: ActivityResult ->
if (resultData.resultCode == RESULT_OK) {

val result = ScanIntentResult.parseActivityResult(
resultData.resultCode,
resultData.data
)

result.contents?.let { qrCodeContent ->
loginFromQrCode(qrCodeContent)
}
}
}
}

private fun startQrCodeReader() {
qrCodeReaderActivityResultLauncher?.launch(ScanContract().createIntent(this, ScanOptions()))
}

// endregion
}
//package com.salesforce.androidnativekotlintemplate
//
//import android.content.Intent
//import android.os.Bundle
//import android.view.View
//import android.view.View.VISIBLE
//import android.widget.Button
//import androidx.activity.result.ActivityResult
//import androidx.activity.result.ActivityResultLauncher
//import androidx.activity.result.contract.ActivityResultContracts
//import com.journeyapps.barcodescanner.ScanContract
//import com.journeyapps.barcodescanner.ScanIntentResult
//import com.journeyapps.barcodescanner.ScanOptions
//import com.salesforce.androidnativekotlintemplate.R.id.qr_login_button
//import com.salesforce.androidsdk.ui.LoginActivity
//
///**
// * A subclass of Salesforce Mobile SDK's login activity that enables log in via
// * a Salesforce UI Bridge API generated QR code. If an app wishes not to use
// * this feature, this class can be removed and use the superclass directly.
// *
// */
// // Uncomment when enabling log in via Salesforce UI Bridge API generated QR codes
//class QrCodeEnabledLoginActivity : LoginActivity() {
//
// // region Activity Implementation
//
// override fun onCreate(savedInstanceState: Bundle?) {
// super.onCreate(savedInstanceState)
//
// findViewById<Button>(qr_login_button).visibility = VISIBLE
// prepareQRReader()
// }
//
// // endregion
// // region User Interface Events
//
// /**
// * An action for the "Log In With QR" button.
// * @param view The button that the user tapped
// */
// fun onQRLoginClick(@Suppress("UNUSED_PARAMETER") view: View?) = startQrCodeReader()
//
// // endregion
// // region Private Implementation For QR Code Log In
//
// private var qrCodeReaderActivityResultLauncher: ActivityResultLauncher<Intent>? = null
//
// private fun prepareQRReader() {
// qrCodeReaderActivityResultLauncher = registerForActivityResult(
// ActivityResultContracts.StartActivityForResult()
// ) { resultData: ActivityResult ->
// if (resultData.resultCode == RESULT_OK) {
//
// val result = ScanIntentResult.parseActivityResult(
// resultData.resultCode,
// resultData.data
// )
//
// result.contents?.let { qrCodeContent ->
// loginFromQrCode(qrCodeContent)
// }
// }
// }
// }
//
// private fun startQrCodeReader() {
// qrCodeReaderActivityResultLauncher?.launch(ScanContract().createIntent(this, ScanOptions()))
// }
//
// // endregion
//}
146 changes: 73 additions & 73 deletions AndroidNativeKotlinTemplate/app/src/main/res/layout/sf__login.xml
Original file line number Diff line number Diff line change
@@ -1,79 +1,79 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This override layout adds a "Log In With QR" button to enable log in via Salesforce UI Bridge API generated QR codes -->
<!-- Uncomment when enabling log in via Salesforce UI Bridge API generated QR codes -->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/sf__auth_container_phone"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:windowDrawsSystemBarBackgrounds="true">
<!--<?xml version="1.0" encoding="utf-8"?>-->
<!--&lt;!&ndash; This override layout adds a "Log In With QR" button to enable log in via Salesforce UI Bridge API generated QR codes &ndash;&gt;-->
<!--&lt;!&ndash; Uncomment when enabling log in via Salesforce UI Bridge API generated QR codes &ndash;&gt;-->
<!--<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"-->
<!-- android:id="@+id/sf__auth_container_phone"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:windowDrawsSystemBarBackgrounds="true">-->

<ProgressBar
android:id="@+id/sf__loading_spinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true" />
<!-- <ProgressBar-->
<!-- android:id="@+id/sf__loading_spinner"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_centerInParent="true" />-->

<WebView
android:id="@+id/sf__oauth_webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
android:visibility="gone"
android:windowDrawsSystemBarBackgrounds="true" />
<!-- <WebView-->
<!-- android:id="@+id/sf__oauth_webview"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:scrollbars="none"-->
<!-- android:visibility="gone"-->
<!-- android:windowDrawsSystemBarBackgrounds="true" />-->

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:orientation="vertical">
<!-- <LinearLayout-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_alignParentEnd="true"-->
<!-- android:layout_alignParentBottom="true"-->
<!-- android:orientation="vertical">-->

<Button
android:id="@+id/sf__idp_login_button"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="20dp"
android:background="@drawable/sf__primary_color_button"
android:onClick="onIDPLoginClick"
android:text="@string/sf__launch_idp"
android:textAllCaps="false"
android:textColor="?attr/sfColorSecondary"
android:textSize="14sp"
android:textStyle="bold"
android:visibility="gone" />
<!-- <Button-->
<!-- android:id="@+id/sf__idp_login_button"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="50dp"-->
<!-- android:layout_marginLeft="20dp"-->
<!-- android:layout_marginRight="20dp"-->
<!-- android:layout_marginBottom="20dp"-->
<!-- android:background="@drawable/sf__primary_color_button"-->
<!-- android:onClick="onIDPLoginClick"-->
<!-- android:text="@string/sf__launch_idp"-->
<!-- android:textAllCaps="false"-->
<!-- android:textColor="?attr/sfColorSecondary"-->
<!-- android:textSize="14sp"-->
<!-- android:textStyle="bold"-->
<!-- android:visibility="gone" />-->

<Button
android:id="@+id/sf__bio_login_button"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="20dp"
android:background="@drawable/sf__primary_color_button"
android:onClick="onBioAuthClick"
android:text="@string/sf__login_with_biometric"
android:textAllCaps="false"
android:textColor="?attr/sfColorSecondary"
android:textSize="14sp"
android:textStyle="bold"
android:visibility="gone" />
<!-- <Button-->
<!-- android:id="@+id/sf__bio_login_button"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="50dp"-->
<!-- android:layout_marginLeft="20dp"-->
<!-- android:layout_marginRight="20dp"-->
<!-- android:layout_marginBottom="20dp"-->
<!-- android:background="@drawable/sf__primary_color_button"-->
<!-- android:onClick="onBioAuthClick"-->
<!-- android:text="@string/sf__login_with_biometric"-->
<!-- android:textAllCaps="false"-->
<!-- android:textColor="?attr/sfColorSecondary"-->
<!-- android:textSize="14sp"-->
<!-- android:textStyle="bold"-->
<!-- android:visibility="gone" />-->

<Button
android:id="@+id/qr_login_button"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="20dp"
android:background="@drawable/sf__primary_color_button"
android:onClick="onQRLoginClick"
android:text="@string/login_with_qr"
android:textAllCaps="false"
android:textColor="?attr/sfColorSecondary"
android:textSize="14sp"
android:textStyle="bold"
android:visibility="gone" />
</LinearLayout>
</RelativeLayout>
<!-- <Button-->
<!-- android:id="@+id/qr_login_button"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="50dp"-->
<!-- android:layout_marginLeft="20dp"-->
<!-- android:layout_marginRight="20dp"-->
<!-- android:layout_marginBottom="20dp"-->
<!-- android:background="@drawable/sf__primary_color_button"-->
<!-- android:onClick="onQRLoginClick"-->
<!-- android:text="@string/login_with_qr"-->
<!-- android:textAllCaps="false"-->
<!-- android:textColor="?attr/sfColorSecondary"-->
<!-- android:textSize="14sp"-->
<!-- android:textStyle="bold"-->
<!-- android:visibility="gone" />-->
<!-- </LinearLayout>-->
<!--</RelativeLayout>-->
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>

<resources>
<string name="remoteAccessConsumerKey">3MVG9.AgwtoIvERSd8i8lePrqfnKG_MM7P9KAJ4g53iaPA4EN8zUt3__o.8YA_hCeRn_kGR.Xe9I9_pnsFuAW</string>
<string name="oauthRedirectURI">mobilesdk://android/pn/tester</string>
<string name="remoteAccessConsumerKey">3MVG98dostKihXN53TYStBIiS8FC2a3tE3XhGId0hQ37iQjF0xe4fxMSb2mFaWZn9e3GiLs1q67TNlyRji.Xw</string>
<string name="oauthRedirectURI">testsfdc:///mobilesdk/detect/oauth/done</string>
<string-array name="oauthScopes">
<item>api</item>
<item>web</item>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,5 @@

<!-- Text for the "Log In With QR" button -->
<!-- Uncomment when enabling log in via Salesforce UI Bridge API generated QR codes -->
<string name="login_with_qr">Log In with QR</string>

<!-- <string name="login_with_qr">Log In with QR</string> -->
</resources>
Loading

0 comments on commit 3049445

Please sign in to comment.