Hi Erick,
Yeah that makes sense. What is happening is that OAuth (OAuthTokenCredential) portal credentials do work and I can see those credentials in the Credential Cache automatically. However secured service credentials (UserCredential) do not seem to get added automatically.
Below is the code we use...
First we attempt to add the FeatureLayer which is derived from ServiceFeatureTable where the url to the secure service is passed in prior to the ServiceFeatureTable. mAgencyCredential is a Credential variable.
if (mAgencyCredentials != null) { //Check if credentials already available
fsTable.setCredential(mAgencyCredentials); //on premise shared through AGOL
}
FeatureLayer fLayer = new FeatureLayer(fsTable);
mMap.getOperationalLayers().add(fLayer);
When we do the ".add" command this will automatically trigger the class we built to check credentials. If null or invalid
public class S1AuthenticationChallengeHandler extends DefaultAuthenticationChallengeHandler {
public S1AuthenticationChallengeHandler(Activity context) {
super(context);
}
private String lastFSPassIn = "";
public static Boolean backPressed = false; //used to prevent login screen from showing up when user backs out of web map preview window.
@Override
public AuthenticationChallengeResponse handleChallenge(AuthenticationChallenge challenge) {
if (challenge.getRemoteResource() instanceof Portal) { //instance of portal
// let DefaultAuthenticationChallengeHandler handle this challenge
return super.handleChallenge(challenge);
} else { //secured service
if (!backPressed) { //back pressed on FeatureServiceLogin triggers one more handler event unfortunately by doing a countdown. Do not want to trigger another countdownlatch so if backpressed do nothing
int maxAttempts = 5;
if (challenge.getFailureCount() > maxAttempts) {
// exceeded maximum amount of attempts. Act like it was a cancel
Toast.makeText(S1ViewerActivity.getS1ViewerActivity(), "Exceeded maximum amount of attempts. Please try again!", Toast.LENGTH_LONG).show();
return new AuthenticationChallengeResponse(AuthenticationChallengeResponse.Action.CANCEL, challenge);
}
String fsURL = challenge.getRemoteResource().getUri();
if (!fsURL.endsWith("/FeatureServer")) {
if (fsURL.contains("/FeatureServer")) {
fsURL = fsURL.substring(0, fsURL.indexOf("/FeatureServer") + 14);
}
}
final String fsURLPassIn = fsURL;
// create a countdown latch with a count of one to synchronize the dialog
DownloadHelper.signal = new CountDownLatch(1);
S1ViewerActivity.getS1ViewerActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
try {
if (DownloadHelper.downloadSyncAction != null) {
if (MapExtentDownloadFS.getMapExtentDownloadFS() != null) {
showFSLogin(errorLabel, fsURLPassIn); //this will prompt user to type in username and password
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
try {
DownloadHelper.signal.await();
} catch (InterruptedException e) {
String error = "Interruption handling AuthenticationChallengeResponse: " + e.getMessage();
//Toast.makeText(this, error, Toast.LENGTH_LONG).show();
}
// if credentials were set, return a new auth challenge response with them. otherwise, act like it was a cancel.
if (mAgencyCredentials != null) {
return new AuthenticationChallengeResponse(AuthenticationChallengeResponse.Action.CONTINUE_WITH_CREDENTIAL, mAgencyCredentials);
} else {
lastFSPassIn = ""; //In case of failure to login this needs to be set back to empty string in case user tries to login to webmap again.
return new AuthenticationChallengeResponse(AuthenticationChallengeResponse.Action.CANCEL, challenge);
}
} else {
return new AuthenticationChallengeResponse(AuthenticationChallengeResponse.Action.CANCEL, challenge);
}
}
}
}
The core line of code that runs (in showFSLogin) when login credentials required after typed in is as follows...
mAgencyCredentials = new UserCredential(userName, password);