Skip to content
This repository has been archived by the owner on Feb 23, 2021. It is now read-only.

Display Touch ID dialog on Android (if supported) #1312

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
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
3 changes: 2 additions & 1 deletion mobile/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,9 @@ dependencies {
implementation project(':react-native-svg')
implementation project(':react-native-gesture-handler')
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
implementation "com.android.support:support-annotations:${rootProject.ext.supportLibVersion}"
implementation "com.facebook.react:react-native:+" // From node_modules
implementation 'androidx.biometric:biometric:1.0.0-alpha03'
// Add v8-android - prebuilt libv8.so into APK
implementation 'org.chromium:v8-android:+'
addUnimodulesDependencies()
Expand Down
1 change: 1 addition & 0 deletions mobile/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<!-- OPTIONAL PERMISSIONS, REMOVE WHATEVER YOU DO NOT NEED -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.VIBRATE" />

<!-- These require runtime permissions on M -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.lightningapp;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import java.util.concurrent.Executors;
import androidx.biometric.BiometricPrompt;

public class FingerprintDialogModule extends ReactContextBaseJavaModule {
public FingerprintDialogModule(ReactApplicationContext reactContext) {
super(reactContext); //required by React Native
}

@Override
//getName is required to define the name of the module represented in JavaScript
public String getName() {
return "FingerprintDialog";
}

@ReactMethod
public void getBiometricPrompt() {
val executor = Executors.newSingleThreadExecutor();
BiometricPrompt.Builder()
.setTitle("Use your fingerprint to unlock")
.setSubtitle("Lightning App requires authentication to continue")
.setDescription("Use your fingerprint to unlock the app or press cancel and enter in your pin")
.setNegativeButton("Cancel")
.build();
}
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will likely add an error handler, (and possibly a success handler) to this file after seeing how it behaves as it.

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.lightningapp;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import com.lightningapp.FingerprintDialogModule;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class FingerprintDialogPackage implements ReactPackage {

@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}

@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
//this is where you register the module
modules.add(new FingerprintDialogModule(reactContext));
return modules;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ protected List<ReactPackage> getPackages() {
new SvgPackage(),
new RNGestureHandlerPackage(),
new ModuleRegistryAdapter(mModuleRegistryProvider),
new LndNativePackage()
new LndNativePackage(),
new FingerprintDialogPackage()
);
}

Expand Down
2 changes: 2 additions & 0 deletions mobile/android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
android.useAndroidX=true
android.enableJetifier=true
148 changes: 74 additions & 74 deletions mobile/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion mobile/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"start": "react-native start"
},
"dependencies": {
"expo-constants": "^7.0.0",
"expo-font": "^6.0.1",
"expo-keep-awake": "^6.0.0",
"expo-local-authentication": "^6.0.0",
Expand All @@ -28,7 +29,7 @@
"react-native-picker-select": "^6.3.2",
"react-native-share": "^1.2.1",
"react-native-svg": "^9.6.2",
"react-native-unimodules": "^0.5.4",
"react-native-unimodules": "^0.7.0-rc.1",
"react-native-v8": "^0.59.10-patch.1",
"react-navigation": "^3.11.1"
},
Expand Down
11 changes: 8 additions & 3 deletions src/action/auth-mobile.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,20 @@ class AuthAction {
// TouchID & KeyStore Authentication
//

async checkFingerprintHardwareAndEnrollment() {
const hasHardware = await this._Fingerprint.hasHardwareAsync();
const isEnrolled = await this._Fingerprint.isEnrolledAsync();
return hasHardware && isEnrolled ? true : false;
}

/**
* Try authenticating the user using either via TouchID/FaceID on iOS
* or a fingerprint reader on Android.
* @return {Promise<undefined>}
*/
async tryFingerprint() {
const hasHardware = await this._Fingerprint.hasHardwareAsync();
const isEnrolled = await this._Fingerprint.isEnrolledAsync();
if (!hasHardware || !isEnrolled) {
const hasFingerprint = await this.checkFingerprintHardwareAndEnrollment();
if (!hasFingerprint) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice refactor 👍

return;
}
const msg = 'Unlock your Wallet';
Expand Down
8 changes: 7 additions & 1 deletion src/view/pin-mobile.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { View, StyleSheet } from 'react-native';
import { NativeModules, View, StyleSheet } from 'react-native';
import { observer } from 'mobx-react';
import PropTypes from 'prop-types';
import Background from '../component/background';
Expand Down Expand Up @@ -37,6 +37,12 @@ class PinView extends React.Component {

render() {
const { store, auth } = this.props;
const FingerprintDialog = NativeModules.FingerprintDialog;
const hasActiveFingerprint = this.props.auth.checkFingerprintHardwareAndEnrollment();

if (hasActiveFingerprint) {
FingerprintDialog.getBiometricPrompt();
}
return (
<Background image="purple-gradient-bg">
<MainContent style={styles.content}>
Expand Down