唉,MAF 登录组件并非设计为可根据您的需要进行定制。Claudia Pacheco 的博客文章“在 Android 中自定义 MAF 登录组件”很好地概述了您拥有的选项。品牌定制方面的问题在于要求可能没有尽头:有些人对定制徽标感到满意,而另一些人则需要完全不同的布局。HttpConversation
因此,您应该实现自己的登录页面并在流程之上实现通信,如文档中所述。我为你整理了一个小例子,让你开始:
res/layout/layout_main.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="logon.example.com.basicauthconvflow.MainActivity">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingEnd="8dp"
android:paddingStart="8dp"
tools:layout_editor_absoluteY="8dp"
tools:layout_editor_absoluteX="8dp">
<EditText
android:id="@+id/server_host"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Host (e.g. hcpms-p0123456trial.hanatrial.ondemand.com"
android:inputType="text"
android:maxLines="1" />
<EditText
android:id="@+id/application_id"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="com.logon.test"
android:ems="10"
android:hint="Application ID"
android:inputType="none"
android:maxLines="1" />
<EditText
android:id="@+id/user_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="pXXXXXXX"
android:ems="10"
android:hint="User name"
android:inputType="none"
android:maxLines="1" />
<EditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="Password"
android:inputType="textPassword"
android:maxLines="1" />
<Button
android:id="@+id/login_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Log in"/>
</LinearLayout>
</ScrollView>
src/main/java/logon/example/com/basicauthconflow/MainActivity.java
package logon.example.com.basicauthconvflow;
import android.app.Activity;
import android.net.Uri;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import com.sap.smp.client.httpc.HttpConversationManager;
import com.sap.smp.client.httpc.HttpMethod;
import com.sap.smp.client.httpc.IHttpConversation;
import com.sap.smp.client.httpc.SAPCookieManager;
import com.sap.smp.client.httpc.authflows.CommonAuthFlowsConfigurator;
import com.sap.smp.client.httpc.authflows.UsernamePasswordProvider;
import com.sap.smp.client.httpc.authflows.UsernamePasswordToken;
import com.sap.smp.client.httpc.events.IReceiveEvent;
import com.sap.smp.client.httpc.events.ISendEvent;
import com.sap.smp.client.httpc.events.ITransmitEvent;
import com.sap.smp.client.httpc.listeners.IRequestListener;
import com.sap.smp.client.httpc.listeners.IResponseListener;
import com.sap.smp.client.httpc.utils.EmptyFlowListener;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import java.net.HttpCookie;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;
public class MainActivity extends AppCompatActivity {
/**
* Mobile Services registration API URI for this app
*/
URI registrationUri;
/**
* Mobile Services application ID
*/
String applicationId;
/**
* User name for login
*/
String user;
/**
* Password for login
*/
char[] password;
/**
* Mobile Services application connection ID ("registration ID") after login
*/
String appcid;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((Button)findViewById(R.id.login_button)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
applicationId = ((EditText)findViewById(R.id.application_id)).getText().toString();
user = ((EditText)findViewById(R.id.user_name)).getText().toString();
password = ((EditText)findViewById(R.id.password)).getText().toString().toCharArray();
String serverAuthority = ((EditText)findViewById(R.id.server_host)).getText().toString() + ":443";
Uri.Builder builder = new Uri.Builder();
// Assemble path to the Mobile Services registration API for this app
builder.scheme("https")
.encodedAuthority(serverAuthority)
.appendPath("odata")
.appendPath("applications")
.appendPath("latest")
.appendPath(applicationId)
.appendPath("Connections");
registrationUri = URI.create(builder.build().toString());
login();
}
});
}
/**
* Performs a login, registering with Mobile Services if required.
*/
private void login() {
if(isRegistered()) {
// There is a valid registration and the cookie manager has a session cookie
Toast.makeText(this, "Already registered with APPCID " + appcid, Toast.LENGTH_SHORT).show();
} else {
this.register();
}
}
/**
* Performs a registration request against Mobile Services and extracts the application connection
* ID from the response.
* The application connection ID is set as a side-effect of this method.
*/
private void register() {
final IHttpConversation conv = createConversation();
conv.setMethod(HttpMethod.POST);
conv.addHeader("Content-Type", "application/json; charset=utf-8");
conv.setRequestListener(new IRequestListener() {
@Override
public Object onRequestHeaderSending(ISendEvent event) {
return null;
}
@Override
public Object onRequestBodySending(ITransmitEvent event) throws IOException {
JSONObject json = new JSONObject();
try {
json.put("DeviceType", "Android");
event.getWriter().write(json.toString());
return null;
} catch (JSONException e) {
throw new IOException(e);
}
}
});
conv.setResponseListener(new IResponseListener() {
@Override
public void onResponseReceived(final IReceiveEvent event) throws IOException {
final int statusCode = event.getResponseStatusCode();
final Activity activity = MainActivity.this;
if (activity != null)
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
if (statusCode == 201) {
// Extract the connection ID from the cookies.
if(extractAppcidFromResponse(event)) {
Toast.makeText(activity, "Registered with APPCID " + appcid, Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(activity, "Registration was not succesful (" + statusCode + ")", Toast.LENGTH_SHORT).show();
}
}
});
}
});
conv.start();
}
/**
* Create an HTTP conversation targeting the Mobile Services registration API and configured
* for Basic authentication based on the current activity instance state.
*
* @return The conversation
*/
private IHttpConversation createConversation() {
HttpConversationManager manager = new HttpConversationManager(this);
CommonAuthFlowsConfigurator configurator = new CommonAuthFlowsConfigurator(this);
configurator.supportBasicAuthUsing(new UsernamePasswordProvider() {
@Override
public Object onCredentialsNeededUpfront(ISendEvent event) {
return null;
}
@Override
public Object onCredentialsNeededForChallenge(IReceiveEvent event) {
return new UsernamePasswordToken(user, new String(password));
}
});
configurator.configure(manager);
URL serverUrl;
try {
serverUrl = registrationUri.toURL();
} catch (MalformedURLException e) {
Log.e(this.getClass().getSimpleName(), "Unexpected error constructing registration URL.", e);
return null;
}
// Create the conversation.
return manager.create(serverUrl);
}
/**
* Tells if there is an existing registration for this application.
* The application connection ID is set as a side-effect of this method.
*
* @return true if there is an existing registration; false otherwise
*/
private boolean isRegistered() {
return extractAppcidFromCookies(SAPCookieManager.getInstance().getCookieStore().get(registrationUri));
}
/**
* Extracts the Mobile Services application connection ID from the specified response event.
* The application connection ID is set as a side-effect of this method.
*
* @param event The event to search
* @return true if it could be found; false otherwise
*/
private boolean extractAppcidFromResponse(IReceiveEvent event) {
try {
return extractAppcidFromCookies(SAPCookieManager.getInstance().getCookieStore().get(
event.getResponseURL().toURI()));
} catch (URISyntaxException e) {
Log.e(this.getClass().getSimpleName(), "Unable to extract APPCID", e);
}
return false;
}
/**
* Extracts the Mobile Services application connection ID from the specified list of cookies.
* The application connection ID is set as a side-effect of this method.
*
* @param httpCookies The cookies to search
* @return true if it could be found; false otherwise
*/
private boolean extractAppcidFromCookies(List<HttpCookie> httpCookies) {
if (httpCookies != null)
for (HttpCookie httpCookie : httpCookies)
if ("X-SMP-APPCID".equals(httpCookie.getName())) {
appcid = httpCookie.getValue();
return true;
}
return false;
}
}