Skip to content

Commit

Permalink
Merge branch 'Deep-Link-Routing-Validator-2.0' into Integration-Valid…
Browse files Browse the repository at this point in the history
…ator-2.0

# Conflicts:
#	Branch-SDK/src/main/res/drawable/branch_icon.png
  • Loading branch information
rob-gioia-branch committed Nov 15, 2024
2 parents effe1d5 + 5e1f9f6 commit e7902da
Show file tree
Hide file tree
Showing 9 changed files with 689 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import io.branch.referral.util.LinkProperties;
import io.branch.referral.util.ProductCategory;
import io.branch.referral.util.ShareSheetStyle;
import io.branch.referral.validators.LinkingValidator;

public class MainActivity extends Activity {
private EditText txtShortUrl;
Expand Down Expand Up @@ -661,6 +662,7 @@ protected void onStart() {
// IMP : Do not make this call in your production app

//IntegrationValidator.validate(MainActivity.this);
LinkingValidator.validate(MainActivity.this);
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package io.branch.referral.validators;

import android.content.Context;
import android.view.WindowManager;
import android.widget.Button;

import java.util.Objects;

public class LinkingValidator {
private static LinkingValidator instance;
private LinkingValidatorDialog linkingValidatorDialog;

private LinkingValidator(Context context) {}

public static void validate(Context context) {
if (instance == null) {
instance = new LinkingValidator(context);
}
instance.linkingValidatorDialog = new LinkingValidatorDialog(context);
instance.validateDeepLinkRouting(context);
}

private void validateDeepLinkRouting(Context context) {
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.copyFrom(Objects.requireNonNull(instance.linkingValidatorDialog.getWindow()).getAttributes());
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = 2000;
instance.linkingValidatorDialog.show();
instance.linkingValidatorDialog.getWindow().setAttributes(lp);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package io.branch.referral.validators;

public class LinkingValidatorConstants {
public static final String canonicalURLPromptText = "Please paste in a web link for the $canonical_url";
public static final String deeplinkPathPromptText = "Please paste in a value for the $deeplink_path";
public static final String customKeyPromptText = "Please enter your custom key and value for routing";
public static final String step1ButtonText = "Next";
public static final String step2ButtonText = " Generate Links for Testing ";
public static final String step3ButtonText = "Done";
public static final String canonicalUrlKey = "$canonical_url";
public static final String deeplinkPathKey = "$deeplink_path";

public static final String linkingValidatorRow1Title = "Link using App Link";
public static final String linkingValidatorRow2Title = "Link using URI scheme";
public static final String linkingValidatorRow3Title = "Web-only link";
public static final String linkingValidatorRow4Title = "Link with missing data";
public static final String linkingValidatorRow5Title = "Warm start use case";
public static final String linkingValidatorRow6Title = "Foreground click use case";

public static final String infoButton1Copy = "Verifies that Universal Links / App Links are working correctly for your Branch domain";
public static final String infoButton2Copy = "Verifies that URI schemes work correctly for your Branch domain";
public static final String infoButton3Copy = "Verifies that web-only links are handled correctly to take you to the mobile web";
public static final String infoButton4Copy = "Verifies that your app gracefully handles Branch links missing deep link data";
public static final String infoButton5Copy = "Click the button to simulate a deep link click for the warm start use case";
public static final String infoButton6Copy = "Click the button to simulate a deep link click for the foreground use case";

public static final String debugButton1Copy = "Ensure you’ve entered the correct SHA 256s on the dashboard and added your Branch domains to the Android Manifest";
public static final String debugButton2Copy = "Ensure that you’ve added a unique Branch URI scheme to the dashboard and Android Manifest";
public static final String debugButton3Copy = "Ensure that your code checks for $web-only in the link data, and if it is true routes the user to the mobile web";
public static final String debugButton4Copy = "Ensure that your code gracefully handles missing or invalid deep link data like taking them to the home screen";
public static final String debugButton5Copy = "Ensure that you are initializing Branch inside of onStart() and that the code is called anytime the app enters the foreground";
public static final String debugButton6Copy = "Ensure that you are calling reInit() inside of onNewIntent() after checking if branch_force_new_session is true";


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package io.branch.referral.validators;

import android.app.Dialog;
import android.content.Context;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

import io.branch.referral.R;

public class LinkingValidatorDialog extends Dialog implements AdapterView.OnItemSelectedListener {

private enum ROUTING_TYPE { CANONICAL_URL, DEEPLINK_PATH, CUSTOM }
private ROUTING_TYPE routingType;
private final Button ctaButton;
private final Spinner linkingValidatorDropdownMenu;
private final TextView linkingValidatorText;
private final EditText linkingValidatorEditText;
private final LinearLayout customKVPField;
private final LinearLayout linkingValidatorRowsLayout;
private int step = 1;
private String routingKey = "";
private String routingValue = "";
private LinkingValidatorDialogRowItem row1;
private LinkingValidatorDialogRowItem row2;
private LinkingValidatorDialogRowItem row3;
private LinkingValidatorDialogRowItem row4;
private LinkingValidatorDialogRowItem row5;
private LinkingValidatorDialogRowItem row6;

public LinkingValidatorDialog(final Context context) {
super(context);
requestWindowFeature(Window.FEATURE_NO_TITLE);
this.setContentView(R.layout.dialog_linking_validator);

linkingValidatorDropdownMenu = findViewById(R.id.linkingValidatorDropdownMenu);
List<String> choices = new ArrayList<>();
choices.add(LinkingValidatorConstants.canonicalUrlKey);
choices.add(LinkingValidatorConstants.deeplinkPathKey);
choices.add("other (custom)");
ArrayAdapter<String> dataAdapter = new ArrayAdapter<>(context, android.R.layout.simple_spinner_item, choices);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
linkingValidatorDropdownMenu.setAdapter(dataAdapter);
linkingValidatorDropdownMenu.setOnItemSelectedListener(this);

ctaButton = findViewById(R.id.linkingValidatorButton);
ctaButton.setText(LinkingValidatorConstants.step1ButtonText);
ctaButton.setOnClickListener(view -> {
switch(step) {
case 1:
LoadStep2Screen();
break;
case 2:
GenerateBranchLinks();
break;
case 3:
CloseDialog();
break;
}
});

linkingValidatorText = findViewById(R.id.linkingValidatorText);
linkingValidatorEditText = findViewById(R.id.linkingValidatorEditText);
customKVPField = findViewById(R.id.customKVPField);
linkingValidatorRowsLayout = findViewById(R.id.linkingValidatorRows);

linkingValidatorEditText.setVisibility(View.GONE);
customKVPField.setVisibility(View.GONE);
linkingValidatorRowsLayout.setVisibility(View.GONE);

routingType = ROUTING_TYPE.CANONICAL_URL;

row1 = findViewById(R.id.linkingValidatorRow1);
row2 = findViewById(R.id.linkingValidatorRow2);
row3 = findViewById(R.id.linkingValidatorRow3);
row4 = findViewById(R.id.linkingValidatorRow4);
row5 = findViewById(R.id.linkingValidatorRow5);
row6 = findViewById(R.id.linkingValidatorRow6);
}

@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
String item = adapterView.getItemAtPosition(i).toString();
switch (item) {
case "$canonical_url":
routingType = ROUTING_TYPE.CANONICAL_URL;
break;
case "$deeplink_path":
routingType = ROUTING_TYPE.DEEPLINK_PATH;
break;
case "other (custom)":
routingType = ROUTING_TYPE.CUSTOM;
break;
}
}

@Override
public void onNothingSelected(AdapterView<?> adapterView) {

}

void LoadStep2Screen() {
step++;
ctaButton.setText(LinkingValidatorConstants.step2ButtonText);
linkingValidatorDropdownMenu.setVisibility(View.GONE);

switch(routingType) {
case CANONICAL_URL:
linkingValidatorEditText.setVisibility(View.VISIBLE);
linkingValidatorText.setText(LinkingValidatorConstants.canonicalURLPromptText);
break;
case DEEPLINK_PATH:
linkingValidatorEditText.setVisibility(View.VISIBLE);
linkingValidatorText.setText(LinkingValidatorConstants.deeplinkPathPromptText);
break;
case CUSTOM:
customKVPField.setVisibility(View.VISIBLE);
linkingValidatorText.setText(LinkingValidatorConstants.customKeyPromptText);
break;
}
}

void GenerateBranchLinks() {
switch(routingType) {
case CANONICAL_URL:
routingKey = LinkingValidatorConstants.canonicalUrlKey;
routingValue = linkingValidatorEditText.getText().toString();
break;
case DEEPLINK_PATH:
routingKey = LinkingValidatorConstants.deeplinkPathKey;
routingValue = linkingValidatorEditText.getText().toString();
break;
}

step++;
linkingValidatorEditText.setVisibility(View.GONE);
customKVPField.setVisibility(View.GONE);
linkingValidatorText.setVisibility(View.GONE);
ctaButton.setText(LinkingValidatorConstants.step3ButtonText);
linkingValidatorRowsLayout.setVisibility(View.VISIBLE);

EditText customKeyEditText = findViewById(R.id.keyEditText);
EditText customValueEditText = findViewById(R.id.valueEditText);

//if routing key is empty, it is a custom key outside of $canonical_url and $deeplink_path
if(routingKey.isEmpty()) {
routingKey = customKeyEditText.getText().toString();
routingValue = customValueEditText.getText().toString();
}

row1.InitializeRow(LinkingValidatorConstants.linkingValidatorRow1Title, LinkingValidatorConstants.infoButton1Copy, LinkingValidatorConstants.debugButton1Copy, routingKey, routingValue, "regularBranchLink", true, 0);
row2.InitializeRow(LinkingValidatorConstants.linkingValidatorRow2Title, LinkingValidatorConstants.infoButton2Copy, LinkingValidatorConstants.debugButton2Copy, routingKey, routingValue, "uriFallbackBranchLink", true, 1, "$uri_redirect_mode", "2");
row3.InitializeRow(LinkingValidatorConstants.linkingValidatorRow3Title, LinkingValidatorConstants.infoButton3Copy, LinkingValidatorConstants.debugButton3Copy, routingKey, routingValue, "webOnlyBranchLink", true, 2, "$web_only", "true");
row4.InitializeRow(LinkingValidatorConstants.linkingValidatorRow4Title, LinkingValidatorConstants.infoButton4Copy, LinkingValidatorConstants.debugButton4Copy, routingKey, "", "missingDataBranchLink", true, 3);
row5.InitializeRow(LinkingValidatorConstants.linkingValidatorRow5Title, LinkingValidatorConstants.infoButton5Copy, LinkingValidatorConstants.debugButton5Copy, routingKey, routingValue, "warmStartUseCase", false, 4);
row6.InitializeRow(LinkingValidatorConstants.linkingValidatorRow6Title, LinkingValidatorConstants.infoButton6Copy, LinkingValidatorConstants.debugButton6Copy, routingKey, routingValue, "foregroundClickUseCase", false, 5);
}

private void CloseDialog() {
this.dismiss();
}
}
Loading

0 comments on commit e7902da

Please sign in to comment.