diff --git a/build.gradle b/build.gradle
index 9614486c..68f8c01c 100644
--- a/build.gradle
+++ b/build.gradle
@@ -20,9 +20,6 @@ buildscript {
repositories {
google()
jcenter()
- maven {
- url = "https://androidx.dev/snapshots/builds/12815573/artifacts/repository"
- }
}
dependencies {
classpath 'com.android.tools.build:gradle:8.7.3'
@@ -34,11 +31,6 @@ allprojects {
google()
jcenter()
- // AndroidX snapshots repository
- maven {
- url = "https://androidx.dev/snapshots/builds/12815573/artifacts/repository"
- }
-
// Repository for DexMaker
maven {
url = "https://linkedin.jfrog.io/artifactory/open-source/"
diff --git a/demos/custom-tabs-auth-tab/.gitignore b/demos/custom-tabs-auth-tab/.gitignore
new file mode 100644
index 00000000..796b96d1
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/demos/custom-tabs-auth-tab/build.gradle b/demos/custom-tabs-auth-tab/build.gradle
new file mode 100644
index 00000000..43fb98d4
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/build.gradle
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2024 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+apply plugin: 'com.android.application'
+
+android {
+ namespace 'com.google.androidbrowserhelper.demos.customtabsauthtab'
+ compileSdkVersion 35
+ defaultConfig {
+ applicationId "com.google.androidbrowserhelper.demos.customtabsauthtab"
+ minSdkVersion 26
+ targetSdkVersion 35
+ versionCode 1
+ versionName "1.0"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ }
+ }
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_17
+ targetCompatibility JavaVersion.VERSION_17
+ }
+}
+
+dependencies {
+ implementation project(path: ':androidbrowserhelper')
+ implementation fileTree(dir: "libs", include: ["*.jar"])
+ implementation 'androidx.appcompat:appcompat:1.7.0'
+ implementation 'androidx.activity:activity:1.9.3'
+ implementation 'androidx.browser:browser:1.9.0-alpha01'
+ implementation 'com.google.android.material:material:1.12.0'
+ implementation 'androidx.annotation:annotation:1.9.1'
+ implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
+}
diff --git a/demos/custom-tabs-auth-tab/src/main/AndroidManifest.xml b/demos/custom-tabs-auth-tab/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..828ba710
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/src/main/AndroidManifest.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demos/custom-tabs-auth-tab/src/main/java/com/google/androidbrowserhelper/demos/customtabsauthtab/AuthManager.java b/demos/custom-tabs-auth-tab/src/main/java/com/google/androidbrowserhelper/demos/customtabsauthtab/AuthManager.java
new file mode 100644
index 00000000..75755fcb
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/src/main/java/com/google/androidbrowserhelper/demos/customtabsauthtab/AuthManager.java
@@ -0,0 +1,106 @@
+package com.google.androidbrowserhelper.demos.customtabsauthtab;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.annotation.NonNull;
+import androidx.browser.auth.AuthTabIntent;
+import androidx.annotation.OptIn;
+import androidx.browser.auth.ExperimentalAuthTab;
+
+import java.io.IOException;
+import java.util.UUID;
+
+/**
+ * This class helps managing an authentication flow. It was created with the goal of demonstrating
+ * how to use Custom Tabs Auth Tab to handle auth and is not meant as a complete implementation
+ * of the OAuth protocol. We recommend checking out https://github.com/openid/AppAuth-Android for
+ * a comprehensive implementation of the OAuth protocol.
+ */
+
+@OptIn(markerClass = ExperimentalAuthTab.class)
+public class AuthManager {
+ private static final String TAG = "OAuthManager";
+
+ private final String mClientId;
+ private final String mClientSecret;
+ private final String mAuthorizationEndpoint;
+ private final String mRedirectScheme;
+
+ public interface OAuthCallback {
+ void auth(String accessToken, String scope, String tokenType);
+ }
+
+ public AuthManager(String clientId, String clientSecret, String authorizationEndpoint,
+ String redirectScheme) {
+ mClientId = clientId;
+ mClientSecret = clientSecret;
+ mAuthorizationEndpoint = authorizationEndpoint;
+ mRedirectScheme = redirectScheme;
+ }
+
+ public void authorize(Context context, ActivityResultLauncher launcher, String scope) {
+ // Generate a random state.
+ String state = UUID.randomUUID().toString();
+
+ // Save the state so we can verify later.
+ SharedPreferences preferences =
+ context.getSharedPreferences("OAUTH_STORAGE", Context.MODE_PRIVATE);
+ preferences.edit()
+ .putString("OAUTH_STATE", state)
+ .apply();
+
+ // Create an authorization URI to the OAuth Endpoint.
+ Uri uri = Uri.parse(mAuthorizationEndpoint)
+ .buildUpon()
+ .appendQueryParameter("response_type", "code")
+ .appendQueryParameter("client_id", mClientId)
+ .appendQueryParameter("scope", scope)
+ .appendQueryParameter("state", state)
+ .build();
+
+ // Open the Authorization URI in a Chrome Custom Auth Tab.
+ AuthTabIntent authTabIntent = new AuthTabIntent.Builder().build();
+ authTabIntent.launch(launcher, uri, mRedirectScheme);
+ }
+
+ public void continueAuthFlow(@NonNull Context context, Uri uri, @NonNull OAuthCallback callback) {
+ String code = uri.getQueryParameter("code");
+ SharedPreferences preferences =
+ context.getSharedPreferences("OAUTH_STORAGE", Context.MODE_PRIVATE);
+ String state = preferences.getString("OAUTH_STATE", "");
+ Uri tokenUri = Uri.parse("https://github.com/login/oauth/access_token")
+ .buildUpon()
+ .appendQueryParameter("client_id", mClientId)
+ .appendQueryParameter("client_secret", mClientSecret)
+ .appendQueryParameter("code", code)
+ .appendQueryParameter("state", state)
+ .build();
+
+ // Run the network request off the UI thread.
+ new Thread(() -> {
+ try {
+ String response = Utils.fetch(tokenUri);
+ // The response is a query-string. We concatenate with a valid domain to be
+ // able to easily parse and extract values.
+ Uri responseUri = Uri.parse("http://example.com?" + response);
+ String accessToken = responseUri.getQueryParameter("access_token");
+ String tokenType = responseUri.getQueryParameter("token_type");
+ String scope = responseUri.getQueryParameter("scope");
+
+ // Invoke the callback in the main thread.
+ new Handler(Looper.getMainLooper()).post(
+ () -> callback.auth(accessToken, scope, tokenType));
+
+ } catch (IOException e) {
+ Log.e(TAG, "Error requesting access token: " + e.getMessage());
+ }
+ }).start();
+ }
+}
diff --git a/demos/custom-tabs-auth-tab/src/main/java/com/google/androidbrowserhelper/demos/customtabsauthtab/GithubApi.java b/demos/custom-tabs-auth-tab/src/main/java/com/google/androidbrowserhelper/demos/customtabsauthtab/GithubApi.java
new file mode 100644
index 00000000..1d62cdca
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/src/main/java/com/google/androidbrowserhelper/demos/customtabsauthtab/GithubApi.java
@@ -0,0 +1,43 @@
+package com.google.androidbrowserhelper.demos.customtabsauthtab;
+
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.Log;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+
+public class GithubApi {
+ private static final String TAG = "GithubAPI";
+ private static final String API_ENDPOINT = "https://api.github.com/user";
+ private static final String AUTH_HEADER_KEY = "Authorization";
+
+ public interface UserCallback {
+ void onUserData(String username);
+ }
+
+ public static void requestGithubUsername(String token, UserCallback callback) {
+ new Thread(() -> {
+ try {
+ Uri uri = Uri.parse(API_ENDPOINT);
+ Map headers =
+ Collections.singletonMap(AUTH_HEADER_KEY, "token " + token);
+ String response = Utils.fetch(uri, headers);
+ JSONObject user = new JSONObject(response);
+ String username = user.getString("name");
+
+ // Invoke the callback in the main thread.
+ new Handler(Looper.getMainLooper()).post(() -> {
+ callback.onUserData(username);
+ });
+ } catch (IOException | JSONException ex) {
+ Log.e(TAG, "Error fetching GitHub user: " + ex.getMessage());
+ }
+ }).start();
+ }
+}
diff --git a/demos/custom-tabs-auth-tab/src/main/java/com/google/androidbrowserhelper/demos/customtabsauthtab/MainActivity.java b/demos/custom-tabs-auth-tab/src/main/java/com/google/androidbrowserhelper/demos/customtabsauthtab/MainActivity.java
new file mode 100644
index 00000000..3e4e1a75
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/src/main/java/com/google/androidbrowserhelper/demos/customtabsauthtab/MainActivity.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2024 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.androidbrowserhelper.demos.customtabsauthtab;
+
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import androidx.activity.result.ActivityResultLauncher;
+import androidx.annotation.OptIn;
+import androidx.appcompat.app.AppCompatActivity;
+import androidx.browser.auth.AuthTabIntent;
+import androidx.browser.auth.ExperimentalAuthTab;
+
+@OptIn(markerClass = ExperimentalAuthTab.class)
+public class MainActivity extends AppCompatActivity {
+ private static final String TAG = "MainActivity";
+
+ private static final String AUTHORIZATION_ENDPOINT = "https://github.com/login/oauth/authorize";
+ private static final String CLIENT_ID = "";
+ private static final String CLIENT_SECRET = "";
+ private static final String REDIRECT_SCHEME = "auth";
+
+ private static final AuthManager O_AUTH_MANAGER =
+ new AuthManager(CLIENT_ID, CLIENT_SECRET, AUTHORIZATION_ENDPOINT, REDIRECT_SCHEME);
+
+ private final ActivityResultLauncher mLauncher =
+ AuthTabIntent.registerActivityResultLauncher(this, this::handleAuthResult);
+
+ private Button mLoginButton;
+ private TextView mUserText;
+ private ProgressBar mProgressBar;
+ private boolean mLoggedIn;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+
+ mLoginButton = findViewById(R.id.login_button);
+ mUserText = findViewById(R.id.user_text);
+ mProgressBar = findViewById(R.id.progress_bar);
+
+ Intent intent = getIntent();
+ if (intent != null) {
+ Uri data = intent.getData();
+ if (data != null && data.getHost() != null
+ && data.getHost().startsWith("callback")) {
+ mProgressBar.setVisibility(View.VISIBLE);
+ mLoginButton.setEnabled(false);
+ completeAuth(data);
+ }
+ }
+ }
+
+ public void login(View v) {
+ if (mLoggedIn) {
+ mLoginButton.setText(R.string.login);
+ mUserText.setText(R.string.logged_out);
+ mLoggedIn = false;
+ } else {
+ O_AUTH_MANAGER.authorize(this, mLauncher, "user");
+ }
+ }
+
+ private void handleAuthResult(AuthTabIntent.AuthResult result) {
+ if (result.resultCode == AuthTabIntent.RESULT_OK) {
+ completeAuth(result.resultUri);
+ }
+ }
+
+ private void completeAuth(Uri uri) {
+ O_AUTH_MANAGER.continueAuthFlow(this, uri, (accessToken, scope, tokenType) -> {
+ GithubApi.requestGithubUsername(accessToken, (username -> {
+ mLoginButton.setText(R.string.logout);
+ mLoginButton.setEnabled(true);
+ mProgressBar.setVisibility(View.INVISIBLE);
+ mUserText.setText(getString(R.string.logged_in, username));
+ mLoggedIn = true;
+ }));
+ });
+ }
+}
\ No newline at end of file
diff --git a/demos/custom-tabs-auth-tab/src/main/java/com/google/androidbrowserhelper/demos/customtabsauthtab/Utils.java b/demos/custom-tabs-auth-tab/src/main/java/com/google/androidbrowserhelper/demos/customtabsauthtab/Utils.java
new file mode 100644
index 00000000..ebd29121
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/src/main/java/com/google/androidbrowserhelper/demos/customtabsauthtab/Utils.java
@@ -0,0 +1,49 @@
+package com.google.androidbrowserhelper.demos.customtabsauthtab;
+
+import android.net.Uri;
+
+import androidx.annotation.NonNull;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Map;
+
+public class Utils {
+ public static String fetch(@NonNull Uri uri) throws IOException {
+ return fetch(uri, Collections.emptyMap());
+ }
+
+ public static String fetch(@NonNull Uri uri, Map headers) throws IOException {
+ HttpURLConnection connection = null;
+ try {
+ URL url = new URL(uri.toString());
+ connection = (HttpURLConnection)url.openConnection();
+ for(Map.Entry entry: headers.entrySet()) {
+ connection.setRequestProperty(entry.getKey(), entry.getValue());
+ }
+ connection.setDoOutput(true);
+ return inputStreamToString(connection.getInputStream());
+ } finally {
+ if (connection != null) {
+ connection.disconnect();
+ }
+ }
+ }
+
+ @NonNull
+ public static String inputStreamToString(@NonNull InputStream inputStream) throws IOException {
+ try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
+ String line;
+ StringBuilder builder = new StringBuilder();
+ while ((line = reader.readLine()) != null) {
+ builder.append(line).append('\n');
+ }
+ return builder.toString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/demos/custom-tabs-auth-tab/src/main/res/drawable/ic_launcher_background.xml b/demos/custom-tabs-auth-tab/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 00000000..9e983cb3
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,171 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/demos/custom-tabs-auth-tab/src/main/res/drawable/ic_launcher_foreground.xml b/demos/custom-tabs-auth-tab/src/main/res/drawable/ic_launcher_foreground.xml
new file mode 100644
index 00000000..9be1fda8
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/src/main/res/drawable/ic_launcher_foreground.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demos/custom-tabs-auth-tab/src/main/res/layout/activity_main.xml b/demos/custom-tabs-auth-tab/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..ad1f1ec3
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/src/main/res/layout/activity_main.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
diff --git a/demos/custom-tabs-auth-tab/src/main/res/mipmap-anydpi/ic_launcher.xml b/demos/custom-tabs-auth-tab/src/main/res/mipmap-anydpi/ic_launcher.xml
new file mode 100644
index 00000000..6f3b755b
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/src/main/res/mipmap-anydpi/ic_launcher.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demos/custom-tabs-auth-tab/src/main/res/mipmap-anydpi/ic_launcher_round.xml b/demos/custom-tabs-auth-tab/src/main/res/mipmap-anydpi/ic_launcher_round.xml
new file mode 100644
index 00000000..6f3b755b
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/src/main/res/mipmap-anydpi/ic_launcher_round.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demos/custom-tabs-auth-tab/src/main/res/mipmap-hdpi/ic_launcher.webp b/demos/custom-tabs-auth-tab/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 00000000..c209e78e
Binary files /dev/null and b/demos/custom-tabs-auth-tab/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/demos/custom-tabs-auth-tab/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/demos/custom-tabs-auth-tab/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..b2dfe3d1
Binary files /dev/null and b/demos/custom-tabs-auth-tab/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/demos/custom-tabs-auth-tab/src/main/res/mipmap-mdpi/ic_launcher.webp b/demos/custom-tabs-auth-tab/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 00000000..4f0f1d64
Binary files /dev/null and b/demos/custom-tabs-auth-tab/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/demos/custom-tabs-auth-tab/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/demos/custom-tabs-auth-tab/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..62b611da
Binary files /dev/null and b/demos/custom-tabs-auth-tab/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/demos/custom-tabs-auth-tab/src/main/res/mipmap-xhdpi/ic_launcher.webp b/demos/custom-tabs-auth-tab/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 00000000..948a3070
Binary files /dev/null and b/demos/custom-tabs-auth-tab/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/demos/custom-tabs-auth-tab/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/demos/custom-tabs-auth-tab/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..1b9a6956
Binary files /dev/null and b/demos/custom-tabs-auth-tab/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/demos/custom-tabs-auth-tab/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/demos/custom-tabs-auth-tab/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..28d4b77f
Binary files /dev/null and b/demos/custom-tabs-auth-tab/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/demos/custom-tabs-auth-tab/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/demos/custom-tabs-auth-tab/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9287f508
Binary files /dev/null and b/demos/custom-tabs-auth-tab/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/demos/custom-tabs-auth-tab/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/demos/custom-tabs-auth-tab/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..aa7d6427
Binary files /dev/null and b/demos/custom-tabs-auth-tab/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/demos/custom-tabs-auth-tab/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/demos/custom-tabs-auth-tab/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9126ae37
Binary files /dev/null and b/demos/custom-tabs-auth-tab/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/demos/custom-tabs-auth-tab/src/main/res/values-night/themes.xml b/demos/custom-tabs-auth-tab/src/main/res/values-night/themes.xml
new file mode 100644
index 00000000..bbcbc94f
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/src/main/res/values-night/themes.xml
@@ -0,0 +1,7 @@
+
+
+
+
\ No newline at end of file
diff --git a/demos/custom-tabs-auth-tab/src/main/res/values/colors.xml b/demos/custom-tabs-auth-tab/src/main/res/values/colors.xml
new file mode 100644
index 00000000..03bda374
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/src/main/res/values/colors.xml
@@ -0,0 +1,18 @@
+
+
+
+ #6200EE
+ #3700B3
+ #03DAC5
+
diff --git a/demos/custom-tabs-auth-tab/src/main/res/values/strings.xml b/demos/custom-tabs-auth-tab/src/main/res/values/strings.xml
new file mode 100644
index 00000000..520cf405
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/src/main/res/values/strings.xml
@@ -0,0 +1,20 @@
+
+
+
+ Custom Auth Tab OAuth
+ You are not logged in.
+ Hello, %s.
+ login
+ logout
+
diff --git a/demos/custom-tabs-auth-tab/src/main/res/values/themes.xml b/demos/custom-tabs-auth-tab/src/main/res/values/themes.xml
new file mode 100644
index 00000000..18744301
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/src/main/res/values/themes.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/demos/custom-tabs-auth-tab/src/main/res/xml/backup_rules.xml b/demos/custom-tabs-auth-tab/src/main/res/xml/backup_rules.xml
new file mode 100644
index 00000000..75dd5113
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/src/main/res/xml/backup_rules.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/demos/custom-tabs-auth-tab/src/main/res/xml/data_extraction_rules.xml b/demos/custom-tabs-auth-tab/src/main/res/xml/data_extraction_rules.xml
new file mode 100644
index 00000000..a73ffe12
--- /dev/null
+++ b/demos/custom-tabs-auth-tab/src/main/res/xml/data_extraction_rules.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demos/custom-tabs-ephemeral-with-fallback/build.gradle b/demos/custom-tabs-ephemeral-with-fallback/build.gradle
index 010a0edd..ef0722b0 100644
--- a/demos/custom-tabs-ephemeral-with-fallback/build.gradle
+++ b/demos/custom-tabs-ephemeral-with-fallback/build.gradle
@@ -45,7 +45,7 @@ dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'androidx.activity:activity:1.9.3'
- implementation 'androidx.browser:browser:1.9.0-SNAPSHOT'
+ implementation 'androidx.browser:browser:1.9.0-alpha01'
implementation 'com.google.android.material:material:1.12.0'
implementation 'androidx.annotation:annotation:1.9.1'
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
diff --git a/demos/custom-tabs-ephemeral/build.gradle b/demos/custom-tabs-ephemeral/build.gradle
index c11649a9..d63597ed 100644
--- a/demos/custom-tabs-ephemeral/build.gradle
+++ b/demos/custom-tabs-ephemeral/build.gradle
@@ -45,7 +45,7 @@ dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'androidx.activity:activity:1.9.3'
- implementation 'androidx.browser:browser:1.9.0-SNAPSHOT'
+ implementation 'androidx.browser:browser:1.9.0-alpha01'
implementation 'com.google.android.material:material:1.12.0'
implementation 'androidx.annotation:annotation:1.9.1'
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
diff --git a/demos/custom-tabs-oauth/readme.md b/demos/custom-tabs-oauth/readme.md
new file mode 100644
index 00000000..7395be8c
--- /dev/null
+++ b/demos/custom-tabs-oauth/readme.md
@@ -0,0 +1,2 @@
+This demo is deprecated but is retained for historical purposes.
+Please use the Auth Tab demo found in demo/custom-tabs-auth-tab.
\ No newline at end of file
diff --git a/demos/custom-tabs-oauth/src/main/java/com/google/androidbrowserhelper/demos/customtabsoauth/MainActivity.java b/demos/custom-tabs-oauth/src/main/java/com/google/androidbrowserhelper/demos/customtabsoauth/MainActivity.java
index 97dfe906..96e76557 100644
--- a/demos/custom-tabs-oauth/src/main/java/com/google/androidbrowserhelper/demos/customtabsoauth/MainActivity.java
+++ b/demos/custom-tabs-oauth/src/main/java/com/google/androidbrowserhelper/demos/customtabsoauth/MainActivity.java
@@ -25,6 +25,11 @@
import android.widget.ProgressBar;
import android.widget.TextView;
+@Deprecated
+/*
+ * This sample is deprecated and retained for historical purposes only.
+ * Instead use Auth Tab demo found in demos/custom-tabs-auth-tab.
+ */
public class MainActivity extends Activity {
private static final String AUTHORIZATION_ENDPOINT = "https://github.com/login/oauth/authorize";
private static final String CLIENT_ID = "";
diff --git a/demos/custom-tabs-oauth/src/main/java/com/google/androidbrowserhelper/demos/customtabsoauth/OAuthManager.java b/demos/custom-tabs-oauth/src/main/java/com/google/androidbrowserhelper/demos/customtabsoauth/OAuthManager.java
index decc129a..dcc7658b 100644
--- a/demos/custom-tabs-oauth/src/main/java/com/google/androidbrowserhelper/demos/customtabsoauth/OAuthManager.java
+++ b/demos/custom-tabs-oauth/src/main/java/com/google/androidbrowserhelper/demos/customtabsoauth/OAuthManager.java
@@ -15,11 +15,10 @@
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-/**
- * This class helps managing an OAuth flow. It was created with the goal of demonstrating how to
- * use Custom Tabs to handle the authorization flow and is not meant as a complete implementation
- * of the OAuth protocol. We recommend checking out https://github.com/openid/AppAuth-Android for
- * a comprehensive implementation of the OAuth protocol.
+@Deprecated
+/*
+ * This sample is deprecated and retained for historical purposes only.
+ * Instead use Auth Tab demo found in demos/custom-tabs-auth-tab.
*/
public class OAuthManager {
private static final String TAG = "OAuthManager";
diff --git a/settings.gradle b/settings.gradle
index 56d15026..a0c64ef5 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -6,6 +6,7 @@ include ':demos:custom-tabs-example-app'
include ':demos:custom-tabs-headers'
include ':demos:custom-tabs-navigation-callbacks'
include ':demos:custom-tabs-oauth'
+include ':demos:custom-tabs-auth-tab'
include ':demos:custom-tabs-ephemeral-with-fallback'
include ':demos:custom-tabs-ephemeral'
include ':demos:custom-tabs-session'