-4

In my mobile application, I have created a separate class file to implement the BiometricManager and BiometricPrompt to use the fingerprint authentication. I have to trigger the Biometric popup in three activities, so I created a common function in separate class file. But the BiometricPrompt object has three parameters such as activity, executor & authentication callback. If I pass the Login activity object (in below code) then it is throwing an error as "Your activity is not yet attached to the Application instance. You can't request ViewModel before onCreate call". Can somebody please help to fix this issue. Thanks in advance.

NewLoginActivity newLoginActivity = new NewLoginActivity();
BiometricManager biometricManager = BiometricManager.from(context);
switch (biometricManager.canAuthenticate(BIOMETRIC_STRONG | DEVICE_CREDENTIAL)) {
    case BiometricManager.BIOMETRIC_SUCCESS:
        Log.d("MY_APP_TAG", "App can authenticate using biometrics.");
        break;
    case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
        Log.e("MY_APP_TAG", "No biometric features available on this device.");
        break;
    case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE:
        Log.e("MY_APP_TAG", "Biometric features are currently unavailable.");
        break;
    case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
        // Prompts the user to create credentials that your app accepts.
        final Intent enrollIntent = new Intent(Settings.ACTION_BIOMETRIC_ENROLL);
        enrollIntent.putExtra(Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED,
                BIOMETRIC_STRONG | DEVICE_CREDENTIAL);
        startActivityForResult(enrollIntent, REQUEST_CODE);
        break;
}

executor = ContextCompat.getMainExecutor(context);
biometricPrompt = new BiometricPrompt(newLoginActivity,
        executor, new BiometricPrompt.AuthenticationCallback() {
    @Override
    public void onAuthenticationError(int errorCode,
                                      @NonNull CharSequence errString) {
        super.onAuthenticationError(errorCode, errString);
        Toast.makeText(getApplicationContext(),
                "Authentication error: " + errString, Toast.LENGTH_SHORT)
                .show();
    }

    @Override
    public void onAuthenticationSucceeded(
            @NonNull BiometricPrompt.AuthenticationResult result) {
        super.onAuthenticationSucceeded(result);
        Toast.makeText(getApplicationContext(),
                "Authentication succeeded!", Toast.LENGTH_SHORT).show();
        authErrorStatus.setVisibility(View.GONE);
        login();
    }

    @Override
    public void onAuthenticationFailed() {
        super.onAuthenticationFailed();
        Toast.makeText(getApplicationContext(), "Authentication failed",
                Toast.LENGTH_SHORT)
                .show();
    }
});

promptInfo = new BiometricPrompt.PromptInfo.Builder()
        .setTitle("Biometric login for my app")
        .setSubtitle("Log in using your biometric credential")
        .setNegativeButtonText("Use account password")
        .build();

Please check the below log error I got in logcat.

2021-05-11 12:21:21.245 6808-6808/com.purchasingpower.ppow E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.purchasingpower.ppow, PID: 6808
    java.lang.IllegalStateException: Your activity is not yet attached to the Application instance. You can't request ViewModel before onCreate call.
        at androidx.activity.ComponentActivity.getViewModelStore(ComponentActivity.java:263)
        at androidx.lifecycle.ViewModelProvider.<init>(ViewModelProvider.java:99)
        at androidx.biometric.BiometricPrompt.getViewModel(BiometricPrompt.java:1027)
        at androidx.biometric.BiometricPrompt.<init>(BiometricPrompt.java:844)
        at com.app.purchasingpower.utility.BiometricHandler.checkBiometricSensor(BiometricHandler.java:109)
        at com.app.purchasingpower.activity.NewLoginActivity.checkFingerprintSensor(NewLoginActivity.java:861)
        at com.app.purchasingpower.activity.NewLoginActivity.access$2900(NewLoginActivity.java:92)
        at com.app.purchasingpower.activity.NewLoginActivity$6.onCallback(NewLoginActivity.java:802)
        at com.app.purchasingpower.activity.NewLoginActivity$1.onCallback(NewLoginActivity.java:324)
        at com.app.purchasingpower.volley.JsonObjectResponseController$1$1.onResponse(JsonObjectResponseController.java:131)
        at com.app.purchasingpower.volley.JsonObjectResponseController$1$1.onResponse(JsonObjectResponseController.java:127)
        at com.android.volley.toolbox.JsonRequest.deliverResponse(JsonRequest.java:83)
        at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:106)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
2021-05-11 12:21:21.282 6808-6808/com.purchasingpower.ppow I/Process: Sending signal. PID: 6808 SIG: 9
4

1 回答 1

1

您正在创建Activity自己的实例:

NewLoginActivity newLoginActivity = new NewLoginActivity();

您永远不应该Activity在 Android 中创建实例。系统将始终为您创建它。

解决方案取决于这段代码的位置:如果它在FragmentActivity子类中,只需传递this. 如果它在 a 中Fragment,则通过getActivity()。如果它在另一个类中,您需要将FragmentActivity作为参数传递给该类,以便您可以将它传递给BiometricPrompt.

于 2021-05-13T04:11:44.773 回答