-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from icerockdev/develop
Release 0.1.0
- Loading branch information
Showing
42 changed files
with
1,905 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
name: KMP library compilation check | ||
|
||
on: | ||
pull_request: | ||
branches: | ||
- master | ||
- develop | ||
|
||
jobs: | ||
build: | ||
runs-on: macOS-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v1 | ||
- name: Set up JDK 1.8 | ||
uses: actions/setup-java@v1 | ||
with: | ||
java-version: 1.8 | ||
- name: Check build | ||
run: ./gradlew build publishToMavenLocal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
name: KMP library publish | ||
|
||
on: | ||
release: | ||
types: [published] | ||
|
||
jobs: | ||
build: | ||
runs-on: macOS-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v1 | ||
- name: Set up JDK 1.8 | ||
uses: actions/setup-java@v1 | ||
with: | ||
java-version: 1.8 | ||
- name: Publish | ||
run: ./gradlew publishAllPublicationsToBintrayRepository -DBINTRAY_USER=${{ secrets.BINTRAY_USER }} -DBINTRAY_KEY=${{ secrets.BINTRAY_KEY }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
|
||
plugins { | ||
plugin(Deps.Plugins.androidLibrary) | ||
plugin(Deps.Plugins.kotlinMultiPlatform) | ||
plugin(Deps.Plugins.androidExtensions) | ||
plugin(Deps.Plugins.mobileMultiPlatform) | ||
plugin(Deps.Plugins.mavenPublish) | ||
} | ||
|
||
group = "dev.icerock.moko" | ||
version = Deps.mokoBiometryVersion | ||
|
||
dependencies { | ||
androidLibrary(Deps.Libs.Android.appCompat) | ||
androidLibrary(Deps.Libs.Android.biometric) | ||
|
||
mppLibrary(Deps.Libs.MultiPlatform.mokoResources) | ||
} | ||
|
||
|
||
publishing { | ||
repositories.maven("https://api.bintray.com/maven/icerockdev/moko/moko-biometry/;publish=1") { | ||
name = "bintray" | ||
|
||
credentials { | ||
username = System.getProperty("BINTRAY_USER") | ||
password = System.getProperty("BINTRAY_KEY") | ||
} | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest package="dev.icerock.moko.biometry" /> |
177 changes: 177 additions & 0 deletions
177
biometry/src/androidMain/kotlin/dev/icerock/moko/biometry/BiometryAuthenticator.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
/* | ||
* Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
|
||
package dev.icerock.moko.biometry | ||
|
||
import android.content.pm.PackageManager | ||
import android.os.Build | ||
import androidx.biometric.BiometricConstants | ||
import androidx.biometric.BiometricPrompt | ||
import androidx.core.content.ContextCompat | ||
import androidx.fragment.app.Fragment | ||
import androidx.fragment.app.FragmentManager | ||
import androidx.lifecycle.Lifecycle | ||
import androidx.lifecycle.LifecycleObserver | ||
import androidx.lifecycle.LifecycleOwner | ||
import androidx.lifecycle.OnLifecycleEvent | ||
import dev.icerock.moko.resources.desc.StringDesc | ||
import dev.icerock.moko.resources.desc.desc | ||
import java.util.concurrent.Executor | ||
import kotlin.coroutines.suspendCoroutine | ||
|
||
actual class BiometryAuthenticator actual constructor() { | ||
|
||
var fragmentManager: FragmentManager? = null | ||
private var _packageManager: PackageManager? = null | ||
|
||
fun bind(lifecycle: Lifecycle, fragmentManager: FragmentManager) { | ||
this.fragmentManager = fragmentManager | ||
|
||
val observer = object : LifecycleObserver { | ||
|
||
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) | ||
fun onDestroyed(source: LifecycleOwner) { | ||
this@BiometryAuthenticator.fragmentManager = null | ||
source.lifecycle.removeObserver(this) | ||
} | ||
} | ||
lifecycle.addObserver(observer) | ||
} | ||
|
||
fun setPackageManager(packageManager: PackageManager) { | ||
this._packageManager = packageManager | ||
} | ||
|
||
actual suspend fun checkBiometryAuthentication( | ||
requestReason: StringDesc, | ||
failureButtonText: StringDesc): Boolean { | ||
|
||
val fragmentManager = | ||
fragmentManager | ||
?: throw IllegalStateException("can't check biometry without active window") | ||
|
||
val currentFragment: Fragment? = fragmentManager.findFragmentByTag(BIOMETRY_RESOLVER_FRAGMENT_TAG) | ||
val resolverFragment: ResolverFragment = if (currentFragment != null) { | ||
currentFragment as ResolverFragment | ||
} else { | ||
ResolverFragment().apply { | ||
fragmentManager | ||
.beginTransaction() | ||
.add(this, BIOMETRY_RESOLVER_FRAGMENT_TAG) | ||
.commitNow() | ||
} | ||
} | ||
|
||
return suspendCoroutine<Boolean> { continuation -> | ||
var resumed = false | ||
resolverFragment.showBiometricPrompt( | ||
requestTitle = "Biometry".desc(), | ||
requestReason = requestReason, | ||
failureButtonText = failureButtonText, | ||
credentialAllowed = true | ||
) { | ||
if (!resumed) { | ||
continuation.resumeWith(it) | ||
resumed = true | ||
} | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Performs a fingerprint scan availability check | ||
* | ||
* @return true if it is possible to use a fingerprint scanner, false - if it is not available | ||
*/ | ||
actual fun isTouchIdEnabled(): Boolean { | ||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { | ||
return false | ||
} | ||
return _packageManager?.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT) | ||
?: throw IllegalStateException("can't check touch id enabled without packageManager") | ||
} | ||
|
||
/** | ||
* Performs the availability check of the FaceID scan | ||
* | ||
* @return true if it is possible to use the face scanner, false - if it is not available | ||
*/ | ||
actual fun isFaceIdEnabled(): Boolean { | ||
return false | ||
} | ||
|
||
class ResolverFragment : Fragment() { | ||
|
||
private lateinit var executor: Executor | ||
private lateinit var biometricPrompt: BiometricPrompt | ||
private lateinit var promptInfo: BiometricPrompt.PromptInfo | ||
|
||
init { | ||
retainInstance = true | ||
} | ||
|
||
/** | ||
* Prepare and show BiometricPrompt system dialog | ||
* | ||
* @param requestTitle biometric prompt title | ||
* @param requestReason biometric prompt reason | ||
* @param failureButtonText | ||
* @param credentialAllowed Allows user to authenticate using their lock screen PIN, pattern, or password. | ||
*/ | ||
fun showBiometricPrompt( | ||
requestTitle: StringDesc, | ||
requestReason: StringDesc, | ||
failureButtonText: StringDesc, | ||
credentialAllowed: Boolean, | ||
callback: (Result<Boolean>) -> Unit | ||
) { | ||
val context = requireContext() | ||
|
||
executor = ContextCompat.getMainExecutor(context) | ||
|
||
biometricPrompt = BiometricPrompt(this, executor, | ||
object : BiometricPrompt.AuthenticationCallback() { | ||
override fun onAuthenticationError(errorCode: Int, | ||
errString: CharSequence) { | ||
super.onAuthenticationError(errorCode, errString) | ||
if (errorCode == BiometricConstants.ERROR_NEGATIVE_BUTTON) { | ||
callback.invoke(Result.failure(Exception(errorCode.toString()))) | ||
} else { | ||
callback.invoke(Result.failure(Exception(errString.toString()))) | ||
} | ||
} | ||
|
||
override fun onAuthenticationSucceeded( | ||
result: BiometricPrompt.AuthenticationResult) { | ||
super.onAuthenticationSucceeded(result) | ||
callback.invoke(Result.success(true)) | ||
} | ||
|
||
override fun onAuthenticationFailed() { | ||
super.onAuthenticationFailed() | ||
callback.invoke(Result.success(false)) | ||
} | ||
} | ||
) | ||
|
||
promptInfo = BiometricPrompt.PromptInfo.Builder() | ||
.setTitle(requestTitle.toString(context)) | ||
.setSubtitle(requestReason.toString(context)) | ||
.apply { | ||
if (!credentialAllowed) { | ||
this.setNegativeButtonText(failureButtonText.toString(context)) | ||
} | ||
} | ||
.setDeviceCredentialAllowed(credentialAllowed) | ||
.build() | ||
|
||
biometricPrompt.authenticate(promptInfo) | ||
} | ||
} | ||
|
||
companion object { | ||
private const val BIOMETRY_RESOLVER_FRAGMENT_TAG = "BiometryControllerResolver" | ||
} | ||
|
||
} |
42 changes: 42 additions & 0 deletions
42
biometry/src/commonMain/kotlin/dev/icerock/moko/biometry/BiometryAuthenticator.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* | ||
* Copyright 2021 IceRock MAG Inc. Use of this source code is governed by the Apache 2.0 license. | ||
*/ | ||
|
||
package dev.icerock.moko.biometry | ||
|
||
import dev.icerock.moko.resources.desc.StringDesc | ||
|
||
expect class BiometryAuthenticator() { | ||
|
||
/** | ||
* Performs user authentication using biometrics-fingerprint/face scan-returns the result of the scan | ||
* | ||
* @param requestReason - Text describing the reason for confirmation via biometrics | ||
* @param failureButtonText - Text of the button to go to the backup verification method in case of unsuccessful biometrics recognition | ||
* | ||
* @throws Exception if authentication failed | ||
* | ||
* @return true for successful confirmation of biometrics, false for unsuccessful confirmation | ||
*/ | ||
|
||
suspend fun checkBiometryAuthentication( | ||
requestReason: StringDesc, | ||
failureButtonText: StringDesc | ||
): Boolean | ||
|
||
/** | ||
* Performs a fingerprint scan availability check | ||
* | ||
* @return true if it is possible to use a fingerprint scanner, false - if it is not available | ||
*/ | ||
|
||
fun isTouchIdEnabled(): Boolean | ||
|
||
/** | ||
* Performs the availability check of the FaceID scan | ||
* | ||
* @return true if it is possible to use the face scanner, false - if it is not available | ||
*/ | ||
|
||
fun isFaceIdEnabled(): Boolean | ||
} |
Oops, something went wrong.