Skip to content
This repository was archived by the owner on Jun 20, 2024. It is now read-only.

Commit 53afbc1

Browse files
committed
seperate sign in activities, fix tests
1 parent bf03cb6 commit 53afbc1

File tree

9 files changed

+349
-209
lines changed

9 files changed

+349
-209
lines changed

app/src/main/AndroidManifest.xml

+3-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727

2828
<activity android:name=".ui.language.SelectLanguageActivity" />
2929

30-
<activity android:name=".ui.authentication.SignInActivity" />
30+
<activity android:name=".ui.authentication.SignInWithWeb3Activity" />
31+
32+
<activity android:name=".ui.authentication.SignInWithGoogleActivity" />
3133

3234
<activity android:name=".ui.BottomNavigationActivity" />
3335

app/src/main/java/ai/elimu/crowdsource/MainActivity.java

+28-8
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,54 @@
33
import android.content.Intent;
44
import android.os.Bundle;
55
import android.text.TextUtils;
6+
import android.view.View;
7+
import android.widget.Button;
68

79
import androidx.appcompat.app.AppCompatActivity;
810

9-
import ai.elimu.crowdsource.ui.authentication.SignInActivity;
10-
import ai.elimu.crowdsource.ui.language.SelectLanguageActivity;
1111
import ai.elimu.crowdsource.ui.BottomNavigationActivity;
12+
import ai.elimu.crowdsource.ui.authentication.SignInWithGoogleActivity;
13+
import ai.elimu.crowdsource.ui.authentication.SignInWithWeb3Activity;
14+
import ai.elimu.crowdsource.ui.language.SelectLanguageActivity;
1215
import ai.elimu.crowdsource.util.SharedPreferencesHelper;
1316
import ai.elimu.model.v2.enums.Language;
1417
import timber.log.Timber;
1518

1619
public class MainActivity extends AppCompatActivity {
1720

21+
private Button signInWeb3Button, signInGoogleButton;
22+
1823
@Override
1924
protected void onCreate(Bundle savedInstanceState) {
2025
Timber.i("onCreate");
2126
super.onCreate(savedInstanceState);
2227

2328
setContentView(R.layout.activity_main);
29+
signInWeb3Button = findViewById(R.id.w3_sign_in);
30+
signInGoogleButton = findViewById(R.id.g_sign_in);
31+
signInWeb3Button.setOnClickListener(new View.OnClickListener() {
32+
@Override
33+
public void onClick(View view) {
34+
Intent signInWithWeb3Intent = new Intent(getApplicationContext(), SignInWithWeb3Activity.class);
35+
startActivity(signInWithWeb3Intent);
36+
}
37+
});
38+
signInGoogleButton.setOnClickListener(new View.OnClickListener() {
39+
@Override
40+
public void onClick(View view) {
41+
// Redirect to sign-in with Google
42+
Intent signInWithGoogleIntent = new Intent(getApplicationContext(), SignInWithGoogleActivity.class);
43+
startActivity(signInWithGoogleIntent);
44+
}
45+
});
2446
}
2547

2648
@Override
2749
protected void onStart() {
2850
Timber.i("onStart");
2951
super.onStart();
3052

53+
3154
// Check if language has been selected
3255
Language language = SharedPreferencesHelper.getLanguage(getApplicationContext());
3356
Timber.i("language: " + language);
@@ -39,13 +62,10 @@ protected void onStart() {
3962
} else {
4063
// Check for an existing signed-in Contributor
4164
String providerIdGoogle = SharedPreferencesHelper.getProviderIdGoogle(getApplicationContext());
65+
String web3Account = SharedPreferencesHelper.getWeb3Account(getApplicationContext());
4266
Timber.i("providerIdGoogle: " + providerIdGoogle);
43-
if (TextUtils.isEmpty(providerIdGoogle)) {
44-
// Redirect to sign-in with Google
45-
Intent signInWithGoogleIntent = new Intent(getApplicationContext(), SignInActivity.class);
46-
startActivity(signInWithGoogleIntent);
47-
finish();
48-
} else {
67+
Timber.i("web3 account: " + web3Account);
68+
if (!TextUtils.isEmpty(providerIdGoogle) || !TextUtils.isEmpty(web3Account)) {
4969
// Redirect to crowdsourcing activity selection
5070
Intent intent = new Intent(getApplicationContext(), BottomNavigationActivity.class);
5171
startActivity(intent);

app/src/main/java/ai/elimu/crowdsource/server/BridgeServer.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class BridgeServer(moshi: Moshi) : WebSocketServer(InetSocketAddress(PORT)) {
6565
}
6666
}
6767
"ack" -> {
68-
68+
pubsCache.remove(topic);
6969
}
7070
else -> error("Unknown type")
7171
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
package ai.elimu.crowdsource.ui.authentication;
2+
3+
import android.content.Intent;
4+
import android.os.Bundle;
5+
import android.view.View;
6+
import android.widget.ProgressBar;
7+
import android.widget.Toast;
8+
9+
import androidx.appcompat.app.AppCompatActivity;
10+
11+
import com.google.android.gms.auth.api.signin.GoogleSignIn;
12+
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
13+
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
14+
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
15+
import com.google.android.gms.common.SignInButton;
16+
import com.google.android.gms.common.api.ApiException;
17+
import com.google.android.gms.common.api.CommonStatusCodes;
18+
import com.google.android.gms.tasks.Task;
19+
20+
import org.json.JSONException;
21+
import org.json.JSONObject;
22+
23+
import java.io.IOException;
24+
import java.util.concurrent.ExecutorService;
25+
import java.util.concurrent.Executors;
26+
27+
import ai.elimu.crowdsource.BaseApplication;
28+
import ai.elimu.crowdsource.BuildConfig;
29+
import ai.elimu.crowdsource.MainActivity;
30+
import ai.elimu.crowdsource.R;
31+
import ai.elimu.crowdsource.rest.ContributorService;
32+
import ai.elimu.crowdsource.util.SharedPreferencesHelper;
33+
import okhttp3.MediaType;
34+
import okhttp3.RequestBody;
35+
import okhttp3.ResponseBody;
36+
import retrofit2.Call;
37+
import retrofit2.Response;
38+
import retrofit2.Retrofit;
39+
import timber.log.Timber;
40+
41+
/**
42+
* Prompts the Contributor for access to her Google account. Then stores the account details in the
43+
* webapp's database.
44+
*
45+
* See https://developers.google.com/identity/sign-in/android/sign-in
46+
*/
47+
public class SignInWithGoogleActivity extends AppCompatActivity implements View.OnClickListener {
48+
49+
private static final int RC_SIGN_IN = 0;
50+
51+
private SignInButton signInButton;
52+
53+
private ProgressBar signInProgressBar;
54+
55+
private GoogleSignInClient googleSignInClient;
56+
57+
@Override
58+
protected void onCreate(Bundle savedInstanceState) {
59+
Timber.i("onCreate");
60+
super.onCreate(savedInstanceState);
61+
62+
setContentView(R.layout.activity_sign_in_with_google);
63+
64+
signInButton = findViewById(R.id.sign_in_button);
65+
signInButton.setSize(SignInButton.SIZE_WIDE);
66+
67+
signInProgressBar = findViewById(R.id.sign_in_progressbar);
68+
}
69+
70+
@Override
71+
protected void onStart() {
72+
Timber.i("onStart");
73+
super.onStart();
74+
75+
// If the contributor is already signed in, the GoogleSignInAccount will be non-null.
76+
GoogleSignInAccount existingGoogleSignInAccount = GoogleSignIn.getLastSignedInAccount(this);
77+
if (existingGoogleSignInAccount != null) {
78+
updateUI(existingGoogleSignInAccount);
79+
} else {
80+
// Configure sign-in to request the contributors's Google ID, basic profile and e-mail address. ID and basic profile are included in DEFAULT_SIGN_IN.
81+
GoogleSignInOptions googleSignInOptions = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
82+
.requestIdToken(BuildConfig.OAUTH_CLIENT_ID)
83+
.requestEmail()
84+
.build();
85+
googleSignInClient = GoogleSignIn.getClient(this, googleSignInOptions);
86+
87+
signInButton.setOnClickListener(this);
88+
}
89+
}
90+
91+
@Override
92+
public void onClick(View v) {
93+
Timber.i("onClick");
94+
95+
signIn();
96+
}
97+
98+
private void signIn() {
99+
Timber.i("signIn");
100+
101+
Intent signInIntent = googleSignInClient.getSignInIntent();
102+
startActivityForResult(signInIntent, RC_SIGN_IN);
103+
}
104+
105+
@Override
106+
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
107+
Timber.i("onActivityResult");
108+
super.onActivityResult(requestCode, resultCode, data);
109+
110+
// Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
111+
if (requestCode == RC_SIGN_IN) {
112+
// The Task returned from this call is always completed, no need to attach a listener.
113+
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
114+
handleSignInResult(task);
115+
}
116+
}
117+
118+
private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
119+
Timber.i("handleSignInResult");
120+
121+
try {
122+
GoogleSignInAccount googleSignInAccount = completedTask.getResult(ApiException.class);
123+
124+
// Signed in successfully, show authenticated UI.
125+
updateUI(googleSignInAccount);
126+
} catch (ApiException e) {
127+
// The ApiException status code indicates the detailed failure reason.
128+
// Please refer to the GoogleSignInStatusCodes class reference for more information.
129+
Timber.w("e.getStatusCode(): " + e.getStatusCode());
130+
String statusCodeString = CommonStatusCodes.getStatusCodeString(e.getStatusCode());
131+
Timber.w("statusCodeString: " + statusCodeString);
132+
Toast.makeText(getApplicationContext(), "Error: \"" + statusCodeString + "\"", Toast.LENGTH_LONG).show();
133+
updateUI(null);
134+
}
135+
}
136+
137+
private void updateUI(GoogleSignInAccount googleSignInAccount) {
138+
Timber.i("updateUI");
139+
140+
Timber.i("googleSignInAccount: " + googleSignInAccount);
141+
if (googleSignInAccount != null) {
142+
// Get the details from the Contributor's Google account
143+
String providerIdGoogle = googleSignInAccount.getId();
144+
String email = googleSignInAccount.getEmail();
145+
String firstName = googleSignInAccount.getGivenName();
146+
String lastName = googleSignInAccount.getFamilyName();
147+
String imageUrl = googleSignInAccount.getPhotoUrl().toString();
148+
149+
// Display the progressbar while connecting to the webapp
150+
signInButton.setVisibility(View.GONE);
151+
signInProgressBar.setVisibility(View.VISIBLE);
152+
153+
// Prepare JSON object to be sent to the webapp's REST API
154+
JSONObject contributorJSONObject = new JSONObject();
155+
try {
156+
contributorJSONObject.put("providerIdGoogle", providerIdGoogle);
157+
contributorJSONObject.put("email", email);
158+
contributorJSONObject.put("firstName", firstName);
159+
contributorJSONObject.put("lastName", lastName);
160+
contributorJSONObject.put("imageUrl", imageUrl);
161+
} catch (JSONException e) {
162+
Timber.e(e);
163+
}
164+
Timber.i("contributorJSONObject: " + contributorJSONObject);
165+
166+
// Register the Contributor in the webapp's database
167+
BaseApplication baseApplication = (BaseApplication) getApplication();
168+
Retrofit retrofit = baseApplication.getRetrofit();
169+
ContributorService contributorService = retrofit.create(ContributorService.class);
170+
RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), contributorJSONObject.toString());
171+
Call<ResponseBody> call = contributorService.createContributor(requestBody);
172+
Timber.i("call.request(): " + call.request());
173+
ExecutorService executorService = Executors.newSingleThreadExecutor();
174+
executorService.execute(new Runnable() {
175+
@Override
176+
public void run() {
177+
Timber.i("run");
178+
179+
try {
180+
Response<ResponseBody> response = call.execute();
181+
Timber.i("response: " + response);
182+
Timber.i("response.isSuccessful(): " + response.isSuccessful());
183+
if (response.isSuccessful()) {
184+
String bodyString = response.body().string();
185+
Timber.i("bodyString: " + bodyString);
186+
187+
// Persist the Contributor's account details in SharedPreferences
188+
SharedPreferencesHelper.storeProviderIdGoogle(getApplicationContext(), providerIdGoogle);
189+
SharedPreferencesHelper.storeEmail(getApplicationContext(), email);
190+
SharedPreferencesHelper.storeFirstName(getApplicationContext(), firstName);
191+
SharedPreferencesHelper.storeLastName(getApplicationContext(), lastName);
192+
SharedPreferencesHelper.storeImageUrl(getApplicationContext(), imageUrl);
193+
194+
// Redirect to the MainActivity
195+
Intent mainActivityIntent = new Intent(getApplicationContext(), MainActivity.class);
196+
startActivity(mainActivityIntent);
197+
finish();
198+
} else {
199+
String errorBodyString = response.errorBody().string();
200+
Timber.e("errorBodyString: " + errorBodyString);
201+
// TODO: Handle error
202+
203+
runOnUiThread(() -> {
204+
Toast.makeText(getApplicationContext(), "Error " + response.code() + ": \"" + response.message() + "\"", Toast.LENGTH_LONG).show();
205+
206+
// Hide the progressbar
207+
signInButton.setVisibility(View.VISIBLE);
208+
signInProgressBar.setVisibility(View.GONE);
209+
});
210+
}
211+
} catch (IOException e) {
212+
Timber.e(e, null);
213+
// TODO: Handle error
214+
215+
runOnUiThread(() -> {
216+
Toast.makeText(getApplicationContext(), "Error: " + e.getClass().getSimpleName(), Toast.LENGTH_LONG).show();
217+
218+
// Hide the progressbar
219+
signInButton.setVisibility(View.VISIBLE);
220+
signInProgressBar.setVisibility(View.GONE);
221+
});
222+
}
223+
}
224+
});
225+
}
226+
}
227+
}

0 commit comments

Comments
 (0)