Google Recaptcha Giving INTERNAL_ERROR on Android & IOS - android

I'm using Google recaptcha api to implement captcha on login action in my app. But every time I try to initialise the recaptcha api to get the recaptcha tasks client then It's giving either INTERNAL_ERROR or Timed out waiting for 10000 ms
I'm calling initiateSDK inside onCreate() of Application activity
Please let me know what's the reason for these errors and solution to fix.
In iOS, we are using same approach.
Code Snippet
public void initiateSDK(Context context) {
if (recaptchaTasksClient == null) {
init(context);
}
}
private void init(Context context) {
new Handler().post(() -> Recaptcha.getTasksClient((Application) context.getApplicationContext(), BuildConfig.RECAPTCHA_API_KEY)
.addOnSuccessListener(client -> {
recaptchaTasksClient = client;
})
.addOnFailureListener(e -> {
e.printStackTrace();
Log.d("RECAPTCHA", e.getMessage());
}));
}

Here are a few things you can try:
Check the version of the reCAPTCHA API that you're using. It's possible that you're using an outdated version, which could cause issues.
Make sure that you've correctly implemented the API on your site. It's possible that there is a problem with the way you've implemented the API, which could be causing the INTERNAL_ERROR message to appear.
Check your site's security settings. It's possible that your site's security settings are preventing the reCAPTCHA API from functioning correctly.
Try clearing your browser's cache and cookies. This can help to resolve issues that are caused by outdated data stored in your browser.
Make sure that you have a valid API key. It's possible that you're using an invalid or outdated API key, which could cause the INTERNAL_ERROR message to appear.
If you've tried these steps and are still experiencing issues with Google reCAPTCHA on Android and iOS, it's possible that the issue could be related to a problem with the API itself. In this case, you may want to try contacting Google for further assistance.

I experienced this. What ended up being the issue was that the client initialization insisted on being done on a UI thread. The working code ended up looking something like this:
private fun initializeRecaptchaClient() {
lifecycleScope.launch {
withContext(Dispatchers.Main) {
Recaptcha.getClient(application, "SITE_KEY")
.onSuccess {
this.recaptchaClient = it
}
.onFailure {
Log.e("Error initializing Recaptcha client", it)
}
}
}
}
The error that led to trying this solution, which only intermittently showed up was:
E/ViewConfiguration: Tried to access UI constants from a non-visual Context:[overridden Application class]#870795fUI constants, such as display metrics or window metrics, must be accessed from Activity or other visual Context. Use an Activity or a Context created with Context#createWindowContext(int, Bundle), which are adjusted to the configuration and visual bounds of an area on screen
java.lang.IllegalArgumentException: Tried to access UI constants from a non-visual Context:[overridden Application class]#870795f
I'm very much not entirely sure why that is. I did get the client to initialize successfully in a brand new test project without needing to force to the Main thread.
Although another cause of the "Internal Error" that I experienced while trying to get it working in the new app was forgetting the INTERNET permission.
I hope this helps someone.

Related

Firebase push notification - Default FirebaseApp is not initialized in this process

I am struggling to implement Google's Firebase push notifications in a mature MVVMcross application. We are being forced to seek a new solution to our current one because it appears that the functionality is about to be deprecated in AppCenter.
We've placed the code inside the RootActivity file (at the bottom of the method)
protected override void OnCreate(Bundle bundle)
When I run the app in a USB/debug scenario on my Android Galaxy I get the current error "Default FirebaseApp is not initialized in this process"
I tried to use the approach that was recommended in the error message to no avail:
FirebaseApp.InitializeApp(RootActivity.Context);
FirebaseMessaging.Instance.GetToken().AddOnCompleteListener(new OnCompleteListener());
In case anyone is wondering here is the code for the method that is mentioned above was setup for testing purposes using a breakpoint:
public class OnCompleteListener : Java.Lang.Object, IOnCompleteListener
{
public void OnComplete(Android.Gms.Tasks.Task task)
{
var token = task.Result.ToString();
}
}
We initially tested this in a standard Xamarin Forms Android app for testing and didn't have any problem with getting the token but we hit the wall when we played with it in our client's MVVMcross app.
I would also like to mention that I have tried the following solution with no luck as well:
var setupSingleton = MvxAndroidSetupSingleton.EnsureSingletonAvailable(Context);
setupSingleton.EnsureInitialized();
FirebaseMessaging.Instance.GetToken().AddOnCompleteListener(new OnCompleteListener());
I found that I had two problems. The first one was the fact that my project name did not match in my manifest and google services key. I was using my own key that I setup for testing. After I realized this I switched back to my client's key and double checked that it was part of the build. As soon as I resolved that issue I found that I needed to install the nuget package for Xamarin.Google.Dagger to resolve the reflection issues. After taking care of that I did a clean/rebuild and ran the debug on my Galaxy S20 test device. This fix allowed me to hit my test break point that I setup for testing the token reception from FCM.

Using the Android Turbolinks Framework, how do I mitigate Bridge Injection Failures

I asked this question on the Turbolinks GitHub page last week as I kept experiencing this bridge injection failure issue.
The issue is extremely intermittent and is very challenging to reproduce, but the code of the problem is that on some devices, we we see the Turbolinks Bridge Injection Failed error and our page subsequently fails to load properly.
There's too much code to post here (not to mention NDA restrictions), but suffice it to say that the page is being loaded on the majority of devices and on the ones that fail, we notice a 401 exception from our server due to bad authentication details and then this callback fires off.
Does anyone know why a Bridge Injection issue would occur on some devices, but not on others?
As it turns out, the issue lies not anywhere in my code nor in turbolinks, but is directly correlated to users having the Chrome Browser installed.
I ran countless data logs and tests to confirm, but the upshot is this:
Turbolinks will not work properly if the device:
1) Does not have Chrome installed
2) Has Chrome Disabled
3) Has an outdated version of Chrome that requires an update (no specific minimum version from what I could find, more just a generic, an update needs to happen after X versions).
In any of the 3 situations, this Bridge Injection Error will fire off and that is unquestionably the cause.
The solution is to redirect the user to the Play store via their device and instruct them to either download, enable, or update Chrome.
/**
* Open the Google Play store app URL Link
*/
void openChromeAppPlayStoreLink() {
//Try catch logic pulled from - https://stackoverflow.com/a/11753070/2480714
String chromeStr = "com.android.chrome";
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("market://details?id=" + chromeStr));
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
try {
startActivity(intent);
} catch (android.content.ActivityNotFoundException anfe) {
//Will fail if play store is disabled or uninstalled for some reason
intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://play.google.com/store/apps/details?id=" + chromeStr));
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK|Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
Why this is required when neither Turbolinks nor my forked version use the WebChromeClient is not something I fully understand.
As a quick disclaimer : I am sure you can get Turbolinks to work fine in some situations that do not do all that we were doing server-side, but in our situation, this was the lynchpin that was causing issues.

Google Smart Lock dialog is not appearing in Android O devices

I recently integrated GoogleSmartLock with my app. Somehow the save dialog is not coming up in Android O devices and the API is throwing following error.
The Credentials API's save confirmation dialog has been disabled to
avoid conflicts with the Android Autofill feature. This choice may be
overridden via
AuthCredentialsOptions.Builder.forceEnableSaveDialog().,
resolution=null}
I checked the latest release notes of the playservices and found out that following API can fix this problem.
Auth.AuthCredentialsOptions.Builder forceEnableSaveDialog ()
But I am not sure how to use this api with GoogleApIClient as it does not have build method that technically should return AuthCredentialOptions instance. Please let me know if anyone is facing the same problem.
Update 1: This issue is resolved in the latest release (Version 11.8.0):
AuthCredentialsOptions has been deprecated, replaced by the new CredentialsOptions.
Credentials.getClient() now offers overloads that accept CredentialsOptions .
Code examples (as well as further documentation on using .forceEnableSaveDialog) are available in the "Targeting Android O and above" section of the overview documentation and have been updated to use the new options class.
The build() method was missing from the public SDK for AuthCredentialsOptions.Builder and we fixed it (see the accepted answer)
But a more important clarification: Autofill with Google save dialog stores passwords to the same Smart Lock database, so if the Autofill dialog shows, then you don't need to worry about using the API to force the other dialog to show (in fact, if you force the dialog via the API, then make sure to suppress the Autofill one ... user should not see two dialogs). Data saved via either dialog will be available for Smart Lock auto sign-in (and vice versa for Autofill) and the data is sync'ed via Google Account with Chrome (autofill and API).
Since the dialogs store data to the same place, we opted to show the Autofill with Google one when user uses Google as their autofill manager because it will provide a consistent experience across all apps on Oreo devices. Working on improving error message, documentation, and branding to clarify this. Sorry for the confusion.
I managed to use reflection for this workaround:
Auth.AuthCredentialsOptions authCredentialsOptions = null;
try {
Constructor<Auth.AuthCredentialsOptions> constructor = Auth.AuthCredentialsOptions.class.getDeclaredConstructor(Auth.AuthCredentialsOptions.Builder.class);
constructor.setAccessible(true);
authCredentialsOptions = constructor.newInstance(new Auth.AuthCredentialsOptions.Builder().forceEnableSaveDialog());
} catch (Exception e) {
e.printStackTrace();
}
GoogleApiClient.Builder builder = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.enableAutoManage(this, 0, this);
if (authCredentialsOptions != null) {
builder.addApi(Auth.CREDENTIALS_API, authCredentialsOptions);
} else {
builder.addApi(Auth.CREDENTIALS_API);
}
mGoogleApiClient = builder.build();

Auto Update of application using HockeyApp SDK

I am using Android HockeyAppSDK to deploy updates to an application. I am trying to use the docs to customise the default UpdateManager class to allow updates to be installed automatically, without prompting the user to accept the update.
I am quite unsure of how to handle this. The obvious way (in my mind anyway) is to do the following:
private void checkForUpdates () {
UpdateManager.register (this, Constants.HOCKEY_API_KEY, new UpdateManagerListener() {
public void onUpdateAvailable() {
//I assume stuff will need to be handled here
}
});
}
Has anyone done this before, or can find a way to do it?
Many thanks
After emailing the support team for Hockey, they believe that within their current compiled API it is not possible to perform an update without prompting users to accept.
The whole source would require modification and compilation before working as expected it seems.
You can use UpdateTask from library

Android - Windows Live API, User has to sign in every time?

I am trying to submit a status from my application to Window's live, the user starts the app, gets asked to give my app permissions to do this, and once granted I have a live session object and I can update their status. This works perfectly.
However, if the user closes the application and then opens it again, they are again asked to approve my app for this action. Every time.
Now the live documentation says you can obtain a refresh token (which I do) to prevent this, problem is the access token and the refresh token are all baked in the LiveConnectSession, so when my application is closed this object is destroyed and the user is asked to give the app permissions again.
So what I'd like to know is if anyone knows a way of recreating that object when the application starts (if I stored the token and refresh token) or a way of saving the object onDestroy()..
Iterable<String> scopes = Arrays.asList("wl.signin", "wl.share", "wl.offline_access" );
this.auth.login(this, scopes, this);
public void onAuthComplete(LiveStatus status, LiveConnectSession session, Object userState) {
if(status == LiveStatus.CONNECTED) {
Log.d("", "Signed in.");
client = new LiveConnectClient(session);
stuck with the same issue using Windows Phone..
I have tried serializing the session, which does not work because the session class has no default constructor.
EDIT:
after two full days searching for the mistake I was making, I finally found out what I was doing wrong: I have to use the wl.offline_access scope to make this work!
Now everything is fun again. Can't believe that this was the problem. Tested & working. Nice!
As I can see, you are using the offline scope, so that's not the problem for you.
But I have found out more:
there are two ways to connect to Live (in C#, I don't know how the methods are called in Java):
use LiveConnectClient.LoginAsync (which comes with GUI)
use LiveConnectClient.InitializeAsync (which is UI less and connects in background)
So if your application is already connected, use the second one to gain access to a new session object.
AFAIK, this object is valid for one year, after that, the user has to sign in again. But don't quote me on that.
Please let me know if this works for you.

Categories

Resources