0

我在使用 SAP SDK 为 HANA 云平台上的 SAP Mobile 构建的应用程序中使用 MAFLogon 作为我的登录屏幕。

LogonUIFacade mLogonUIFacade = LogonUIFacade.getInstance();

        //Initialize the Logon UI Facade
        mLogonUIFacade.init(this, mContext, getString(R.string.HCPMS_APP_ID));
// Present the logon screen to the user
        setContentView(mLogonUIFacade.logon());

        // Hide the splash screen (do this at the end, so defaults are not reset)
        mLogonUIFacade.showSplashScreen(false);

上面的代码创建了一个内置的登录 Activity。如何创建自定义活动或自定义此活动?(更改标志、颜色等)

4

1 回答 1

1

唉,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;
    }

}
于 2017-06-14T19:13:29.123 回答