--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Nov 06 12:51:09 PST 2024
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
5 | networkTimeout=10000
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/xml/network_security_config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Branch-SDK/src/androidTest/assets/pre_install_apps_no_package.branch:
--------------------------------------------------------------------------------
1 | {
2 | "apps": {
3 | "io.branch.referral.packager": {
4 | "preinstall_partner": "branch_",
5 | "preinstall_campaign": "branch_campaign",
6 | "custom_key": "custom_value"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Branch-SDK/src/main/java/io/branch/referral/IBranchRequestTracingCallback.java:
--------------------------------------------------------------------------------
1 | package io.branch.referral;
2 |
3 | import org.json.JSONObject;
4 |
5 | public interface IBranchRequestTracingCallback {
6 | void onRequestCompleted(String uri, JSONObject request, JSONObject response, String error, String requestUrl);
7 | }
8 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policy
2 |
3 | ## Reporting a Vulnerability
4 | If you discover a potential security issue in this project we ask that you notify Branch Security directly via email to security@branch.io
5 | Please do not open GitHub issues or pull requests - this makes the problem immediately visible to everyone, including malicious actors.
6 |
--------------------------------------------------------------------------------
/Branch-SDK/proguard-consumer.txt:
--------------------------------------------------------------------------------
1 | # Remove references to Huawei's OAID (Google's advertising id equivalent) if the dependency is not available in your project.
2 | -dontwarn com.huawei.hms.ads.**
3 |
4 | -dontwarn com.miui.referrer.**
5 | -dontwarn com.samsung.android.sdk.sinstallreferrer.**
6 |
7 | -dontwarn com.google.android.gms.**
8 |
9 | -dontwarn com.android.billingclient.**
10 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/pill_button.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_first_page_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_last_page_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
4 | # Custom for Visual Studio
5 | *.cs diff=csharp
6 |
7 | # Standard to msysgit
8 | *.doc diff=astextplain
9 | *.DOC diff=astextplain
10 | *.docx diff=astextplain
11 | *.DOCX diff=astextplain
12 | *.dot diff=astextplain
13 | *.DOT diff=astextplain
14 | *.pdf diff=astextplain
15 | *.PDF diff=astextplain
16 | *.rtf diff=astextplain
17 | *.RTF diff=astextplain
18 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_person_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature-request.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🚀 Feature Request
3 | description: Suggest an idea for this project
4 | title: "(short issue description)"
5 | labels: [feature-request, needs-triage]
6 | assignees: []
7 | body:
8 | - type: textarea
9 | id: description
10 | attributes:
11 | label: Describe the feature
12 | description: A clear and concise description of the feature you are proposing.
13 | validations:
14 | required: true
15 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_insert_photo_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Branch-SDK/src/main/java/io/branch/referral/util/AdType.java:
--------------------------------------------------------------------------------
1 | package io.branch.referral.util;
2 |
3 | /**
4 | * Ad Types
5 | */
6 | public enum AdType {
7 | BANNER("BANNER"),
8 | INTERSTITIAL("INTERSTITIAL"),
9 | REWARDED_VIDEO("REWARDED_VIDEO"),
10 | NATIVE("NATIVE");
11 |
12 | private final String name;
13 |
14 | AdType(String name) {
15 | this.name = name;
16 | }
17 |
18 | public String getName() {
19 | return name;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_logout_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_security_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_open_in_new_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Branch-SDK/src/main/java/io/branch/interfaces/IBranchLoggingCallbacks.java:
--------------------------------------------------------------------------------
1 | package io.branch.interfaces;
2 |
3 | /**
4 | * A set of callbacks that interface with the SDK's internal logging.
5 | */
6 | public interface IBranchLoggingCallbacks {
7 | /**
8 | * Callback method that returns each time a log is generated
9 | * @param logMessage The log message
10 | * @param severityConstantName any of DEBUG, ERROR, INFO, WARN, VERBOSE
11 | */
12 | void onBranchLog(String logMessage, String severityConstantName);
13 | }
14 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | ---
2 | blank_issues_enabled: false
3 | contact_links:
4 | - name: "📕 Documentation Issue"
5 | url: https://help.branch.io/developers-hub/docs/android-sdk-overview
6 | about: Report an issue in the Branch Android SDK Reference documentation by clicking "Suggest edits" button on the documentation page.
7 | - name: "Branch Support"
8 | url: https://help.branch.io/using-branch/page/submit-a-ticket
9 | about: If you are having general trouble with Branch Android SDK integration, please submit a ticket to Branch Support.
10 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/baseline_document_scanner_24.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Eclipse
2 | *.class
3 | Branch-SDK-TestBed/.settings/org.eclipse.jdt.core.prefs
4 | Branch-SDK/.settings/org.eclipse.jdt.core.prefs
5 |
6 | # Android Studio
7 | .idea
8 | *.iml
9 | local.properties
10 | build/
11 |
12 | # Gradle
13 | .gradle/*
14 | .metadata/*
15 |
16 | *.gen
17 | bin/
18 | gen/
19 |
20 | # Mac stuff
21 | *.DS_Store
22 |
23 | # Branch
24 | Branch-SDK-TestBed/gradle/wrapper/gradle-wrapper.jar
25 | Branch-SDK-TestBed/gradlew
26 | Branch-SDK-TestBed/gradlew.bat
27 |
28 | Branch-SDK-TestBed/gradle/wrapper/gradle-wrapper.properties
29 |
30 | .direnv
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_doorbell_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_link_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_remove_red_eye_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Branch-SDK-TestBed
5 |
6 | install count =
7 |
8 | "Launched by Branch on auto deep linking!"
9 | "Launched by normal application flow"
10 |
11 | Disable ad network callouts
12 | Settings
13 |
14 |
--------------------------------------------------------------------------------
/Branch-SDK/javadoc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_emoji_events_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_shopping_bag_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Branch-SDK/src/main/java/io/branch/data/InstallReferrerResult.kt:
--------------------------------------------------------------------------------
1 | package io.branch.data
2 |
3 | data class InstallReferrerResult (var appStore: String?,
4 | var installBeginTimestampSeconds: Long,
5 | var installReferrer: String?,
6 | var referrerClickTimestampSeconds: Long,
7 | var installBeginTimestampServerSeconds: Long?,
8 | var referrerClickTimestampServerSeconds: Long?,
9 | var isClickThrough: Boolean = true)
10 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_person_off_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Branch-SDK/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-20
15 | android.library=true
16 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_pageview_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-20
15 | android.library.reference.1=../Branch-SDK
16 |
--------------------------------------------------------------------------------
/install-dependencies.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Fix the CircleCI path
4 | export PATH="$ANDROID_HOME/platform-tools:$ANDROID_HOME/tools:$PATH"
5 |
6 | DEPS="$ANDROID_HOME/installed-dependencies"
7 |
8 | if [ ! -e $DEPS ]; then
9 | cp -r /usr/local/android-sdk-linux $ANDROID_HOME &&
10 | echo y | android update sdk -u -a -t android-23 &&
11 | echo y | android update sdk -u -a -t platform-tools &&
12 | echo y | android update sdk -u -a -t build-tools-21.1.2 &&
13 | echo y | android update sdk -u -a -t sys-img-x86-android-23 &&
14 | echo y | android update sdk -u -a -t addon-google_apis-google-18 &&
15 | echo n | android create avd -n circleci-android23 -f -t android-23 --abi default/x86 &&
16 | touch $DEPS
17 | fi
18 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/layout/activity_log_output.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_share_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Branch-SDK/src/main/java/io/branch/referral/validators/IntegrationValidatorCheck.java:
--------------------------------------------------------------------------------
1 | package io.branch.referral.validators;
2 |
3 | import android.content.Context;
4 |
5 | public abstract class IntegrationValidatorCheck {
6 | String name;
7 | String errorMessage;
8 | String moreInfoLink;
9 |
10 | public abstract boolean RunTests(Context context);
11 |
12 | public String GetOutput(Context context, boolean didTestSucceed) {
13 | String symbol = RunTests(context) ? IntegrationValidatorConstants.checkmark : IntegrationValidatorConstants.xmark;
14 | return errorMessage;
15 | }
16 |
17 | public String GetTestName() {
18 | return name;
19 | }
20 |
21 | public String GetMoreInfoLink() {
22 | return moreInfoLink;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_monetization_on_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/layout/auto_deep_link_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
--------------------------------------------------------------------------------
/Branch-SDK/src/androidTest/java/io/branch/referral/utils/AssetUtils.java:
--------------------------------------------------------------------------------
1 | package io.branch.referral.utils;
2 |
3 | import android.content.Context;
4 |
5 | import java.io.BufferedReader;
6 | import java.io.IOException;
7 | import java.io.InputStreamReader;
8 |
9 | /**
10 | * Asset Utilities.
11 | */
12 | public class AssetUtils {
13 | public static String readJsonFile (Context context, String filename) {
14 | StringBuilder sb = new StringBuilder();
15 | try {
16 | BufferedReader br = new BufferedReader(new InputStreamReader(context.getAssets().open(filename)));
17 | String line = br.readLine();
18 | while (line != null) {
19 | sb.append(line);
20 | line = br.readLine();
21 | }
22 | } catch (IOException e) {
23 | e.printStackTrace();
24 | }
25 | return sb.toString();
26 | }
27 | }
--------------------------------------------------------------------------------
/Branch-SDK/doc/script.js:
--------------------------------------------------------------------------------
1 | function show(type)
2 | {
3 | count = 0;
4 | for (var key in methods) {
5 | var row = document.getElementById(key);
6 | if ((methods[key] & type) != 0) {
7 | row.style.display = '';
8 | row.className = (count++ % 2) ? rowColor : altColor;
9 | }
10 | else
11 | row.style.display = 'none';
12 | }
13 | updateTabs(type);
14 | }
15 |
16 | function updateTabs(type)
17 | {
18 | for (var value in tabs) {
19 | var sNode = document.getElementById(tabs[value][0]);
20 | var spanNode = sNode.firstChild;
21 | if (value == type) {
22 | sNode.className = activeTableTab;
23 | spanNode.innerHTML = tabs[value][1];
24 | }
25 | else {
26 | sNode.className = tableTab;
27 | spanNode.innerHTML = "" + tabs[value][1] + "";
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Branch-SDK/src/androidTest/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/Branch-SDK/src/main/java/io/branch/referral/BranchApp.java:
--------------------------------------------------------------------------------
1 | package io.branch.referral;
2 |
3 | import android.app.Application;
4 |
5 | /**
6 | *
7 | * Default Android Application class for Branch SDK. You should use this as your application class
8 | * in your manifest if you are not creating an Application class. If you already have an Application
9 | * class then you can either extend your Application class with BranchApp or initialize Branch yourself
10 | * via Branch.getAutoInstance(this);.
11 | *
12 | *
13 | * Add this entry to the manifest if you don't have an Application class :
14 | *
20 | */
21 | public class BranchApp extends Application {
22 |
23 | @Override
24 | public void onCreate() {
25 | super.onCreate();
26 | Branch.getAutoInstance(this);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Branch-SDK/proguard-project.txt:
--------------------------------------------------------------------------------
1 | # To enable ProGuard in your project, edit project.properties
2 | # to define the proguard.config property as described in that file.
3 | #
4 | # Add project specific ProGuard rules here.
5 | # By default, the flags in this file are appended to flags specified
6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt
7 | # You can edit the include path and order by changing the ProGuard
8 | # include property in project.properties.
9 | #
10 | # For more details, see
11 | # http://developer.android.com/guide/developing/tools/proguard.html
12 |
13 | # Add any project specific keep options here:
14 |
15 | # If your project uses WebView with JS, uncomment the following
16 | # and specify the fully qualified class name to the JavaScript interface
17 | # class:
18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
19 | # public *;
20 | #}
21 |
22 | # Huawei's OAID (Google's advertising id equivalent)
23 | -keep class com.huawei.hms.ads.** { *; }
24 | -keep interface com.huawei.hms.ads.** { *; }
--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | ## Reference
2 | SDK-XXX -- .
3 |
4 | ## Description
5 |
6 |
7 | ## Testing Instructions
8 |
9 |
10 | ## Risk Assessment [`HIGH` || `MEDIUM` || `LOW`]
11 |
12 |
13 |
14 | - [ ] I, the PR creator, have tested — integration, unit, or otherwise — this code.
15 |
16 | ## Reviewer Checklist (To be checked off by the reviewer only)
17 |
18 | - [ ] JIRA Ticket is referenced in PR title.
19 | - Correctness & Style
20 | - [ ] Conforms to [AOSP Style Guides](https://source.android.com/setup/contribute/code-style)
21 | - [ ] Mission critical pieces are documented in code and out of code as needed.
22 | - [ ] Unit Tests reviewed and test issue sufficiently.
23 | - [ ] Functionality was reviewed in QA independently by another engineer on the team.
24 |
25 | cc @BranchMetrics/saas-sdk-devs for visibility.
26 |
--------------------------------------------------------------------------------
/Branch-SDK/src/main/java/io/branch/referral/BranchAsyncTask.java:
--------------------------------------------------------------------------------
1 | package io.branch.referral;
2 |
3 | import android.os.AsyncTask;
4 | import android.os.Build;
5 |
6 | /**
7 | *
8 | * Convenient class for handling ASync task with pool executor depending on the SDK platform
9 | *
10 | */
11 | public abstract class BranchAsyncTask extends AsyncTask {
12 |
13 | /**
14 | * Execute Params in back ground depending on the platform version. This executes task in parallel with the {@link AsyncTask#THREAD_POOL_EXECUTOR}
15 | *
16 | * @param params Params for executing this Async task
17 | * @return This object for method chaining
18 | */
19 | public final AsyncTask executeTask(Params... params) {
20 | try {
21 | return executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
22 | } catch (Exception t) {
23 | BranchLogger.w("Caught Exception in AsyncTask: " + t.getMessage());
24 | return execute(params);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/Branch-SDK/src/main/java/io/branch/receivers/SharingBroadcastReceiver.kt:
--------------------------------------------------------------------------------
1 | package io.branch.receivers
2 |
3 | import android.content.BroadcastReceiver
4 | import android.content.ComponentName
5 | import android.content.Context
6 | import android.content.Intent
7 | import android.content.Intent.EXTRA_CHOSEN_COMPONENT
8 | import io.branch.referral.BranchLogger
9 | import io.branch.referral.NativeShareLinkManager
10 | import io.branch.referral.util.SharingUtil
11 |
12 | class SharingBroadcastReceiver: BroadcastReceiver() {
13 | override fun onReceive(context: Context, intent: Intent) {
14 | val clickedComponent: ComponentName? = intent.getParcelableExtra(EXTRA_CHOSEN_COMPONENT);
15 |
16 | BranchLogger.v("Intent: $intent")
17 | BranchLogger.v("Clicked component: $clickedComponent")
18 |
19 | NativeShareLinkManager.getInstance().linkShareListenerCallback?.onChannelSelected(
20 | clickedComponent.toString()
21 | )
22 |
23 | NativeShareLinkManager.getInstance().linkShareListenerCallback?.onLinkShareResponse(SharingUtil.sharedURL, null);
24 | }
25 | }
--------------------------------------------------------------------------------
/Branch-SDK/src/androidTest/java/io/branch/referral/KeyTest.java:
--------------------------------------------------------------------------------
1 | package io.branch.referral;
2 |
3 | import androidx.test.ext.junit.runners.AndroidJUnit4;
4 |
5 | import org.junit.Assert;
6 | import org.junit.Test;
7 | import org.junit.runner.RunWith;
8 |
9 | @RunWith(AndroidJUnit4.class)
10 | public class KeyTest extends BranchTest {
11 |
12 | @Test
13 | public void testManifestKeys() {
14 | Assert.assertFalse(BranchUtil.isTestModeEnabled());
15 |
16 | String branchKey = BranchUtil.readBranchKey(getTestContext());
17 | Assert.assertTrue(branchKey.startsWith("key_live"));
18 |
19 | Branch.enableTestMode();
20 | branchKey = BranchUtil.readBranchKey(getTestContext());
21 | Assert.assertTrue(branchKey.startsWith("key_test"));
22 | }
23 |
24 | @Test
25 | public void testAutoInstanceWithKey() {
26 | final String expectedKey = "key_XXX";
27 | initBranchInstance(expectedKey);
28 |
29 | final String actualKey = PrefHelper.getInstance(getTestContext()).getBranchKey();
30 | Assert.assertEquals(expectedKey, actualKey);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Branch SDK Documentation for Android
2 |
3 | The Branch Android SDK for deep linking and attribution.
4 |
5 | > ## Branch Sandbox Program
6 | >
7 | > As part of this [sandbox program](https://help.branch.io/developers-hub/docs/branch-sandbox-program), you will be able to partner directly with Branch’s Product and Engineering team for exclusive access to test drive our innovative products before the market and proactively exchange valuable feedback. With your support, we will create the winning measurement and linking solutions of the future together.
8 | >
9 | > **If you would like to join, please reach out to us today at [sandbox@branch.io](mailto:sandbox@branch.io "mailto:sandbox@branch.io") or by filling out this [form](https://branch.link/sandbox?~channel=android-repo).**
10 |
11 | Branch helps mobile apps grow with deep links / deeplinks that power paid acquisition and re-engagement campaigns, referral programs, content sharing, deep linked emails, smart banners, custom user onboarding, and more.
12 |
13 | View [Branch's SDK documentation for Android](https://help.branch.io/developers-hub/docs/android-sdk-overview)
14 |
--------------------------------------------------------------------------------
/License.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Branch Metrics, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/.github/workflows/stale.yml:
--------------------------------------------------------------------------------
1 | # This workflow warns and then closes issues that have had no activity for a specified amount of time.
2 | #
3 | # You can adjust the behavior by modifying this file.
4 | # For more information, see:
5 | # https://github.com/actions/stale
6 | name: Mark stale issues
7 |
8 | on:
9 | schedule:
10 | - cron: '0 0 * * *'
11 |
12 | jobs:
13 | stale:
14 |
15 | runs-on: ubuntu-latest
16 | permissions:
17 | issues: write
18 |
19 | steps:
20 | - uses: actions/stale@v10
21 | with:
22 | days-before-issue-stale: 60
23 | days-before-close: 7
24 | stale-issue-message: 'This issue has been automatically marked as stale due to inactivity for 60 days. If this issue is still relevant, please respond with any updates or this issue will be closed in 7 days. If you believe this is a mistake, please comment to let us know. Thank you for your contributions.'
25 | stale-issue-label: 'no-issue-activity'
26 | close-issue-message: 'This issue has been closed due to inactivity. If this issue is still relevant, please reopen it or create a new one. Thank you for your contributions.'
27 | start-date: '2023-05-22'
28 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_settings_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/Branch-SDK/src/main/java/io/branch/referral/validators/BranchKeysValidatorCheck.java:
--------------------------------------------------------------------------------
1 | package io.branch.referral.validators;
2 |
3 | import static io.branch.referral.validators.IntegrationValidatorConstants.branchKeysMoreInfoDocsLink;
4 |
5 | import android.content.Context;
6 | import android.text.TextUtils;
7 |
8 | import io.branch.referral.BranchUtil;
9 |
10 | public class BranchKeysValidatorCheck extends IntegrationValidatorCheck {
11 |
12 | String name = "Branch Keys";
13 | String errorMessage = "Unable to read Branch keys from your application. Did you forget to add Branch keys in your application?.";
14 | String moreInfoLink = branchKeysMoreInfoDocsLink;
15 |
16 | public BranchKeysValidatorCheck() {
17 | super.name = name;
18 | super.errorMessage = errorMessage;
19 | super.moreInfoLink = moreInfoLink;
20 | }
21 |
22 | @Override
23 | public boolean RunTests(Context context) {
24 | return !TextUtils.isEmpty(BranchUtil.readBranchKey(context));
25 | }
26 |
27 | @Override
28 | public String GetOutput(Context context, boolean didTestSucceed) {
29 | didTestSucceed = RunTests(context);
30 | return super.GetOutput(context, didTestSucceed);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Branch-SDK/src/main/java/io/branch/referral/validators/LinkingValidator.java:
--------------------------------------------------------------------------------
1 | package io.branch.referral.validators;
2 |
3 | import android.content.Context;
4 | import android.view.WindowManager;
5 | import android.widget.Button;
6 |
7 | import java.util.Objects;
8 |
9 | public class LinkingValidator {
10 | private static LinkingValidator instance;
11 | private LinkingValidatorDialog linkingValidatorDialog;
12 |
13 | private LinkingValidator(Context context) {}
14 |
15 | public static void validate(Context context) {
16 | if (instance == null) {
17 | instance = new LinkingValidator(context);
18 | }
19 | instance.linkingValidatorDialog = new LinkingValidatorDialog(context);
20 | instance.validateDeepLinkRouting(context);
21 | }
22 |
23 | private void validateDeepLinkRouting(Context context) {
24 | WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
25 | lp.copyFrom(Objects.requireNonNull(instance.linkingValidatorDialog.getWindow()).getAttributes());
26 | lp.width = WindowManager.LayoutParams.MATCH_PARENT;
27 | lp.height = 2000;
28 | instance.linkingValidatorDialog.show();
29 | instance.linkingValidatorDialog.getWindow().setAttributes(lp);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Branch-SDK/src/main/java/io/branch/referral/util/DependencyUtils.kt:
--------------------------------------------------------------------------------
1 | package io.branch.referral.util
2 |
3 | import io.branch.referral.BranchLogger
4 |
5 | fun classExists(className: String): Boolean {
6 | return try {
7 | Class.forName(className)
8 | true
9 | } catch (e: ClassNotFoundException) {
10 | BranchLogger.v("Could not find $className. If expected, import the dependency into your app.")
11 | false
12 | }
13 | }
14 |
15 | const val playStoreInstallReferrerClass = "com.android.installreferrer.api.InstallReferrerClient"
16 |
17 | const val playStoreAdvertisingIdClientClass =
18 | "com.google.android.gms.ads.identifier.AdvertisingIdClient"
19 |
20 | const val huaweiAdvertisingIdClientClass = "com.huawei.hms.ads.identifier.AdvertisingIdClient";
21 |
22 | const val huaweiInstallReferrerClass =
23 | "com.huawei.hms.ads.installreferrer.api.InstallReferrerClient"
24 |
25 | const val samsungInstallReferrerClass =
26 | "com.samsung.android.sdk.sinstallreferrer.api.InstallReferrerClient"
27 |
28 | const val xiaomiInstallReferrerClass = "com.miui.referrer.api.GetAppsReferrerClient"
29 |
30 | const val billingGooglePlayClass = "com.android.billingclient.api.BillingClient"
31 |
32 | const val androidBrowserClass = "androidx.browser.customtabs.CustomTabsIntent"
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | VERSION_NAME=5.20.3
2 | VERSION_CODE=052403
3 | GROUP=io.branch.sdk.android
4 |
5 | POM_DESCRIPTION=Use the Branch SDK (branch.io) to create and power the links that point back to your apps for all of these things and more. Branch makes it incredibly simple to create powerful deep links that can pass data across app install and open while handling all edge cases (using on desktop vs. mobile vs. already having the app installed, etc). Best of all, it is really simple to start using the links for your own app: only 2 lines of code to register the deep link router and one more line of code to create the links with custom data.
6 | POM_URL=https://github.com/BranchMetrics/Branch-Android-SDK/
7 | POM_SCM_URL=https://github.com/BranchMetrics/Branch-Android-SDK/
8 | POM_SCM_CONNECTION=scm:git@github.com:BranchMetrics/Branch-Android-SDK.git
9 | POM_SCM_DEV_CONNECTION=scm:git@github.com:BranchMetrics/Branch-Android-SDK.git
10 | POM_LICENCE_NAME=The Apache Software License, Version 2.0
11 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt
12 | POM_LICENCE_DIST=repo
13 | POM_DEVELOPER_ID=branch
14 | POM_DEVELOPER_NAME=Branch Metrics
15 |
16 | ANDROID_BUILD_SDK_VERSION_MINIMUM=21
17 | ANDROID_BUILD_SDK_VERSION_COMPILE=34
18 | ANDROID_BUILD_TOOLS_VERSION=34.0.0
19 | android.useAndroidX=true
20 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/src/main/res/drawable/ic_baseline_qr_code_24.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/Branch-SDK/src/main/java/io/branch/referral/SharingHelper.java:
--------------------------------------------------------------------------------
1 | package io.branch.referral;
2 |
3 | /**
4 | * Define the Applications for the sharing the link with.
5 | */
6 | public class SharingHelper {
7 | /**
8 | *
9 | * Defines the Application for sharing a deep link with.
10 | *
Activity to demonstrate the auto deep linking functionality.
12 | * This activity is defined in the manifest with Keys for auto deep linking.
13 | * See manifest file for auto deep link configurations.
37 |
38 |
39 |
--------------------------------------------------------------------------------
/Branch-SDK-TestBed/InitializationTestPlan.md:
--------------------------------------------------------------------------------
1 | # Test plan for different (re)initialization scenarios
2 |
3 | This is a test plan enlisting possible initialization scenarios. As CSMs
4 | find bugs arising from unforeseen initialization scenarios, this list should
5 | be updated. Unless noted, initialization is expected to work in all scenarios.
6 |
7 |
8 | ## Assumptions:
9 | * User followed [Android documentation](https://docs.branch.io/apps/android/)
10 | * Application can have multiple activities (launcher activity is called
11 | `SplashActivity` and all others are `NextActivity`)
12 | * Latest Branch SDK version is being used
13 |
14 |
15 | ## Scenario #1:
16 | * `initSession` is only called in `SplashActivity.onStart`.
17 |
18 |
19 | ### 1. Application in background
20 | ```
21 | Test by opening the app via:
22 | * launcher icon
23 | * recent apps tray (not available in cold start)
24 | * push notification
25 | ```
26 | #### Cold start:
27 | * Repro: Close app and remove it from the recent apps list
28 | (not 100% guarantee that this will work because manufacturers determine
29 | if application is killed when removed from recents list). Alternatively,
30 | call `adb shell pm clear my.app.package.id` from the command line (this
31 | will also clear cache and stored data). Open app.
32 | * Initialization entry point = `SplashActivity.onCreate`
33 |
34 |
35 | #### Warm start:
36 | * Repro: Close app via the back button. Open app.
37 | * Initialization entry point = `SplashActivity.onCreate`
38 |
39 | #### Hot start:
40 | * Repro: Close app via the home button. Open app.
41 | * Initialization entry point is either `SplashActivity.onStart` or
42 | `BranchActivityLifecycleObserver.onResume` depending on whether `SplashActivity`
43 | or `NextActivity` was in foreground last. However, if app is opened via
44 | a push notification, the Initialization entry point is guaranteed to be
45 | `SplashActivity.onStart`.
46 |
47 |
48 | ### 2. Application in foreground
49 | ```
50 | Test by opening the app via:
51 | * push notification
52 | ```
53 | #### Burning hot start:
54 | * Repro: have the app open
55 | * Initialization entry point = either `SplashActivity.onNewIntent`
56 | or `SplashActivity.onStart` depending if user is currently on `SplashActivity`
57 | or `NextActivity` respectively. There is one exception, if the user is on
58 | `NextActivity` but `SplashActivity` is still partially visible, then the
59 | entry point will be `SplashActivity.onNewIntent`.
60 |
61 | There are four possible scenarios the users can find themselves in,
62 | `reInitSession` is either called or not and the user is currently in
63 | `SplashActivity` or in `NextActivity`. Note that documentation gives
64 | instructions to use `reInitSession`, however it's a new instruction, so
65 | it may be overlooked by existing users. When the latter happens, we may
66 | expect an initialization failure:
67 | * `reInitSession` is not used (i.e. not following documentation)
68 | * User is in `SplashActivity` = Branch initialization is guaranteed to FAIL
69 | * User is in `NextActivity` = Branch initialization is expected work _unless_
70 | `SplashActivity` is still partially visible (e.g. `NextActivity` is
71 | semi-transparent or is not using the full screen)
72 |
73 |
74 | ## Scenario #2:
75 | * `initSession` is called in both `SplashActivity` and `NextActivity`
76 |
77 | ### 1. Application in foreground
78 | ```
79 | Test by opening the app via push notification launching `NextActivity`:
80 | * when `NextActivity` is currently in foreground
81 | * when `NextActivity` is in backstack (e.g. has been launched before
82 | but user is currently on another `NextActivity`)
83 | * when `NextActivity` is NOT in backstack (e.g. this particular
84 | `NextActivity` has NOT been launched before)
85 | ```
86 |
87 | #### Burning hot start:
88 | * Repro: have the app open
89 |
90 | Again, there are expected failures when `reInitSession` is NOT used in `NextActivity`
91 | * user is currently in `NextActivity` = guaranteed initialization failure
92 | * `NextActivity` is in backstack BUT partially visible
--------------------------------------------------------------------------------
/Branch-SDK/src/main/java/io/branch/referral/BranchQRCodeCache.java:
--------------------------------------------------------------------------------
1 | package io.branch.referral;
2 |
3 | import android.content.Context;
4 |
5 | import org.json.JSONArray;
6 | import org.json.JSONException;
7 | import org.json.JSONObject;
8 |
9 | import java.util.HashMap;
10 | import java.util.HashSet;
11 | import java.util.Iterator;
12 | import java.util.Map;
13 | import java.util.Set;
14 | import java.util.concurrent.ConcurrentHashMap;
15 |
16 | public class BranchQRCodeCache {
17 |
18 | private final SystemObserver systemObserver_;
19 | private final Context context_;
20 |
21 | public ConcurrentHashMap cache = new ConcurrentHashMap<>();
22 |
23 | /**
24 | * Get the singleton instance for this class
25 | *
26 | * @return {@link BranchQRCodeCache} instance if already initialised or null
27 | */
28 | public static BranchQRCodeCache getInstance() {
29 | Branch b = Branch.getInstance();
30 | if (b == null) return null;
31 | return b.getBranchQRCodeCache();
32 | }
33 |
34 | BranchQRCodeCache(Context context) {
35 | context_ = context;
36 | systemObserver_ = new BranchQRCodeCache.SystemObserverInstance();
37 | }
38 |
39 | /**
40 | * Concrete SystemObserver implementation
41 | */
42 | private class SystemObserverInstance extends SystemObserver {
43 | public SystemObserverInstance() {
44 | super();
45 | }
46 | }
47 |
48 | /**
49 | * @return the current SystemObserver instance
50 | */
51 | SystemObserver getSystemObserver() {
52 | return systemObserver_;
53 | }
54 |
55 | //QR Code Caching Functions
56 | public void addQRCodeToCache(JSONObject parameters, byte[] qrCodeData) {
57 | cache.clear();
58 | try {
59 | parameters.getJSONObject("data").remove(Defines.Jsonkey.CreationTimestamp.getKey());
60 | cache.put(parameters, qrCodeData);
61 | } catch (JSONException e) {
62 | e.printStackTrace();
63 | }
64 | }
65 |
66 | public byte[] checkQRCodeCache(JSONObject parameters) {
67 | if (cache.isEmpty()) {
68 | return null;
69 | }
70 | try {
71 | parameters.getJSONObject("data").remove(Defines.Jsonkey.CreationTimestamp.getKey());
72 | JSONObject cacheParam = (JSONObject) cache.keySet().iterator().next();
73 |
74 | if (areEqual(parameters, cacheParam)) {
75 | return cache.get(cacheParam);
76 | } else {
77 | return null;
78 | }
79 | } catch (JSONException e) {
80 | e.printStackTrace();
81 | return null;
82 | }
83 | }
84 |
85 | //Helper Functions
86 | public static boolean areEqual(Object ob1, Object ob2) throws JSONException {
87 | Object obj1Converted = convertJsonElement(ob1);
88 | Object obj2Converted = convertJsonElement(ob2);
89 | return obj1Converted.equals(obj2Converted);
90 | }
91 |
92 | private static Object convertJsonElement(Object elem) throws JSONException {
93 | if (elem instanceof JSONObject) {
94 | JSONObject obj = (JSONObject) elem;
95 | Iterator keys = obj.keys();
96 | Map jsonMap = new HashMap<>();
97 | while (keys.hasNext()) {
98 | String key = keys.next();
99 | jsonMap.put(key, convertJsonElement(obj.get(key)));
100 | }
101 | return jsonMap;
102 | } else if (elem instanceof JSONArray) {
103 | JSONArray arr = (JSONArray) elem;
104 | Set