java.lang.NoSuchMethodError error for setDeviceCredentialAllowed() - android

I am trying to create an authentication system for my App.
When I compile the code, Android Studio throws the following error
java.lang.NoSuchMethodError: No virtual method setDeviceCredentialAllowed(Z)Landroid/hardware/biometrics/BiometricPrompt$Builder; in class Landroid/hardware/biometrics/BiometricPrompt$Builder; or its super classes (declaration of 'android.hardware.biometrics.BiometricPrompt$Builder' appears in /system/framework/framework.jar)
I followed some other possible solutions such as Invalidating Caches and Restarting my Android Studio but it didn't solve the issue
I am using
androidx.biometric:biometric:1.0.0-alpha03
KeyguardManager keyguardManager = (KeyguardManager) getApplication().getSystemService(KEYGUARD_SERVICE);
if(keyguardManager.isKeyguardSecure()){
Toast.makeText(this,"Using keyguard",Toast.LENGTH_SHORT).show();
Builder biometricPromptBuilder = new Builder(this);
biometricPromptBuilder.setTitle("Title");
biometricPromptBuilder.setSubtitle("Subtitle");
biometricPromptBuilder.setDescription("Discription");
biometricPromptBuilder.setNegativeButton("Cancel", newExecutor, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
biometricPromptBuilder.setDeviceCredentialAllowed(true);
android.hardware.biometrics.BiometricPrompt biometricPrompt = biometricPromptBuilder.build();
CancellationSignal cancellationSignal = new CancellationSignal();
biometricPrompt.authenticate(cancellationSignal, newExecutor, new android.hardware.biometrics.BiometricPrompt.AuthenticationCallback() {
#Override
public void onAuthenticationError(int errorCode, CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
}
#Override
public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
super.onAuthenticationHelp(helpCode, helpString);
}
#Override
public void onAuthenticationSucceeded(android.hardware.biometrics.BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
}
#Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
}
});
}
}
The expected output should be a successful compilation of the App

The androidx API was released in beta01, while the framework (android.hardware.biometrics) API was released in 29.
Edit: Just re-read your post, you are using the framework's version of the API. What is your target API level? The framework's version is only available 29+. You should consider using the androidx.biometric version of the API.

Related

How does Fingerprint API know it's been called?

I'm trying to learn how to implement a fingerprint API.
In one of fingerprint guides, it gave me a code
#RequiresApi(api = Build.VERSION_CODES.P)
public class BiometricCallbackV28 extends BiometricPrompt.AuthenticationCallback {
private BiometricCallback biometricCallback;
public BiometricCallbackV28(BiometricCallback biometricCallback) {
this.biometricCallback = biometricCallback;
}
#Override
public void onAuthenticationSucceeded(BiometricPrompt.AuthenticationResult result) {
super.onAuthenticationSucceeded(result);
biometricCallback.onAuthenticationSuccessful();
}
#Override
public void onAuthenticationHelp(int helpCode, CharSequence helpString) {
super.onAuthenticationHelp(helpCode, helpString);
biometricCallback.onAuthenticationHelp(helpCode, helpString);
}
#Override
public void onAuthenticationError(int errorCode, CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
biometricCallback.onAuthenticationError(errorCode, errString);
}
#Override
public void onAuthenticationFailed() {
super.onAuthenticationFailed();
biometricCallback.onAuthenticationFailed();
}
}
But shouldn't there be a test whether the authentication passed THEN call onAuthenticationSucceeded? I don't see anywhere that calls public void onAuthenticationSucceeded. How does it know that the fingerprint matches? Who calls the method?
But shouldn't there be a test whether the authentication passed
The system knows whether the authentication passed, by comparing the scanned fingerprint against fingerprints registered by the user
I don't see anywhere that calls public void onAuthenticationSucceeded
The framework calls all of those callback methods, based on the results from the biometric hardware.

Where does the Callback object come from in the ListenableWorker example?

The Android developer docs show an example of how to use a ListenableWorker. However, despite having added councurrent-futures to my project, I see now relevant Callback object as used in the docs:
#NonNull
#Override
public ListenableFuture<Result> startWork() {
return CallbackToFutureAdapter.getFuture(completer -> {
Callback callback = new Callback() {
...
}
Can anyone point me in the right direction? There doesnt seem to be a Callback class in androidx.concurrent.callback at all.
this is literally the only code sample I can find that uses CallbackToFutureAdapter.getFuture at all.
Looking at the documentation to a similar API, it looks to me that Callback
is not an API in itself but a generic representation of any operation with results.
https://developer.android.com/reference/androidx/concurrent/futures/CallbackToFutureAdapter.html
As an example, you could define the callback as follows,
interface AsyncCallback {
void onSuccess(Foo foo);
void onError(Failure failure);
}
And the startWork method as follows
#Override
public ListenableFuture<Result> startWork() {
return CallbackToFutureAdapter.getFuture(completer -> {
AsyncCallback callback = new AsyncCallback() {
int successes = 0;
#Override
public void onError(Failure failure) {
completer.setException(failure.getException());
}
#Override
public void onSuccess(Foo foo) {
completer.set(Result.success());
}
};
for (int i = 0; i < 100; ++i) {
downloadAsynchronously("https://www.google.com", callback);
}
return callback;
});
}

FINGERPRINT_ERROR_LOCKOUT callback happening twice using Android Native API

I am implementing the android native fingerprint API for one of our applications.
Below is the code of the handler:
public class FingerprintHandler extends
FingerprintManager.AuthenticationCallback {
private CancellationSignal cancellationSignal;
private Context appContext;
private boolean sendCancellation=false;
public FingerprintHandler(Context context) {
appContext = context;
}
public void startAuth(FingerprintManager manager,
FingerprintManager.CryptoObject cryptoObject) {
cancellationSignal = new CancellationSignal();
if (ActivityCompat.checkSelfPermission(appContext,
Manifest.permission.USE_FINGERPRINT) !=
PackageManager.PERMISSION_GRANTED) {
return;
}
manager.authenticate(cryptoObject, cancellationSignal, 0, this, null);
}
#Override
public void onAuthenticationError(int errMsgId,
CharSequence errString) {
Log.d(TAG,"Authentication error callback");
Log.d(TAG,"Error Value: "+errMsgId);
switch(errMsgId){
case FINGERPRINT_ERROR_LOCKOUT:
Log.d(TAG,"Fingerprint error lockout");
nativeLocked = true;
mPreferences.edit().putLong(LAST_FAILURE, System.currentTimeMillis()).apply();
showError(getString(R.string.test_bio_fingerprint_fingerprint_authentication_failed));
mCancelButton.setEnabled(true);
dialogHandler.postDelayed(new Runnable() {
#Override
public void run() {
mCancelButton.setEnabled(true);
dismissDialog();
sendFailure();
}
}, SUCCESS_OR_FAIL_DELAY_MILLIS);
break;
case FINGERPRINT_ERROR_CANCELED:
Log.d(TAG,"Fingerprint has been cancelled");
if(sendCancellation) {
dismissDialog();
if (useEye)
sendCancelForEye();
else
sendCancel();
}
break;
}
}
#Override
public void onAuthenticationHelp(int helpMsgId,
CharSequence helpString) {
Log.d(TAG,"Authentication helper callback");
retryWithError(R.string.test_bio_fingerprint_fingerprint_too_fast);
}
#Override
public void onAuthenticationFailed() {
Log.d(TAG,"Authentication failed callback");
retryWithError(R.string.test_bio_fingerprint_fingerprint_not_recognized);
}
#Override
public void onAuthenticationSucceeded(
FingerprintManager.AuthenticationResult result) {
Log.d(TAG,"Authentication successfull callback");
onAuthenticationSuccess();
}
public void stopListening(boolean sendCancellation) {
this.sendCancellation=sendCancellation;
Log.d(TAG,"stopListening called");
if (cancellationSignal != null) {
cancellationSignal.cancel();
cancellationSignal = null;
}
}
}
The problem is that when there are 5 incorrect authentication attempts I can see the below in my logs:
Authentication error callback
Error Value: 7
Fingerprint error lockout
Authentication error callback
Error Value: 7
Fingerprint error lockout
The lockout call back gets twice. I am unable to figure out why this is happening. Can someone please help.
You need to check errMsgId because first is triggered for your action callback and second time is triggered for "Fingerprint operation canceled."
Also please notice that FingerPrintManager is deprecated and for the new api for BiometricPrompt the implementation should look like example below (you need to replace BiometricConstants.ERROR_NEGATIVE_BUTTON with your action id code):
#Override
public void onAuthenticationError(int errorCode,
#NonNull CharSequence errString) {
super.onAuthenticationError(errorCode, errString);
if (BiometricConstants.ERROR_NEGATIVE_BUTTON == errorCode) {
//do your job only once
}
}

Android priority job queue error while serializing object

Trying to understand how to work with this lib.
Use example from twitter examples:
Configuration configuration = new Configuration.Builder(this)
.minConsumerCount(1)
.maxConsumerCount(3)
.loadFactor(3)
.consumerKeepAlive(120)
.build();
jobManager = new JobManager(this, configuration);
jobManager.addJob(new simpleJob("simple text"));
class simpleJob extends Job{
private String text;
public simpleJob(String text) {
super(new Params(1000).requireNetwork().persist());
this.text = text;
}
#Override
public void onAdded() {
Log.i("job", "onAdded");
}
#Override
public void onRun() throws Throwable {
Log.i("job", "onRun");
}
#Override
protected void onCancel() {
Log.i("job", "onCancel");
}
#Override
protected RetryConstraint shouldReRunOnThrowable(Throwable throwable, int runCount,
int maxRunCount) {
Log.i("job", "shouldReRunOnThrowable");
return RetryConstraint.RETRY;
}
}
In console i see only "onAdded". "onRun" never happened. If i add log interceptor, i see error text "error while serializing object simpleJob".
What is it? What object should be serializable?
As i explore, serializetion does not work if job is inner class. You need to place your job in separate class.

Using RxJava to make Quickblox API requests

I'm trying to use the Quickblox Android SDK combined with RxJava to make some chained and time-based Quickblox API calls. The API already have async methods. Here are two of them:
Create a session:
QBAuth.createSession(new QBEntityCallbackImpl<QBSession>() {
#Override
public void onSuccess(QBSession session, Bundle params) {
}
#Override
public void onError(List<String> errors) {
}
});
Create a Dialog (Chat Room)
QBChatService.getInstance().getGroupChatManager().createDialog(qbDialog,
new QBEntityCallbackImpl<QBDialog>() {
#Override
public void onSuccess(QBDialog dialog, Bundle args) {
}
#Override
public void onError(List<String> errors) {
}
});
As you saw, every API call must have a Callback Implementation as method parameter. The problem is that I have to make some chained API calls. Example:
Create empty session, then
Sign in, then
Retrieve user info, then
Login to chat service, then
....
I searched a little bit about RxJava and I saw that it's good to solve this kind of problem, because you can apply some filters and other things before make the next API call. The problem is that I don't know how to adapt this API to work with RxJava.
Should the API call with callbacks be inside the Observable call() method?
Should the onError() and the onSuccess() methods of the Quickblox API call the onError() and the onNext()/onCompleted() methods of the Subscriber?
Could anyone make some example of the use of
RxJava to create a session and then create a dialog using the
provided create session and create dialog API methods?
Here's a example of how to create observables using Observable.create() in your case:
Observable<QBSession> connectionObservable = Observable.create(new OnSubscribe<QBSession>() {
#Override
public void call(Subscriber<? super QBSession> subscriber) {
if (!subscriber.isUnsubscribed()) {
QBAuth.createSession(new QBEntityCallbackImpl<QBSession>() {
#Override
public void onSuccess(QBSession session, Bundle params) {
subscriber.onNext(session);
subscriber.onCompleted();
}
#Override
public void onError(List<String> errors) {
subscriber.onError(/*some throwable here*/);
}
});
}
}
});
Observable<QBDialog> dialogCreationObservable = Observable.create(new OnSubscribe<QBDialog>() {
#Override
public void call(Subscriber<? super QBDialog> subscriber) {
if (!subscriber.isUnsubscribed()) {
QBChatService.getInstance().getGroupChatManager().createDialog(qbDialog,
new QBEntityCallbackImpl<QBDialog>() {
#Override
public void onSuccess(QBDialog dialog, Bundle args) {
subscriber.onNext(dialog);
subscriber.onCompleted();
}
#Override
public void onError(List<String> errors) {
subscriber.onError(/*some throwable here*/);
}
});
}
}
});

Categories

Resources