From 18aec38d9f4d79afe0748b4bae1dfe11a3ee24ef Mon Sep 17 00:00:00 2001
From: Docile-Alligator <25734209+Docile-Alligator@users.noreply.github.com>
Date: Thu, 23 May 2024 16:12:44 -0400
Subject: Bare bone login using Chrome custom tab.
---
app/build.gradle | 1 +
app/src/main/AndroidManifest.xml | 36 ++-
.../infinityforreddit/AppComponent.java | 3 +
.../activities/LoginActivity.java | 35 +--
.../activities/LoginChromeCustomTabActivity.java | 247 +++++++++++++++++++++
.../infinityforreddit/activities/MainActivity.java | 25 +--
.../events/NewUserLoggedInEvent.java | 4 +
.../layout/activity_login_chrome_custom_tab.xml | 10 +
8 files changed, 318 insertions(+), 43 deletions(-)
create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/activities/LoginChromeCustomTabActivity.java
create mode 100644 app/src/main/java/ml/docilealligator/infinityforreddit/events/NewUserLoggedInEvent.java
create mode 100644 app/src/main/res/layout/activity_login_chrome_custom_tab.xml
diff --git a/app/build.gradle b/app/build.gradle
index 8d094fd7..ed6f7d07 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -63,6 +63,7 @@ dependencies {
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+ implementation 'androidx.activity:activity:1.8.0'
def lifecycleVersion = "2.7.0"
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycleVersion"
implementation "androidx.lifecycle:lifecycle-livedata:$lifecycleVersion"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 17929a31..6c533f12 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -34,23 +34,42 @@
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"
tools:replace="android:label">
+
+
+
+
+
+
+
+
+
+
+
+
+ android:theme="@style/AppTheme.NoActionBar" />
+ android:theme="@style/AppTheme.NoActionBar" />
+ android:theme="@style/AppTheme.NoActionBar" />
-
{
- new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme)
- .setTitle(R.string.have_trouble_login_title)
- .setMessage(R.string.have_trouble_login_message)
- .setPositiveButton(R.string.yes, (dialogInterface, i) -> {
- enableDom = !enableDom;
- ActivityCompat.recreate(this);
- })
- .setNegativeButton(R.string.no, null)
- .show();
- });
-
if (enableDom) {
binding.twoFaInfOTextViewLoginActivity.setVisibility(View.GONE);
}
@@ -144,6 +132,22 @@ public class LoginActivity extends BaseActivity {
String url = uriBuilder.toString();
+ binding.fabLoginActivity.setOnClickListener(view -> {
+ /*new MaterialAlertDialogBuilder(this, R.style.MaterialAlertDialogTheme)
+ .setTitle(R.string.have_trouble_login_title)
+ .setMessage(R.string.have_trouble_login_message)
+ .setPositiveButton(R.string.yes, (dialogInterface, i) -> {
+ enableDom = !enableDom;
+ ActivityCompat.recreate(this);
+ })
+ .setNegativeButton(R.string.no, null)
+ .show();*/
+
+ Intent intent = new Intent(this, LoginChromeCustomTabActivity.class);
+ startActivity(intent);
+ finish();
+ });
+
CookieManager.getInstance().removeAllCookies(aBoolean -> {
});
@@ -190,8 +194,7 @@ public class LoginActivity extends BaseActivity {
ParseAndInsertNewAccount.parseAndInsertNewAccount(mExecutor, new Handler(), name, accessToken, refreshToken, profileImageUrl, bannerImageUrl,
karma, authCode, mRedditDataRoomDatabase.accountDao(),
() -> {
- Intent resultIntent = new Intent();
- setResult(Activity.RESULT_OK, resultIntent);
+ EventBus.getDefault().post(new NewUserLoggedInEvent());
finish();
});
}
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/LoginChromeCustomTabActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/LoginChromeCustomTabActivity.java
new file mode 100644
index 00000000..84c06ea6
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/LoginChromeCustomTabActivity.java
@@ -0,0 +1,247 @@
+package ml.docilealligator.infinityforreddit.activities;
+
+import android.content.ActivityNotFoundException;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.widget.Toast;
+
+import androidx.activity.EdgeToEdge;
+import androidx.annotation.NonNull;
+import androidx.browser.customtabs.CustomTabColorSchemeParams;
+import androidx.browser.customtabs.CustomTabsIntent;
+import androidx.browser.customtabs.CustomTabsService;
+import androidx.core.graphics.Insets;
+import androidx.core.view.ViewCompat;
+import androidx.core.view.WindowInsetsCompat;
+
+import org.greenrobot.eventbus.EventBus;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executor;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import ml.docilealligator.infinityforreddit.FetchMyInfo;
+import ml.docilealligator.infinityforreddit.Infinity;
+import ml.docilealligator.infinityforreddit.R;
+import ml.docilealligator.infinityforreddit.RedditDataRoomDatabase;
+import ml.docilealligator.infinityforreddit.apis.RedditAPI;
+import ml.docilealligator.infinityforreddit.asynctasks.ParseAndInsertNewAccount;
+import ml.docilealligator.infinityforreddit.customtheme.CustomThemeWrapper;
+import ml.docilealligator.infinityforreddit.events.NewUserLoggedInEvent;
+import ml.docilealligator.infinityforreddit.utils.APIUtils;
+import ml.docilealligator.infinityforreddit.utils.SharedPreferencesUtils;
+import retrofit2.Call;
+import retrofit2.Callback;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+
+public class LoginChromeCustomTabActivity extends BaseActivity {
+
+ @Inject
+ @Named("no_oauth")
+ Retrofit mRetrofit;
+ @Inject
+ @Named("oauth")
+ Retrofit mOauthRetrofit;
+ @Inject
+ RedditDataRoomDatabase mRedditDataRoomDatabase;
+ @Inject
+ @Named("default")
+ SharedPreferences mSharedPreferences;
+ @Inject
+ @Named("current_account")
+ SharedPreferences mCurrentAccountSharedPreferences;
+ @Inject
+ CustomThemeWrapper mCustomThemeWrapper;
+ @Inject
+ Executor mExecutor;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ ((Infinity) getApplication()).getAppComponent().inject(this);
+
+ super.onCreate(savedInstanceState);
+ EdgeToEdge.enable(this);
+ setContentView(R.layout.activity_login_chrome_custom_tab);
+ ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
+ Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
+ v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
+ return insets;
+ });
+
+ applyCustomTheme();
+
+ ArrayList resolveInfos = getCustomTabsPackages(getPackageManager());
+ if (!resolveInfos.isEmpty()) {
+ CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder();
+ // add share action to menu list
+ builder.setShareState(CustomTabsIntent.SHARE_STATE_ON);
+ builder.setDefaultColorSchemeParams(
+ new CustomTabColorSchemeParams.Builder()
+ .setToolbarColor(mCustomThemeWrapper.getColorPrimary())
+ .build());
+ CustomTabsIntent customTabsIntent = builder.build();
+ customTabsIntent.intent.setPackage(resolveInfos.get(0).activityInfo.packageName);
+ customTabsIntent.intent.putExtra("com.google.android.apps.chrome.EXTRA_OPEN_NEW_INCOGNITO_TAB", true);
+
+ try {
+ Uri.Builder uriBuilder = Uri.parse(APIUtils.OAUTH_URL).buildUpon();
+ uriBuilder.appendQueryParameter(APIUtils.CLIENT_ID_KEY, APIUtils.CLIENT_ID);
+ uriBuilder.appendQueryParameter(APIUtils.RESPONSE_TYPE_KEY, APIUtils.RESPONSE_TYPE);
+ uriBuilder.appendQueryParameter(APIUtils.STATE_KEY, APIUtils.STATE);
+ uriBuilder.appendQueryParameter(APIUtils.REDIRECT_URI_KEY, APIUtils.REDIRECT_URI);
+ uriBuilder.appendQueryParameter(APIUtils.DURATION_KEY, APIUtils.DURATION);
+ uriBuilder.appendQueryParameter(APIUtils.SCOPE_KEY, APIUtils.SCOPE);
+
+ customTabsIntent.launchUrl(this, uriBuilder.build());
+ } catch (ActivityNotFoundException e) {
+ // TODO catch this
+ }
+ }
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+
+ Uri uri = intent.getData();
+ if (uri == null) {
+ return;
+ }
+
+ String authCode = uri.getQueryParameter("code");
+ if (authCode != null) {
+ String state = uri.getQueryParameter("state");
+ if (APIUtils.STATE.equals(state)) {
+ Map params = new HashMap<>();
+ params.put(APIUtils.GRANT_TYPE_KEY, "authorization_code");
+ params.put("code", authCode);
+ params.put(APIUtils.REDIRECT_URI_KEY, APIUtils.REDIRECT_URI);
+
+ RedditAPI api = mRetrofit.create(RedditAPI.class);
+ Call accessTokenCall = api.getAccessToken(APIUtils.getHttpBasicAuthHeader(), params);
+ accessTokenCall.enqueue(new Callback<>() {
+ @Override
+ public void onResponse(@NonNull Call call, @NonNull Response response) {
+ if (response.isSuccessful()) {
+ try {
+ String accountResponse = response.body();
+ if (accountResponse == null) {
+ //Handle error
+ return;
+ }
+
+ JSONObject responseJSON = new JSONObject(accountResponse);
+ String accessToken = responseJSON.getString(APIUtils.ACCESS_TOKEN_KEY);
+ String refreshToken = responseJSON.getString(APIUtils.REFRESH_TOKEN_KEY);
+
+ FetchMyInfo.fetchAccountInfo(mOauthRetrofit, mRedditDataRoomDatabase,
+ accessToken, new FetchMyInfo.FetchMyInfoListener() {
+ @Override
+ public void onFetchMyInfoSuccess(String name, String profileImageUrl, String bannerImageUrl, int karma) {
+ mCurrentAccountSharedPreferences.edit().putString(SharedPreferencesUtils.ACCESS_TOKEN, accessToken)
+ .putString(SharedPreferencesUtils.ACCOUNT_NAME, name)
+ .putString(SharedPreferencesUtils.ACCOUNT_IMAGE_URL, profileImageUrl).apply();
+ mCurrentAccountSharedPreferences.edit().remove(SharedPreferencesUtils.SUBSCRIBED_THINGS_SYNC_TIME).apply();
+ ParseAndInsertNewAccount.parseAndInsertNewAccount(mExecutor, new Handler(), name, accessToken, refreshToken, profileImageUrl, bannerImageUrl,
+ karma, authCode, mRedditDataRoomDatabase.accountDao(),
+ () -> {
+ EventBus.getDefault().post(new NewUserLoggedInEvent());
+ finish();
+ });
+ }
+
+ @Override
+ public void onFetchMyInfoFailed(boolean parseFailed) {
+ if (parseFailed) {
+ Toast.makeText(LoginChromeCustomTabActivity.this, R.string.parse_user_info_error, Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(LoginChromeCustomTabActivity.this, R.string.cannot_fetch_user_info, Toast.LENGTH_SHORT).show();
+ }
+
+ finish();
+ }
+ });
+ } catch (JSONException e) {
+ e.printStackTrace();
+ Toast.makeText(LoginChromeCustomTabActivity.this, R.string.parse_json_response_error, Toast.LENGTH_SHORT).show();
+ finish();
+ }
+ } else {
+ Toast.makeText(LoginChromeCustomTabActivity.this, R.string.retrieve_token_error, Toast.LENGTH_SHORT).show();
+ finish();
+ }
+ }
+
+ @Override
+ public void onFailure(@NonNull Call call, @NonNull Throwable t) {
+ Toast.makeText(LoginChromeCustomTabActivity.this, R.string.retrieve_token_error, Toast.LENGTH_SHORT).show();
+ t.printStackTrace();
+ finish();
+ }
+ });
+ } else {
+ Toast.makeText(this, R.string.something_went_wrong, Toast.LENGTH_SHORT).show();
+ finish();
+ }
+
+ } else if ("access_denied".equals(uri.getQueryParameter("error"))) {
+ Toast.makeText(this, R.string.access_denied, Toast.LENGTH_SHORT).show();
+ finish();
+ }
+ }
+
+ @Override
+ public SharedPreferences getDefaultSharedPreferences() {
+ return mSharedPreferences;
+ }
+
+ @Override
+ public SharedPreferences getCurrentAccountSharedPreferences() {
+ return mCurrentAccountSharedPreferences;
+ }
+
+ @Override
+ public CustomThemeWrapper getCustomThemeWrapper() {
+ return mCustomThemeWrapper;
+ }
+
+ @Override
+ protected void applyCustomTheme() {
+
+ }
+
+ private ArrayList getCustomTabsPackages(PackageManager pm) {
+ // Get default VIEW intent handler.
+ Intent activityIntent = new Intent()
+ .setAction(Intent.ACTION_VIEW)
+ .addCategory(Intent.CATEGORY_BROWSABLE)
+ .setData(Uri.fromParts("http", "", null));
+
+ // Get all apps that can handle VIEW intents.
+ List resolvedActivityList = pm.queryIntentActivities(activityIntent, 0);
+ ArrayList packagesSupportingCustomTabs = new ArrayList<>();
+ for (ResolveInfo info : resolvedActivityList) {
+ Intent serviceIntent = new Intent();
+ serviceIntent.setAction(CustomTabsService.ACTION_CUSTOM_TABS_CONNECTION);
+ serviceIntent.setPackage(info.activityInfo.packageName);
+ // Check if this package also resolves the Custom Tabs service.
+ if (pm.resolveService(serviceIntent, 0) != null) {
+ packagesSupportingCustomTabs.add(info);
+ }
+ }
+ return packagesSupportingCustomTabs;
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/MainActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/MainActivity.java
index aee81c32..b07f7a92 100644
--- a/app/src/main/java/ml/docilealligator/infinityforreddit/activities/MainActivity.java
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/activities/MainActivity.java
@@ -4,7 +4,6 @@ import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO;
import static androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES;
import android.Manifest;
-import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
@@ -101,6 +100,7 @@ import ml.docilealligator.infinityforreddit.events.ChangeLockBottomAppBarEvent;
import ml.docilealligator.infinityforreddit.events.ChangeNSFWEvent;
import ml.docilealligator.infinityforreddit.events.ChangeRequireAuthToAccountSectionEvent;
import ml.docilealligator.infinityforreddit.events.ChangeShowAvatarOnTheRightInTheNavigationDrawerEvent;
+import ml.docilealligator.infinityforreddit.events.NewUserLoggedInEvent;
import ml.docilealligator.infinityforreddit.events.RecreateActivityEvent;
import ml.docilealligator.infinityforreddit.events.SwitchAccountEvent;
import ml.docilealligator.infinityforreddit.fragments.PostFragment;
@@ -141,8 +141,6 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb
private static final String NEW_ACCOUNT_NAME_STATE = "NANS";
private static final String INBOX_COUNT_STATE = "ICS";
- private static final int LOGIN_ACTIVITY_REQUEST_CODE = 0;
-
MultiRedditViewModel multiRedditViewModel;
SubscribedSubredditViewModel subscribedSubredditViewModel;
AccountViewModel accountViewModel;
@@ -798,8 +796,7 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb
} else if (stringId == R.string.settings) {
intent = new Intent(MainActivity.this, SettingsActivity.class);
} else if (stringId == R.string.add_account) {
- Intent addAccountIntent = new Intent(MainActivity.this, LoginActivity.class);
- startActivityForResult(addAccountIntent, LOGIN_ACTIVITY_REQUEST_CODE);
+ intent = new Intent(MainActivity.this, LoginActivity.class);
} else if (stringId == R.string.anonymous_account) {
SwitchToAnonymousMode.switchToAnonymousMode(mRedditDataRoomDatabase, mCurrentAccountSharedPreferences,
mExecutor, new Handler(), false, () -> {
@@ -1046,17 +1043,6 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb
}
}
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == LOGIN_ACTIVITY_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
- Intent intent = new Intent(this, MainActivity.class);
- startActivity(intent);
- finish();
- }
-
- super.onActivityResult(requestCode, resultCode, data);
- }
-
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_activity, menu);
@@ -1290,6 +1276,13 @@ public class MainActivity extends BaseActivity implements SortTypeSelectionCallb
navigationWrapper.floatingActionButton.setVisibility(hideFab ? View.GONE : View.VISIBLE);
}
+ @Subscribe
+ public void onNewUserLoggedInEvent(NewUserLoggedInEvent event) {
+ Intent intent = new Intent(this, MainActivity.class);
+ startActivity(intent);
+ finish();
+ }
+
@Override
public void onLongPress() {
if (sectionsPagerAdapter != null) {
diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/events/NewUserLoggedInEvent.java b/app/src/main/java/ml/docilealligator/infinityforreddit/events/NewUserLoggedInEvent.java
new file mode 100644
index 00000000..9e729270
--- /dev/null
+++ b/app/src/main/java/ml/docilealligator/infinityforreddit/events/NewUserLoggedInEvent.java
@@ -0,0 +1,4 @@
+package ml.docilealligator.infinityforreddit.events;
+
+public class NewUserLoggedInEvent {
+}
diff --git a/app/src/main/res/layout/activity_login_chrome_custom_tab.xml b/app/src/main/res/layout/activity_login_chrome_custom_tab.xml
new file mode 100644
index 00000000..534433ff
--- /dev/null
+++ b/app/src/main/res/layout/activity_login_chrome_custom_tab.xml
@@ -0,0 +1,10 @@
+
+
+
+
\ No newline at end of file
--
cgit v1.2.3