Thanks in adavance. I am really new to Android/Java development and I am trying to solve this with MicroStrategy Mobile for Android SDK. We need the mobile app to go to an external login site when it is opened, instead of showing the default login screen or login directly to MicroStrategy demo server (default configuration). Unfortunately, MicroStrategy does not provide sufficient documentation on Android SDK and I've already requested documentation several times with no success. I've found the Activity class that handles the Login, and extended the class with an intent to browse to URL. This might (most likely) be wrong due to my limitations in Java and Android development. Our custom authentication flow is handled by an external Java Webapp in Tomcat that captures a token and sign, verifies the sign, parses the data on the token and calls different Tasks that create the user, assigns groups, random alphanumerical password and opens the session for the user on the fly. So mainly, we go to the external website, and through a link there we do a post to the webapp with the token and sign in base64. That functionality is already working for Web access and Mobile Access.
LoginActivity.class
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.microstrategy.android.ui.activity;
import android.app.Fragment;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.microstrategy.android.MstrApplication;
import com.microstrategy.android.infrastructure.MobileLoginManager;
import com.microstrategy.android.infrastructure.SessionManager;
import com.microstrategy.android.infrastructure.SessionManager.GetSessionInfoCallback;
import com.microstrategy.android.model.config.MobileConfig;
import com.microstrategy.android.model.config.MobileProjectSettings;
import com.microstrategy.android.model.config.MobileServerSettings;
import com.microstrategy.android.network.CredentialsHelper;
import com.microstrategy.android.ui.Utils;
import com.microstrategy.android.ui.activity.MSTRNonStartupBaseActivity;
import com.microstrategy.android.ui.fragment.MobileLoginFragment;
import com.microstrategy.android.ui.view.ProgressWheel;
import com.microstrategy.android.utils.MSTRFeature;
import com.microstrategy.android.websdk.R.id;
import com.microstrategy.android.websdk.R.layout;
import com.microstrategy.android.websdk.R.string;
import java.util.HashMap;
import java.util.Map;
public class LoginActivity extends MSTRNonStartupBaseActivity {
private static final String LOG_TAG = "LoginActivity";
public static final String KEY_SERVER_INDEX = "com.microstrategy.android.webapp.serverIndex";
public static final String KEY_PROJECT_INDEX = "com.microstrategy.android.webapp.projectIndex";
public LoginActivity() {
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setContentView(layout.login_view);
if(Utils.hasKitKat()) {
this.getWindow().addFlags(67108864);
} else {
this.getWindow().addFlags(1024);
}
if(!MstrApplication.getInstance().isTablet()) {
this.setRequestedOrientation(1);
}
if(savedInstanceState == null) {
final int serverIndex = this.getIntent().getExtras().getInt("com.microstrategy.android.webapp.serverIndex");
final int projectIndex = this.getIntent().getExtras().getInt("com.microstrategy.android.webapp.projectIndex");
MobileProjectSettings projectSettings = this.getMobileConfig().getProject(serverIndex, projectIndex);
if(projectSettings == null) {
this.finish();
return;
}
int credentialStatus = CredentialsHelper.checkProjectAndParentServerValidity(projectSettings);
MobileLoginManager manager = MobileLoginManager.sharedLoginManager();
MobileLoginFragment fragment = null;
if(CredentialsHelper.isOnlyProjectChangePasswordError(credentialStatus)) {
fragment = manager.newLoginFragment(1, new HashMap() {
{
this.put("com.microstrategy.android.webapp.serverIndex", Integer.valueOf(serverIndex));
this.put("com.microstrategy.android.webapp.projectIndex", Integer.valueOf(projectIndex));
}
});
} else if(projectSettings.getCredentials().getAuthMode() == 5) {
if(!MstrApplication.getInstance().getSecurityHandler().isFeatureAvailable(MSTRFeature.UsherAuthentication)) {
Toast.makeText(this, string.FEATURE_NOT_AVAILABLE_MSG, 0).show();
this.finish();
}
fragment = manager.newLoginFragment(2, new HashMap() {
{
this.put("com.microstrategy.android.webapp.serverIndex", Integer.valueOf(serverIndex));
this.put("com.microstrategy.android.webapp.projectIndex", Integer.valueOf(projectIndex));
}
});
} else {
if(!CredentialsHelper.isAuthenticationError(credentialStatus)) {
this.finish();
return;
}
fragment = manager.newLoginFragment(0, new HashMap() {
{
this.put("com.microstrategy.android.webapp.serverIndex", Integer.valueOf(serverIndex));
this.put("com.microstrategy.android.webapp.projectIndex", Integer.valueOf(projectIndex));
}
});
}
this.showFragment(fragment);
}
}
protected void onDestroy() {
if(this.isFinishing()) {
MobileLoginManager.sharedLoginManager().dismissCurrentDisplayingMobileLoginPromptView();
}
super.onDestroy();
}
public MobileConfig getMobileConfig() {
return MstrApplication.getInstance().getConfigObject();
}
public void onNeedChangePassword(final int serverIndex, final int projectIndex, String errorMessage) {
this.showFragment(MobileLoginManager.sharedLoginManager().newLoginFragment(1, new HashMap() {
{
this.put("com.microstrategy.android.webapp.serverIndex", Integer.valueOf(serverIndex));
this.put("com.microstrategy.android.webapp.projectIndex", Integer.valueOf(projectIndex));
}
}));
}
private void showFragment(Fragment fragment) {
Log.i("Authentication", "showFragment");
this.getFragmentManager().beginTransaction().replace(id.login_fragment, fragment).commit();
}
public void dismissFragment(boolean validated) {
Log.i("Authentication", "dismissFragment");
MobileLoginManager manager = MobileLoginManager.sharedLoginManager();
manager.setMobileLoginPromptStatus(validated?1:2);
this.finish();
}
public void showProgressBar() {
Log.i("Authentication", "showProgressBar");
RelativeLayout disableViewContainer = (RelativeLayout)this.findViewById(id.disable_view);
if(disableViewContainer.getVisibility() != 0) {
disableViewContainer.setVisibility(0);
}
disableViewContainer.bringToFront();
View overlayProgressbar = disableViewContainer.findViewById(id.overlay_circular_progressbar);
if(overlayProgressbar == null) {
disableViewContainer.removeAllViews();
overlayProgressbar = this.getLayoutInflater().inflate(layout.overlay_circular_progressbar, disableViewContainer, false);
disableViewContainer.setGravity(17);
disableViewContainer.addView(overlayProgressbar);
}
View progressBar = overlayProgressbar.findViewById(id.progressbar_in_overlay);
((ProgressWheel)progressBar).spin();
}
public void dismissProgressBar() {
Log.i("Authentication", "dismissProgressBar");
this.runOnUiThread(new Runnable() {
public void run() {
RelativeLayout disableViewContainer = (RelativeLayout)LoginActivity.this.findViewById(id.disable_view);
View overlayProgressbar = disableViewContainer.findViewById(id.overlay_circular_progressbar);
if(overlayProgressbar != null) {
View progressBar = overlayProgressbar.findViewById(id.progressbar_in_overlay);
((ProgressWheel)progressBar).stopSpinning();
}
if(disableViewContainer.getVisibility() == 0) {
disableViewContainer.setVisibility(8);
}
}
});
}
public boolean isProgressBarSpinning() {
RelativeLayout disableViewContainer = (RelativeLayout)this.findViewById(id.disable_view);
if(disableViewContainer == null) {
return false;
} else {
View overlayProgressbar = disableViewContainer.findViewById(id.overlay_circular_progressbar);
if(overlayProgressbar == null) {
return false;
} else {
View progressBar = overlayProgressbar.findViewById(id.progressbar_in_overlay);
return progressBar != null && ((ProgressWheel)progressBar).isSpinning();
}
}
}
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if(intent != null) {
Uri uri = intent.getData();
if(uri != null && uri.getScheme().equals(this.getString(string.usher_scheme))) {
int serverIndex = this.getIntent().getExtras().getInt("com.microstrategy.android.webapp.serverIndex");
int projectIndex = this.getIntent().getExtras().getInt("com.microstrategy.android.webapp.projectIndex");
MobileServerSettings mobileServerSettings = this.getMobileConfig().getMobileServer(serverIndex);
MobileProjectSettings projectSettings = mobileServerSettings.getProject(projectIndex);
final ProgressDialog dialog = new ProgressDialog(this);
dialog.setTitle(this.getString(string.LOGIN));
dialog.setMessage(this.getString(string.WAIT));
dialog.setIndeterminate(true);
dialog.show();
SessionManager.getInstance().validate(projectSettings, false, new GetSessionInfoCallback() {
public void returnResponse(Map sessionStateInfo) {
if(sessionStateInfo != null && sessionStateInfo.containsKey("sessionState")) {
MobileLoginManager manager = MobileLoginManager.sharedLoginManager();
if(manager.getMobileLoginPromptStatus() == 0) {
manager.setMobileLoginPromptStatus(1);
}
}
LoginActivity.this.runOnUiThread(new Runnable() {
public void run() {
dialog.hide();
}
});
LoginActivity.this.finish();
}
});
}
}
}
protected boolean shouldShowOfflineIndicator() {
return false;
}
}
CustomLoginActivity.class
package com.microstrategy.android.custom.afip;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.AppIndex;
import com.google.android.gms.appindexing.Thing;
import com.google.android.gms.common.api.GoogleApiClient;
import com.microstrategy.android.ui.activity.LoginActivity;
/**
* Created by Max on 12/23/2016.
*/
public class CustomLoginActivity extends com.microstrategy.android.ui.activity.LoginActivity {
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
private GoogleApiClient client;
public CustomLoginActivity(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://authinthomo.afip.gob.ar"));
startActivity(intent);
}
}
AndroidManifest.xml
</intent-filter>
</activity>
<activity android:configChanges="orientation|keyboardHidden|screenSize" android:launchMode="singleTask" android:name="com.microstrategy.android.custom.afip.CustomLoginActivity" android:theme="@style/LoginActivityTheme" android:windowSoftInputMode="adjustPan">
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="https" android:host="authinthomo.afip.gob.ar"/>
</intent-filter>
</activity>
Am I on the right track? When I install the apk it just logs in to demo server as configured on the app by default. I am using MicroStrategy SDK for Android 10.6 (latest) & Android Studio. Any comments or help is greatly appreciated.
Thanks in advance, Kind regards, Max
if you have not resolve this problem yet. Exist a configuration file that you can create in the raw folder of your app module. In this you can inject java code for a custom authentication process
The problem with change the manifiest and add a new activity is that the MstrStartupActivity call directly the class in many points com.microstrategy.android.ui.activity.LoginActivity
The MstrStartup Activity is so complex as is so difficult to locate and change all authentication activity call points.
Regrads