Skip to content

Commit b2c936c

Browse files
committed
Resetting the token and starting authenticator, upon error message "Bad credentials".
1 parent 92dde01 commit b2c936c

File tree

8 files changed

+67
-38
lines changed

8 files changed

+67
-38
lines changed

mobile/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
<!-- Permissions: Lollipop MR1 -->
1818
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" android:maxSdkVersion="22"/>
19+
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" android:maxSdkVersion="22"/>
1920
<uses-permission android:name="android.permission.USE_CREDENTIALS" android:maxSdkVersion="22"/>
2021

2122
<application

mobile/src/main/java/io/syslogic/github/activity/BaseActivity.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis
5757
}
5858

5959
public void setMenuProvider(@NonNull BaseMenuProvider menuProvider) {
60-
if (mMenuProvider != null) {removeMenuProvider(mMenuProvider);}
60+
if (this.mMenuProvider != null) {removeMenuProvider(this.mMenuProvider);}
6161
addMenuProvider(menuProvider, this, Lifecycle.State.RESUMED);
62-
mMenuProvider = menuProvider;
62+
this.mMenuProvider = menuProvider;
6363
}
6464
}

mobile/src/main/java/io/syslogic/github/content/RepositorySyncAdapter.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.syslogic.github.content;
22

33
import android.accounts.Account;
4+
import android.app.Activity;
45
import android.content.AbstractThreadedSyncAdapter;
56
import android.content.ContentProviderClient;
67
import android.content.Context;
@@ -61,7 +62,7 @@ public RepositorySyncAdapter(@NonNull Context context, boolean autoInitialize, b
6162
super(context, autoInitialize, allowParallelSyncs);
6263
this.prefs = PreferenceManager.getDefaultSharedPreferences(context);
6364
this.dao = Abstraction.getInstance(context).repositoriesDao();
64-
this.accessToken = TokenHelper.getAccessToken(context);
65+
this.accessToken = TokenHelper.getAccessToken((Activity) context);
6566
this.username = TokenHelper.getUsername(context);
6667
}
6768

mobile/src/main/java/io/syslogic/github/fragment/BaseFragment.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis
168168

169169
@Nullable
170170
protected String getAccessToken() {
171-
return TokenHelper.getAccessToken(requireContext());
171+
return TokenHelper.getAccessToken(requireActivity());
172172
}
173173

174174
@Nullable

mobile/src/main/java/io/syslogic/github/fragment/PreferencesFragment.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public void onCreatePreferences(@Nullable Bundle savedInstanceState, @Nullable S
8989
/* Preference: Account Manager */
9090
Preference pref = this.findPreference(Constants.PREFERENCE_KEY_ACCOUNT_SETTINGS);
9191
if (pref != null) {
92-
String accessToken = TokenHelper.getAccessToken(requireContext());
92+
String accessToken = TokenHelper.getAccessToken(requireActivity());
9393
//if (accessToken != null) {pref.setSummary(R.string.summary_personal_access_token_alt);}
9494
pref.setOnPreferenceClickListener(preference -> {
9595

mobile/src/main/java/io/syslogic/github/network/TokenHelper.java

Lines changed: 58 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
import android.accounts.Account;
44
import android.accounts.AccountManager;
5+
import android.app.Activity;
56
import android.content.Context;
7+
import android.content.Intent;
68
import android.content.pm.ApplicationInfo;
79
import android.content.pm.PackageManager;
810
import android.os.Bundle;
11+
import android.os.Handler;
912
import android.util.Log;
1013

1114
import com.google.gson.JsonObject;
@@ -17,9 +20,13 @@
1720
import androidx.annotation.Nullable;
1821
import io.syslogic.github.BuildConfig;
1922
import io.syslogic.github.Constants;
23+
import io.syslogic.github.activity.AuthenticatorActivity;
24+
import io.syslogic.github.activity.NavHostActivity;
2025
import io.syslogic.github.api.GithubClient;
2126
import io.syslogic.github.api.model.User;
22-
import okhttp3.ResponseBody;
27+
import io.syslogic.github.fragment.HomeScreenFragment;
28+
import io.syslogic.github.fragment.HomeScreenFragmentDirections;
29+
2330
import retrofit2.Call;
2431
import retrofit2.Callback;
2532
import retrofit2.Response;
@@ -38,21 +45,35 @@ public class TokenHelper {
3845
static final boolean mDebug = BuildConfig.DEBUG;
3946

4047
@Nullable
41-
public static String getAccessToken(@NonNull Context context) {
42-
AccountManager accountManager = AccountManager.get(context);
48+
public static String getAccessToken(@NonNull Activity activity) {
49+
AccountManager accountManager = AccountManager.get(activity);
4350
Account account = getAccount(accountManager, 0);
4451
if (account != null) {
4552
/* Default: Load the access token from AccountManager. */
4653
return accountManager.getUserData(account, "token");
4754
} else if (mDebug) {
4855
/* Debug: Try to load and validate the access token. */
49-
return loadTokenFromPackageMeta(context, accountManager);
56+
return loadTokenFromPackageMeta(activity, accountManager);
5057
} else {
5158
Log.e(LOG_TAG, "Account not found: " + Constants.ACCOUNT_TYPE);
5259
return null;
5360
}
5461
}
5562

63+
public static void setAccessToken(Activity activity, @Nullable String token) {
64+
AccountManager accountManager = AccountManager.get(activity);
65+
Account account = getAccount(accountManager, 0);
66+
if (account != null && token == null) {
67+
accountManager.removeAccount(account, activity, accountManagerFuture -> {
68+
Log.d(LOG_TAG, "Account removed: " + Constants.ACCOUNT_TYPE);
69+
}, new Handler());
70+
} else if (account == null && token == null) {
71+
/* This maybe happen when the token loaded from package-meta has expired. */
72+
Intent intent = new Intent(activity, AuthenticatorActivity.class);
73+
activity.startActivity(intent);
74+
}
75+
}
76+
5677
/** The username is now being stored along with the token */
5778
@Nullable
5879
public static String getUsername(@NonNull Context context) {
@@ -67,20 +88,20 @@ public static String getUsername(@NonNull Context context) {
6788
}
6889
}
6990

70-
private static String loadTokenFromPackageMeta(@NonNull Context context, AccountManager accountManager) {
91+
private static String loadTokenFromPackageMeta(@NonNull Activity activity, AccountManager accountManager) {
7192
String token = null;
7293
try {
7394

7495
ApplicationInfo app;
7596
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU) {
7697
PackageManager.ApplicationInfoFlags flags = PackageManager.ApplicationInfoFlags.of(PackageManager.GET_META_DATA);
77-
app = context.getPackageManager().getApplicationInfo(context.getPackageName(), flags);
98+
app = activity.getPackageManager().getApplicationInfo(activity.getPackageName(), flags);
7899
} else {
79-
app = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
100+
app = activity.getPackageManager().getApplicationInfo(activity.getPackageName(), PackageManager.GET_META_DATA);
80101
}
81102

82-
if (app.metaData.keySet().contains("com.github.ACCESS_TOKEN")) {
83-
103+
if (mDebug && app.metaData.keySet().contains("com.github.ACCESS_TOKEN")) {
104+
Log.d(LOG_TAG, "loading access token from meat-data: " + Constants.ACCOUNT_TYPE);
84105
token = app.metaData.getString("com.github.ACCESS_TOKEN");
85106
if (token != null && !token.equals("null")) {
86107

@@ -96,29 +117,46 @@ public void onResponse(@NonNull Call<User> call, @NonNull Response<User> respons
96117
if (response.body() != null) {
97118
User item = response.body();
98119
Account account = addAccount(accountManager, item.getLogin(), finalToken);
99-
if (mDebug) {
100-
if (account != null) {Log.d(LOG_TAG, "account added");}
101-
else {Log.d(LOG_TAG, "account not added");}
102-
}
120+
if (account != null) {Log.d(LOG_TAG, "account added");}
121+
else {Log.d(LOG_TAG, "account not added");}
103122
}
104-
} else {
105-
/* "bad credentials" means that the provided access-token is invalid. */
106-
if (response.errorBody() != null) {
107-
logError(response.errorBody());
123+
} else if (response.errorBody() != null) {
124+
try {
125+
String errors = response.errorBody().string();
126+
JsonObject jsonObject = JsonParser.parseString(errors).getAsJsonObject();
127+
String message = jsonObject.get("message").toString();
128+
129+
/* "Bad credentials" means that the provided access-token is invalid. */
130+
if (BuildConfig.DEBUG) {Log.e(LOG_TAG, "login error: " + message);}
131+
if (message.equals("\"Bad credentials\"")) {
132+
133+
// Remove the token, it is invalid anyway.
134+
TokenHelper.setAccessToken(activity, null);
135+
136+
if (activity instanceof NavHostActivity activity2) {
137+
if (activity2.getCurrentFragment() instanceof HomeScreenFragment) {
138+
activity2.getNavController().navigate(
139+
HomeScreenFragmentDirections
140+
.actionHomeScreenFragmentToPreferencesFragment()
141+
);
142+
}
143+
}
144+
}
145+
} catch (IOException e) {
146+
if (BuildConfig.DEBUG) {Log.e(LOG_TAG, "" + e.getMessage());}
108147
}
109148
}
110149
}
111150
@Override
112151
public void onFailure(@NonNull Call<User> call, @NonNull Throwable t) {
113-
if (mDebug) {Log.e(LOG_TAG, "" + t.getMessage());}
152+
Log.e(LOG_TAG, "" + t.getMessage());
114153
}
115154
});
116155
}
117156
}
118157
} catch (NullPointerException | PackageManager.NameNotFoundException e) {
119158
e.printStackTrace();
120159
}
121-
122160
return token;
123161
}
124162

@@ -143,14 +181,4 @@ public static Account addAccount(AccountManager accountManager, String username,
143181
}
144182
return null;
145183
}
146-
147-
static void logError(@NonNull ResponseBody responseBody) {
148-
try {
149-
String errors = responseBody.string();
150-
JsonObject jsonObject = JsonParser.parseString(errors).getAsJsonObject();
151-
if (BuildConfig.DEBUG) {Log.e(LOG_TAG, jsonObject.get("message").toString());}
152-
} catch (IOException e) {
153-
if (BuildConfig.DEBUG) {Log.e(LOG_TAG, "" + e.getMessage());}
154-
}
155-
}
156-
}
184+
}

mobile/src/main/java/io/syslogic/github/network/TokenService.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public void onCreate() {
2323
this.mAuthenticator = new AccountAuthenticator(this);
2424
}
2525
}
26-
2726
}
2827

2928
@NonNull

mobile/src/main/res/values/strings.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
<string name="button_org_repositories">Org Repositories</string>
1212
<string name="button_repository_search">Repository Search</string>
1313

14-
<string name="title_account_authenticator">"Account Authenticator</string>
15-
<string name="summary_account_authenticator">TODO</string>
14+
<string name="title_account_authenticator">"GitHub API Client</string>
15+
<string name="summary_account_authenticator">Personal Access Token</string>
1616

1717
<string name="title_application_settings">"Application Settings</string>
1818
<string name="summary_intent_account_settings">"Open the account settings</string>

0 commit comments

Comments
 (0)