Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FR-18338.3 #86

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion android/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
</activity>

<service
android:name="com.frontegg.android.services.RefreshTokenService"
android:name="com.frontegg.android.services.RefreshTokenJobService"
android:exported="true"
android:permission="android.permission.BIND_JOB_SERVICE">
<intent-filter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,15 @@ import android.net.Uri
import android.os.Bundle
import android.util.Log
import androidx.browser.customtabs.CustomTabsIntent
import com.frontegg.android.services.FronteggAuthService
import com.frontegg.android.services.FronteggInnerStorage
import com.frontegg.android.EmbeddedAuthActivity.Companion
import com.frontegg.android.services.FronteggAppService
import com.frontegg.android.utils.AuthorizeUrlGenerator

class AuthenticationActivity : Activity() {

var customTabLaunched = false
private val storage = FronteggInnerStorage()
private var customTabLaunched = false
private fun startAuth(url: String) {
val builder = CustomTabsIntent.Builder()
builder.setShowTitle(true)
Expand Down Expand Up @@ -61,10 +64,10 @@ class AuthenticationActivity : Activity() {
val code = intent.data?.getQueryParameter("code")
if (code != null) {
Log.d(TAG, "Got intent with oauth callback")
FronteggAuth.instance.isLoading.value = true
FronteggAuthService.instance.isLoading.value = true

FronteggAuth.instance.handleHostedLoginCallback(code, null, this)
if (FronteggApp.getInstance().useChromeCustomTabs && FronteggApp.getInstance().isEmbeddedMode) {
FronteggAuthService.instance.handleHostedLoginCallback(code, null, this)
if (storage.useChromeCustomTabs && storage.isEmbeddedMode) {
EmbeddedAuthActivity.afterAuthentication(this)
} else {
invokeAuthFinishedCallback()
Expand All @@ -86,7 +89,7 @@ class AuthenticationActivity : Activity() {
* when using external browser login
*/
private fun invokeAuthFinishedCallback() {
if (FronteggApp.getInstance().isEmbeddedMode) {
if (FronteggAuth.instance.isEmbeddedMode) {
return
}
onAuthFinishedCallback?.invoke()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@ import android.webkit.WebView
import android.widget.LinearLayout
import com.frontegg.android.embedded.FronteggNativeBridge
import com.frontegg.android.embedded.FronteggWebView
import com.frontegg.android.services.FronteggAuthService
import com.frontegg.android.services.FronteggInnerStorage
import com.frontegg.android.utils.AuthorizeUrlGenerator
import com.frontegg.android.utils.NullableObject
import io.reactivex.rxjava3.disposables.Disposable
import io.reactivex.rxjava3.functions.Consumer
import org.json.JSONObject

class EmbeddedAuthActivity : Activity() {

lateinit var webView: FronteggWebView
private val storage = FronteggInnerStorage()
private lateinit var webView: FronteggWebView
private var webViewUrl: String? = null
private var directLoginLaunchedDone: Boolean = false
private var directLoginLaunched: Boolean = false
Expand All @@ -39,8 +41,8 @@ class EmbeddedAuthActivity : Activity() {

override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putBoolean(DIRECT_LOGIN_ACTION_LAUNCHED, this.directLoginLaunched);
outState.putBoolean(DIRECT_LOGIN_ACTION_LAUNCHED_DONE, this.directLoginLaunchedDone);
outState.putBoolean(DIRECT_LOGIN_ACTION_LAUNCHED, this.directLoginLaunched)
outState.putBoolean(DIRECT_LOGIN_ACTION_LAUNCHED_DONE, this.directLoginLaunchedDone)
}

private fun consumeIntent(intent: Intent) {
Expand Down Expand Up @@ -127,7 +129,7 @@ class EmbeddedAuthActivity : Activity() {
}

private fun navigateToAuthenticated() {
val mainActivityClass = FronteggApp.getInstance().mainActivityClass
val mainActivityClass = storage.mainActivityClass
if (mainActivityClass != null) {
val intent = Intent(this, mainActivityClass)
startActivity(intent)
Expand All @@ -147,8 +149,8 @@ class EmbeddedAuthActivity : Activity() {
if (directLoginLaunchedDone) {
onAuthFinishedCallback?.invoke()
onAuthFinishedCallback = null
FronteggAuth.instance.isLoading.value = false
FronteggAuth.instance.showLoader.value = false
FronteggAuthService.instance.isLoading.value = false
FronteggAuthService.instance.showLoader.value = false
setResult(RESULT_OK)
finish()
return
Expand Down
159 changes: 57 additions & 102 deletions android/src/main/java/com/frontegg/android/FronteggApp.kt
Original file line number Diff line number Diff line change
@@ -1,60 +1,55 @@
package com.frontegg.android

import android.annotation.SuppressLint
import android.content.ComponentName
import android.content.Context
import android.content.pm.PackageManager.MATCH_ALL
import android.os.Handler
import android.util.Log
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.ProcessLifecycleOwner
import com.frontegg.android.FronteggApp.Companion.init
import com.frontegg.android.FronteggApp.Companion.initWithRegions
import com.frontegg.android.exceptions.FronteggException
import com.frontegg.android.exceptions.FronteggException.Companion.FRONTEGG_APP_MUST_BE_INITIALIZED
import com.frontegg.android.regions.RegionConfig
import com.frontegg.android.services.*
import java.time.Instant

class FronteggApp private constructor(
val context: Context,
var baseUrl: String,
var clientId: String,
var applicationId: String?,
val isEmbeddedMode: Boolean = true,
val regions: List<RegionConfig> = listOf(),
val selectedRegion: RegionConfig? = null,
var handleLoginWithSocialLogin: Boolean = true,
var customUserAgent: String? = null,
var handleLoginWithSSO: Boolean = false,
var shouldPromptSocialLoginConsent: Boolean = true,
val useAssetsLinks: Boolean = false,
var useChromeCustomTabs: Boolean = false,
var mainActivityClass: Class<*>? = null
) {

val credentialManager: CredentialManager = CredentialManager(context)
val auth: FronteggAuth =
FronteggAuth(baseUrl, clientId, applicationId, credentialManager, regions, selectedRegion)
val packageName: String = context.packageName
var appInForeground = true

var lastJobStart: Long = Instant.now().toEpochMilli();
import com.frontegg.android.services.CredentialManager
import com.frontegg.android.services.FronteggAppService
import com.frontegg.android.utils.isActivityEnabled

/**
* An initialization class of Frontegg SDK. Use [init] or [initWithRegions] static methods
* to initialize the [FronteggApp]. To get access to an instance use the [getInstance] method.
*
* @property auth an authentication interface.
*/
interface FronteggApp {
val auth: FronteggAuth

companion object {

@SuppressLint("StaticFieldLeak")
private var instance: FronteggApp? = null

public val TAG: String = FronteggApp::class.java.simpleName

public fun getInstance(): FronteggApp {
/**
* Provide [FronteggApp] instance.
* @return [FronteggApp] object if was initialized.
* @throws FronteggException with the message `frontegg.error.app_must_be_initialized`
* if FronteggApp wasn't initialized before. Use `init` or `initWithRegions` static methods
* to initialize the FronteggApp.
*/
fun getInstance(): FronteggApp {
if (instance == null) {
throw FronteggException(FRONTEGG_APP_MUST_BE_INITIALIZED)
}
return instance!!
}

public fun init(
/**
* Initialization method of [FronteggApp].
* @param fronteggDomain is the Frontegg domain. Could be found at portal.frontegg.com;
* @param clientId is the Frontegg Client ID. Could be found at portal.frontegg.com;
* @param context is the application context;
* @param applicationId is the id of Frontegg application. Could be found at portal.frontegg.com;
* @param useAssetsLinks is the flag which says if Frontegg SDK uses assets links;
* @param useChromeCustomTabs is the flag which says if Frontegg SDK uses chrome custom tabs;
* @param mainActivityClass is the MainActivity.
*/
fun init(
fronteggDomain: String,
clientId: String,
context: Context,
Expand All @@ -69,11 +64,9 @@ class FronteggApp private constructor(
"https://$fronteggDomain"
}

val isEmbeddedMode = isActivityEnabled(context, EmbeddedAuthActivity::class.java.name)
val isEmbeddedMode = context.isActivityEnabled(EmbeddedAuthActivity::class.java.name)



instance = FronteggApp(
instance = FronteggAppService(
context = context,
baseUrl = baseUrl,
clientId = clientId,
Expand All @@ -83,27 +76,31 @@ class FronteggApp private constructor(
useChromeCustomTabs = useChromeCustomTabs,
mainActivityClass = mainActivityClass
)

Handler(context.mainLooper).post {
ProcessLifecycleOwner.get().lifecycle.addObserver(lifecycleEventObserver)
}
}

public fun initWithRegions(
/**
* Initialization method of [FronteggApp] for multi-regions.
* @param regions is a list of [RegionConfig]. Could find at portal.frontegg.com;
* @param context is the application context;
* @param useAssetsLinks is the flag which says if Frontegg SDK uses assets links;
* @param useChromeCustomTabs is the flag which says if Frontegg SDK uses chrome custom tabs;
* @param mainActivityClass is the MainActivity.
*/
fun initWithRegions(
regions: List<RegionConfig>,
context: Context,
useAssetsLinks: Boolean = false,
useChromeCustomTabs: Boolean = false,
mainActivityClass: Class<*>? = null
): FronteggApp {

val isEmbeddedMode = isActivityEnabled(context, EmbeddedAuthActivity::class.java.name)
val isEmbeddedMode = context.isActivityEnabled(EmbeddedAuthActivity::class.java.name)
val selectedRegion = CredentialManager(context).getSelectedRegion()
if (selectedRegion != null) {
val regionConfig = regions.find { it.key == selectedRegion }

if (regionConfig != null) {
val newInstance = FronteggApp(
val newInstance = FronteggAppService(
context = context,
baseUrl = regionConfig.baseUrl,
clientId = regionConfig.clientId,
Expand All @@ -119,7 +116,7 @@ class FronteggApp private constructor(
return newInstance
}
}
val newInstance = FronteggApp(
val newInstance = FronteggAppService(
context = context,
baseUrl = "",
clientId = "",
Expand All @@ -133,57 +130,15 @@ class FronteggApp private constructor(
instance = newInstance
return newInstance
}

private var lifecycleEventObserver = LifecycleEventObserver { _, event ->
when (event) {
Lifecycle.Event.ON_STOP -> {
Log.d(TAG, "ON_STOP")
getInstance().appInForeground = false
getInstance().auth.refreshTokenWhenNeeded()
}

Lifecycle.Event.ON_START -> {
Log.d(TAG, "ON_START")
getInstance().appInForeground = true
getInstance().auth.refreshTokenWhenNeeded()
}

else -> {}
}
}

private fun isActivityEnabled(context: Context, activityClassName: String): Boolean {
return try {
val componentName = ComponentName(context, activityClassName)
val packageManager = context.packageManager
packageManager.getActivityInfo(componentName, MATCH_ALL).isEnabled
} catch (e: Exception) {
false
}
}
}

fun initWithRegion(regionKey: String) {
if (this.regions.isEmpty()) {
throw RuntimeException("illegal state. Frontegg.plist does not contains regions array")
}

val keys = this.regions.joinToString(",") { it.key }

val config = regions.find { it.key == regionKey }
?: throw RuntimeException("invalid region key ${regionKey}. available regions: $keys")


credentialManager.saveSelectedRegion(regionKey)

this.baseUrl = config.baseUrl
this.clientId = config.clientId
this.applicationId = config.applicationId
this.auth.reinitWithRegion(config)


Log.i(TAG, "Frontegg Initialized successfully (region: ${regionKey})")
}


}
/**
* The switch method of the region by [regionKey].
* To use this method you should initialize the [FronteggApp] with
* the [initWithRegions] static method.
* @param regionKey is one of the key of regions you pass into [initWithRegions].
* @throws RuntimeException if you didn't pass any regions to [initWithRegions]
* or [regionKey] does not exist in the regions.
*/
fun initWithRegion(regionKey: String)
}
Loading
Loading