对于背景,这是this上一个问题的延续,建议采用以下方法。
我正在实现下面的本机 Android 代码来调用生物识别身份验证,并使用设备引脚/图案/密码作为备份。我在 android studio 中使用了以下代码,它适用于模拟器和物理设备。本质上,设备身份验证是在应用程序启动时启动的。
主要活动:-
package com.example.deviceauthentication;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.biometric.BiometricPrompt;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Toast;
import java.util.concurrent.Executor;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
BiometricFragment biometricFragment = BiometricFragment.newInstance();
getSupportFragmentManager().beginTransaction()
.add(R.id.containerId, biometricFragment, "biometric_fragment")
.commit();
}
}
生物识别片段类:-
package com.example.deviceauthentication;
import android.os.Build;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.biometric.BiometricManager;
import androidx.fragment.app.Fragment;
import androidx.biometric.BiometricPrompt;
import android.util.Log;
import java.util.concurrent.Executor;
import androidx.annotation.NonNull;
public class BiometricFragment extends Fragment {
private Executor executor;
private BiometricPrompt biometricPrompt;
private BiometricPrompt.PromptInfo promptInfo;
// Default constructor
public BiometricFragment() {
// Required empty public constructor
}
// Factory method to create a new instance of the fragment
public static BiometricFragment newInstance() {
return new BiometricFragment();
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
startBiometricAuthentication();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
executor = getActivity().getMainExecutor();
}
}
// Method to start the biometric authentication process
public void startBiometricAuthentication() {
biometricPrompt = new BiometricPrompt(this, executor, new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
Log.e("BiometricFragment", "Authentication error: " + errString);
Log.d("CALLBACK", "*****************False******************");
}
@Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
Log.d("BiometricFragment", "Authentication succeeded 2");
Log.d("CALLBACK", "*****************True******************");
// Authentication succeeded, you can perform further actions here
}
@Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
Log.e("BiometricFragment", "Authentication failed");
Log.d("CALLBACK", "*****************False******************");
}
});
promptInfo = new BiometricPrompt.PromptInfo.Builder()
.setTitle("Biometric Authentication")
.setSubtitle("Authenticate using your biometric data")
.setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_WEAK | BiometricManager.Authenticators.BIOMETRIC_STRONG | BiometricManager.Authenticators.DEVICE_CREDENTIAL)
.build();
biometricPrompt.authenticate(promptInfo);
}
}
我看到 4 个构建错误:-
Compiling with JDK Java compiler API.Compiling with JDK Java compiler API.
/tmp/build3217451114737202177xxx/MavenTestNew/src/main/java/com/jamesco/maventestnew/MyNativeImpl.java:28: error: cannot find symbol/tmp/build3217451114737202177xxx/MavenTestNew/src/main/java/com/jamesco/maventestnew/MyNativeImpl.java:28: error: cannot find symbol
.add(R.id.containerId, biometricFragment, "biometric_fragment") .add(R.id.containerId, biometricFragment, "biometric_fragment")
^ ^
symbol: variable containerId symbol: variable containerId
location: class id location: class id
/tmp/build3217451114737202177xxx/MavenTestNew/src/main/java/com/jamesco/maventestnew/MyNativeImpl.java:27: error: cannot find symbol/tmp/build3217451114737202177xxx/MavenTestNew/src/main/java/com/jamesco/maventestnew/MyNativeImpl.java:27: error: cannot find symbol
getSupportFragmentManager().beginTransaction() getSupportFragmentManager().beginTransaction()
^ ^
symbol: method getSupportFragmentManager() symbol: method getSupportFragmentManager()
location: class MyNativeImpl location: class MyNativeImpl
/tmp/build3217451114737202177xxx/MavenTestNew/src/main/java/com/jamesco/maventestnew/MyNativeImpl.java:59: error: non-static variable this cannot be referenced from a static context/tmp/build3217451114737202177xxx/MavenTestNew/src/main/java/com/jamesco/maventestnew/MyNativeImpl.java:59: error: non-static variable this cannot be referenced from a static context
return new BiometricFragment(); return new BiometricFragment();
^ ^
/tmp/build3217451114737202177xxx/MavenTestNew/src/main/java/com/jamesco/maventestnew/MyNativeImpl.java:58: error: Illegal static declaration in inner class MyNativeImpl.BiometricFragment/tmp/build3217451114737202177xxx/MavenTestNew/src/main/java/com/jamesco/maventestnew/MyNativeImpl.java:58: error: Illegal static declaration in inner class MyNativeImpl.BiometricFragment
public static BiometricFragment newInstance() { public static BiometricFragment newInstance() {
^ ^
modifier 'static' is only allowed in constant variable declarations modifier 'static' is only allowed in constant variable declarations
Note: Some input files use or override a deprecated API.Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.Note: Recompile with -Xlint:deprecation for details.
Note: Some input files use unchecked or unsafe operations.Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.Note: Recompile with -Xlint:unchecked for details.
4 errors4 errors
Task :compileDebugJavaWithJavac in MavenTestNew FinishedTask :compileDebugJavaWithJavac in MavenTestNew Finished
> Task :compileDebugJavaWithJavac> Task :compileDebugJavaWithJavac FAILED FAILED
:compileDebugJavaWithJavac (Thread[Execution worker for ':',5,main]) completed. Took 5.852 secs.:compileDebugJavaWithJavac (Thread[Execution worker for ':',5,main]) completed. Took 5.852 secs.
AAPT2 aapt2-4.1.1-6503028-linux Daemon #0: shutdownAAPT2 aapt2-4.1.1-6503028-linux Daemon #0: shutdown
AAPT2 aapt2-4.1.1-6503028-linux Daemon #1: shutdownAAPT2 aapt2-4.1.1-6503028-linux Daemon #1: shutdown
AAPT2 aapt2-4.1.1-6503028-linux Daemon #2: shutdownAAPT2 aapt2-4.1.1-6503028-linux Daemon #2: shutdown
AAPT2 aapt2-4.1.1-6503028-linux Daemon #3: shutdownAAPT2 aapt2-4.1.1-6503028-linux Daemon #3: shutdown
FAILURE: FAILURE: Build failed with an exception.Build failed with an exception.
MyNative.java
package com.jamesco.maventestnew;
import com.codename1.system.NativeInterface;
public interface MyNative extends NativeInterface {
String helloWorld(String hi);
boolean nativeAuth();
public class BiometricFragment{}
}
MyNativeImpl.java
package com.jamesco.maventestnew;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.biometric.BiometricPrompt;
import androidx.core.content.ContextCompat;
import androidx.biometric.BiometricManager;
import androidx.biometric.BiometricPrompt;
import androidx.fragment.app.Fragment;
import android.os.Bundle;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.Toast;
import java.util.concurrent.Executor;
import com.codename1.impl.android.AndroidNativeUtil;
import android.os.Build;
import android.app.Activity;
public class MyNativeImpl {
public boolean nativeAuth(){
BiometricFragment biometricFragment = BiometricFragment.newInstance();
getSupportFragmentManager().beginTransaction()
.add(R.id.containerId, biometricFragment, "biometric_fragment")
.commit();
boolean AuthOK = false; //ignore this
return AuthOK; //ignore this
}
public class BiometricFragment extends Fragment {
private Executor executor;
private BiometricPrompt biometricPrompt;
private BiometricPrompt.PromptInfo promptInfo;
// Default constructor
public BiometricFragment() {
// Required empty public constructor
}
// Factory method to create a new instance of the fragment
public static BiometricFragment newInstance() {
return new BiometricFragment();
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
startBiometricAuthentication();
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// You can initialize variables or perform other setup here
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
executor = getActivity().getMainExecutor();
}
}
// Method to start the biometric authentication process
public void startBiometricAuthentication() {
biometricPrompt = new BiometricPrompt(this, executor, new BiometricPrompt.AuthenticationCallback() {
@Override
public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
Log.e("BiometricFragment", "Authentication error: " + errString);
Log.d("AUTHENTICATION", "*****************False******************");
}
@Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
Log.d("BiometricFragment", "Authentication succeeded 2");
Log.d("AUTHENTICATION", "*****************True******************");
// Authentication succeeded, you can perform further actions here
}
@Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
Log.e("BiometricFragment", "Authentication failed");
Log.d("AUTHENTICATION", "*****************False******************");
}
});
promptInfo = new BiometricPrompt.PromptInfo.Builder()
.setTitle("Biometric Authentication")
.setSubtitle("Authenticate using your biometric data")
.setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_WEAK | BiometricManager.Authenticators.BIOMETRIC_STRONG | BiometricManager.Authenticators.DEVICE_CREDENTIAL)
.build();
biometricPrompt.authenticate(promptInfo);
}
}
public String helloWorld(String param) {
Log.d("MyNewApp", param);
return "Tada Android";
}
public boolean isSupported() {
return true;
}
}
我需要指定片段应放置的容器视图 ID,这解释了第一个错误。我怎样才能克服这个问题?另外,如果能帮助解决其他错误,我们将不胜感激。
抱歉,我那里的代码引用了我复制的
R
类。这不适用于标准 Codename One 类,因为它需要 XML 布局代码。更好的方法是从代码构造片段:
public class JavaFragment extends Fragment {
@NonNull
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
// Create a LinearLayout
LinearLayout layout = new LinearLayout(getActivity());
layout.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
layout.setOrientation(LinearLayout.VERTICAL);
// Add a TextView
TextView textView = new TextView(getActivity());
textView.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT));
textView.setText("Fragment created entirely in Java!");
layout.addView(textView);
return layout;
}
}
这将创建一个您可以使用的 Fragment 组件。
重要提示:我建议发送一个已注释掉错误代码的构建版本,并在 Android Studio 中使用生成的项目源代码。这将为您提供代码补全并检查编译是否有效。它将使您免于发送构建进行测试的周期。一旦编译并运行它,您只需将本机代码复制回 Codename One 即可。