Skip to content

Commit

Permalink
Add support for full invisible flow (#39)
Browse files Browse the repository at this point in the history
Co-authored-by: Sergiu Danalachi <[email protected]>
Co-authored-by: e271828- <[email protected]>
  • Loading branch information
3 people authored Jun 15, 2022
1 parent 53d1947 commit 1b50afe
Show file tree
Hide file tree
Showing 29 changed files with 1,047 additions and 567 deletions.
13 changes: 12 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
# Changelog

# 3.0.0

- Add new boolean config option `HCaptchaConfig.hideDialog`.
- (breaking change) Change the behavior of `addOnSuccessListener`, `addOnFailureListener` and `addOnOpenListener` methods.
- previously: the callbacks were removed after utilization
- currently: the callbacks are persisted to be reused for future calls on the same client. This allows multiple human verifications using the same client and the same callback.

# 2.2.0

- Add new callback `addOnOpenListener`.

## 2.1.0

- Add `HCaptcha.setup` method to improve cold-start time, enable asset caching ([#24](https://github.com/hCaptcha/hcaptcha-android-sdk/issues/24))

## 2.0.0
- Add more error codes (see readme for full list)
- Add more error codes (see readme for full list)
228 changes: 124 additions & 104 deletions README.md

Large diffs are not rendered by default.

135 changes: 66 additions & 69 deletions example-app/src/main/java/com/hcaptcha/example/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,80 +4,68 @@
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import com.hcaptcha.sdk.*;
import com.hcaptcha.sdk.tasks.OnFailureListener;
import com.hcaptcha.sdk.tasks.OnOpenListener;
import com.hcaptcha.sdk.tasks.OnSuccessListener;

import java.util.Arrays;

public class MainActivity extends AppCompatActivity {

public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private static final String SITEKEY = "10000000-ffff-ffff-ffff-000000000001";

private RadioGroup sizeRadioGroup;
private CheckBox setupCheckBox;
private Spinner sizeSpinner;
private CheckBox hideDialog;
private CheckBox loading;
private TextView tokenTextView;
private TextView errorTextView;

private HCaptcha hCaptcha;
private HCaptchaConfig hCaptchaConfig;

@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setupCheckBox = findViewById(R.id.setupCheckBox);
setupCheckBox.setOnCheckedChangeListener((checkBox, checked) -> {
initHCaptcha(getSizeFromRadio(sizeRadioGroup));
});

sizeRadioGroup = findViewById(R.id.sizeRadioGroup);
sizeRadioGroup.setOnCheckedChangeListener((radioGroup, resId) -> {
initHCaptcha(getSizeFromRadio(radioGroup));
});
sizeRadioGroup.check(R.id.size_invisible);
sizeSpinner = findViewById(R.id.sizes);
tokenTextView = findViewById(R.id.tokenTextView);
errorTextView = findViewById(R.id.errorTextView);

CheckBox debugCheckBox = findViewById(R.id.webViewDebug);
hideDialog = findViewById(R.id.hide_dialog);
loading = findViewById(R.id.loading);
final ArrayAdapter<HCaptchaSize> adapter = new ArrayAdapter<>(this,
android.R.layout.simple_spinner_dropdown_item,
Arrays.asList(HCaptchaSize.NORMAL, HCaptchaSize.INVISIBLE, HCaptchaSize.COMPACT));
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
sizeSpinner.setAdapter(adapter);

// Toggle verbose webview logs
final CheckBox debugCheckBox = findViewById(R.id.webViewDebug);
debugCheckBox.setOnCheckedChangeListener((checkBox, checked) -> {
android.webkit.WebView.setWebContentsDebuggingEnabled(checked);
});
}

private HCaptchaSize getSizeFromRadio(@NonNull RadioGroup radioGroup) {
switch (radioGroup.getCheckedRadioButtonId()) {
case R.id.size_invisible: return HCaptchaSize.INVISIBLE;
case R.id.size_compact: return HCaptchaSize.COMPACT;
case R.id.size_normal: return HCaptchaSize.NORMAL;
default: return null;
}
private HCaptchaSize getSizeFromSpinner() {
return (HCaptchaSize) sizeSpinner.getSelectedItem();
}

private void initHCaptcha(@Nullable HCaptchaSize size) {
HCaptchaConfig.HCaptchaConfigBuilder builder = HCaptchaConfig.builder()
.siteKey("10000000-ffff-ffff-ffff-000000000001")
.loading(true);
if (size != null) {
builder.size(size);
}

hCaptchaConfig = builder.build();

hCaptcha = HCaptcha.getClient(this);
if (setupCheckBox.isChecked()) {
hCaptcha.setup(hCaptchaConfig);
}
private HCaptchaConfig getConfig() {
final HCaptchaSize size = getSizeFromSpinner();
return HCaptchaConfig.builder()
.siteKey(SITEKEY)
.size(size)
.loading(loading.isChecked())
.hideDialog(hideDialog.isChecked())
.build();
}

private void setTokenTextView(final String text) {
Expand All @@ -90,38 +78,47 @@ private void setErrorTextView(final String error) {
errorTextView.setText(error);
}

public HCaptcha verifyWithHCaptcha() {
if (setupCheckBox.isChecked() || getSizeFromRadio(sizeRadioGroup) == null) {
return hCaptcha.verifyWithHCaptcha();
}
public void onClickClear(final View v) {
setTokenTextView("-");
hCaptcha = null;
}

return hCaptcha.verifyWithHCaptcha(hCaptchaConfig);
public void onClickSetup(final View v) {
hCaptcha = HCaptcha.getClient(this).setup(getConfig());
setupClient(hCaptcha);
}

public void onClickShowHCaptcha(final View v) {
public void onClickVerify(final View v) {
setTokenTextView("-");
verifyWithHCaptcha()
.addOnSuccessListener(new OnSuccessListener<HCaptchaTokenResponse>() {
@Override
public void onSuccess(HCaptchaTokenResponse response) {
String userResponseToken = response.getTokenResult();
setTokenTextView(userResponseToken);
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(HCaptchaException e) {
Log.d(TAG, "hCaptcha failed: " + e.getMessage() + "(" + e.getStatusCode() + ")");
setErrorTextView(e.getMessage());
}
})
.addOnOpenListener(new OnOpenListener() {
@Override
public void onOpen() {
Toast.makeText(MainActivity.this, "hCaptcha shown", Toast.LENGTH_SHORT).show();
}
});

if (hCaptcha != null) {
hCaptcha.verifyWithHCaptcha();
} else {
hCaptcha = HCaptcha.getClient(this).verifyWithHCaptcha(getConfig());
setupClient(hCaptcha);
}
}

private void setupClient(final HCaptcha hCaptcha) {
hCaptcha
.addOnSuccessListener(new OnSuccessListener<HCaptchaTokenResponse>() {
@Override
public void onSuccess(HCaptchaTokenResponse response) {
String userResponseToken = response.getTokenResult();
setTokenTextView(userResponseToken);
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(HCaptchaException e) {
Log.d(TAG, "hCaptcha failed: " + e.getMessage() + "(" + e.getStatusCode() + ")");
setErrorTextView(e.getMessage());
}
})
.addOnOpenListener(new OnOpenListener() {
@Override
public void onOpen() {
Toast.makeText(MainActivity.this, "hCaptcha shown", Toast.LENGTH_SHORT).show();
}
});
}
}
69 changes: 34 additions & 35 deletions example-app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
@@ -1,57 +1,62 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:theme="@style/Theme.AppCompat"
tools:context=".MainActivity">

<RadioGroup
android:id="@+id/sizeRadioGroup"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/size_invisible"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/size_invisible"
style="@style/CheckBoxText" />
<RadioButton
android:id="@+id/size_compact"
<Spinner
android:id="@+id/sizes"
android:theme="@style/ThemeOverlay.AppCompat.Light"
android:spinnerMode="dropdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/size_compact"
style="@style/CheckBoxText" />
<RadioButton
android:id="@+id/size_normal"
android:layout_height="wrap_content" />
<CheckBox
android:id="@+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/size_normal"
android:minHeight="48dp"
android:checked="true"
android:text="@string/loading"
style="@style/CheckBoxText" />
<RadioButton
android:id="@+id/size_default"
<CheckBox
android:id="@+id/hide_dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/size_default"
app:buttonTint="@color/colorAccent"
android:minHeight="48dp"
android:checked="false"
android:text="@string/hide_dialog"
style="@style/CheckBoxText" />
</RadioGroup>
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<CheckBox
android:id="@+id/setupCheckBox"
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/clear"
android:onClick="onClickClear" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minHeight="48dp"
android:checked="true"
android:text="@string/setup"
style="@style/CheckBoxText" />
android:onClick="onClickSetup" />

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/verify"
android:onClick="onClickVerify" />

<CheckBox
android:id="@+id/webViewDebug"
android:layout_width="wrap_content"
Expand All @@ -62,12 +67,6 @@
style="@style/CheckBoxText" />
</LinearLayout>

<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/show_hcaptcha"
android:onClick="onClickShowHCaptcha" />

<LinearLayout
android:background="@android:color/holo_green_light"
android:orientation="horizontal"
Expand All @@ -87,7 +86,7 @@
android:text="-"
android:textColor="@android:color/white"
android:ellipsize="end"
android:maxLines="1"
android:maxLines="10"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Expand All @@ -114,4 +113,4 @@
android:layout_height="wrap_content" />
</LinearLayout>

</LinearLayout>
</LinearLayout>
11 changes: 5 additions & 6 deletions example-app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
<resources>
<string name="app_name">Example hCaptcha App</string>
<string name="size_invisible">Invisible</string>
<string name="size_compact">Compact</string>
<string name="size_normal">Normal</string>
<string name="size_default">Default</string>
<string name="clear">Clear</string>
<string name="setup">Setup</string>
<string name="show_hcaptcha">Show</string>
<string name="verify">Verify</string>
<string name="loading">Loading</string>
<string name="web_view_debug">WebView Debug</string>
</resources>
<string name="hide_dialog">Hide Dialog</string>
</resources>
4 changes: 2 additions & 2 deletions sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ android {
// See https://developer.android.com/studio/publish/versioning
// versionCode must be integer and be incremented by one for every new update
// android system uses this to prevent downgrades
versionCode 12
versionCode 13

// version number visible to the user
// should follow semantic versioning (See https://semver.org)
versionName "2.2.0"
versionName "3.0.0"

buildConfigField 'String', 'VERSION_NAME', "\"${defaultConfig.versionName}_${defaultConfig.versionCode}\""

Expand Down
8 changes: 8 additions & 0 deletions sdk/src/androidTest/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.hcaptcha.sdk"
tools:ignore="ExtraText">
<application>
<activity android:name=".TestActivity" android:theme="@style/Theme.AppCompat.Light" />
</application>
</manifest>
17 changes: 10 additions & 7 deletions sdk/src/androidTest/assets/hcaptcha-form.html
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,21 @@
} catch (e) {
BridgeObject.onError(29);
}
setTimeout(function() {
BridgeObject.onOpen();
}, 200);

if (!bridgeConfig.hideDialog) {
setTimeout(function() {
BridgeObject.onOpen();
}, 200);
}
}

function onPass() {
const token = document.getElementById("input-text").value;
function onPass(arg) {
const token = arg || document.getElementById("input-text").value;
BridgeObject.onPass(token);
}

function onError() {
const errorCode = parseInt(document.getElementById("input-text").value);
function onError(arg) {
const errorCode = arg || parseInt(document.getElementById("input-text").value);
BridgeObject.onError(errorCode);
}

Expand Down
Loading

0 comments on commit 1b50afe

Please sign in to comment.