定制Android App的OA UI
前提条件
已完成账号及用户SDK的开发,详细请参见账号及用户SDK。
定制项
Android App的OA UI定制项如下。
App界面图示 | 可定制内容 |
修改原生元素
| |
新增元素
|
Android不支持客户端修改失败提示信息,且不支持对现有控件增加自定义事件。您仅可以修改现有控件的事件或新增控件来自定义事件。
显示手机区号
登录和注册页面中的手机区号默认不显示,如果您需要显示手机区号,如+86,请根据以下内容来操作。
在App工程中添加以下代码,并通过设置supportForeignMobileNumbers参数的值来控制手机区号的显示和隐藏。
//登录页显示手机区号
OpenAccountUIConfigs.AccountPasswordLoginFlow.supportForeignMobileNumbers=true; //true为显示,false为隐藏
//忘记密码页显示手机区号
OpenAccountUIConfigs.MobileResetPasswordLoginFlow.supportForeignMobileNumbers=true; //true为显示,false为隐藏
修改登录和注册按钮的颜色
登录和注册按钮默认为浅灰色,如果您需要修改App登录和注册按钮的颜色,请根据以下步骤来操作。
在代码工程的styles.xml中新增一个style。
修改style中登录和注册按钮的颜色,其对应的参数为ali_sdk_openaccount_attrs_next_step_bg。
<style name="NewLogin" parent="@style/Login"> //修改item属性的值 <item name="ali_sdk_openaccount_attrs_next_step_bg">@color/color_1FC88B</item> </style>
修改AndroidManifest中的activity的主题配置,使设置的颜色生效。
//AndroidManifest中的activity的主题配置修改 <activity android:name="com.aliyun.iot.ilop.demo.page.login3rd.OALoginActivity" android:configChanges="orientation|screenSize|keyboardHidden|locale|layoutDirection|keyboard" android:theme="@style/NewLogin" />
修改现有控件的事件
如果您需要修改现有控件的事件,只需重新设置控件事件即可。以重写登录界面中的登录事件为例,即重新定义下图所示内容。
修改登录超限提示信息样式
登录App时,如果输入登录密码的次数达到上限,App会限制继续操作,并提示重置密码。如果您需要修改该失败提示对话框的样式,只需修改toastUtils.alert()
即可。
重写
toastUtils.alert()
的代码。//OALoginActivity中的LoginTask protected class LoginTask extends TaskWithDialog<Void, Void, Result<LoginResult>> { private String loginId; private String password; private String sig; private String nocToken; private String cSessionId; public LoginTask(Activity activity, String loginId, String password, String sig, String nocToken, String cSessionId) { super(activity); this.loginId = loginId; this.password = password; this.sig = sig; this.nocToken = nocToken; this.cSessionId = cSessionId; } protected Result<LoginResult> asyncExecute(Void... params) { Map<String, Object> loginRequest = new HashMap(); if (this.loginId != null) { loginRequest.put("loginId", this.loginId); } if (this.password != null) { try { String rsaKey = RSAKey.getRsaPubkey(); if (TextUtils.isEmpty(rsaKey)) { return null; } loginRequest.put("password", Rsa.encrypt(this.password, rsaKey)); } catch (Exception var4) { return null; } } LoginActivity.this.hideSoftInputForHw(); Result result; if (!CommonUtils.isNetworkAvailable()) { if (ConfigManager.getInstance().isSupportOfflineLogin()) { return LoginActivity.this.tryOfflineLogin(this.loginId, this.password); } else { result = new Result(); result.code = 10014; result.message = MessageUtils.getMessageContent(10014, new Object[0]); return result; } } else { if (this.sig != null) { loginRequest.put("sig", this.sig); } if (!TextUtils.isEmpty(this.cSessionId)) { loginRequest.put("csessionid", this.cSessionId); } if (!TextUtils.isEmpty(this.nocToken)) { loginRequest.put("nctoken", this.nocToken); } result = OpenAccountUtils.toLoginResult(RpcUtils.pureInvokeWithRiskControlInfo("loginRequest", loginRequest, "login")); return ConfigManager.getInstance().isSupportOfflineLogin() && result.code == 10019 ? LoginActivity.this.tryOfflineLogin(this.loginId, this.password) : result; } } protected void doWhenException(Throwable t) { this.executorService.postUITask(new Runnable() { public void run() { ToastUtils.toastSystemError(LoginTask.this.context); } }); } protected void onPostExecute(Result<LoginResult> result) { this.dismissProgressDialog(); super.onPostExecute(result); try { if (result == null) { if (ConfigManager.getInstance().isSupportOfflineLogin()) { ToastUtils.toastNetworkError(this.context); } else { ToastUtils.toastSystemError(this.context); } } else { android.net.Uri.Builder builder; Intent h5Intent; String accountName; switch(result.code) { case 1: if (result.data != null && ((LoginResult)result.data).loginSuccessResult != null) { SessionData sessionData = OpenAccountUtils.createSessionDataFromLoginSuccessResult(((LoginResult)result.data).loginSuccessResult); if (sessionData.scenario == null) { sessionData.scenario = 1; } LoginActivity.this.sessionManagerService.updateSession(sessionData); accountName = ((LoginResult)result.data).userInputName; if (TextUtils.isEmpty(accountName)) { accountName = this.loginId; } if (ConfigManager.getInstance().isSupportOfflineLogin()) { OpenAccountSDK.getSqliteUtil().saveToSqlite(this.loginId, this.password); } boolean isExist = LoginActivity.this.loginIdEdit.saveInputHistory(accountName); if (AccountPasswordLoginFlow.showTipAlertAfterLogin && !isExist) { String message = ResourceUtils.getString(LoginActivity.this.getApplicationContext(), "ali_sdk_openaccount_dynamic_text_alert_msg_after_login"); LoginActivity.this.showTipDialog(String.format(message, this.loginId)); } else { LoginActivity.this.loginSuccess(); } return; } break; case 2: SessionData sessionData1 = OpenAccountUtils.createSessionDataFromLoginSuccessResult(((LoginResult)result.data).loginSuccessResult); if (sessionData1.scenario == null) { sessionData1.scenario = 1; } LoginActivity.this.sessionManagerService.updateSession(sessionData1); LoginActivity.this.loginSuccess(); break; case 4037: if (AccountPasswordLoginFlow.showAlertForPwdErrorToManyTimes) { String postive = LoginActivity.this.getResources().getString(string.ali_sdk_openaccount_text_confirm); accountName = LoginActivity.this.getResources().getString(string.ali_sdk_openaccount_text_reset_password); final ToastUtils toastUtils = new ToastUtils(); android.content.DialogInterface.OnClickListener postiveListener = new android.content.DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { toastUtils.dismissAlertDialog(LoginActivity.this); } }; android.content.DialogInterface.OnClickListener negativeListener = new android.content.DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { LoginActivity.this.forgetPassword((View)null); } }; //重写toastUtils类的alert()方法 toastUtils.alert(LoginActivity.this, "", result.message, postive, postiveListener, accountName, negativeListener); } else { ToastUtils.toast(this.context, result.message, result.code); } break; case 26053: if (result.data != null && ((LoginResult)result.data).checkCodeResult != null && !TextUtils.isEmpty(((LoginResult)result.data).checkCodeResult.clientVerifyData)) { builder = Uri.parse(((LoginResult)result.data).checkCodeResult.clientVerifyData).buildUpon(); builder.appendQueryParameter("callback", "https://www.alipay.com/webviewbridge"); h5Intent = new Intent(LoginActivity.this, LoginDoubleCheckWebActivity.class); h5Intent.putExtra("url", builder.toString()); h5Intent.putExtra("title", result.message); h5Intent.putExtra("callback", "https://www.alipay.com/webviewbridge"); LoginActivity.this.startActivityForResult(h5Intent, RequestCode.NO_CAPTCHA_REQUEST_CODE); return; } break; case 26152: if (result.data != null && ((LoginResult)result.data).checkCodeResult != null && !TextUtils.isEmpty(((LoginResult)result.data).checkCodeResult.clientVerifyData)) { builder = Uri.parse(((LoginResult)result.data).checkCodeResult.clientVerifyData).buildUpon(); builder.appendQueryParameter("callback", "https://www.alipay.com/webviewbridge"); h5Intent = new Intent(LoginActivity.this, LoginIVWebActivity.class); h5Intent.putExtra("url", builder.toString()); h5Intent.putExtra("title", result.message); h5Intent.putExtra("callback", "https://www.alipay.com/webviewbridge"); LoginActivity.this.startActivityForResult(h5Intent, RequestCode.RISK_IV_REQUEST_CODE); } break; default: if (TextUtils.equals(result.type, "CALLBACK") && LoginActivity.this.getLoginCallback() != null) { LoginActivity.this.getLoginCallback().onFailure(result.code, result.message); return; } LoginActivity.this.onPwdLoginFail(result.code, result.message); } } } catch (Throwable var8) { AliSDKLogger.e("oa", "after post execute error", var8); ToastUtils.toastSystemError(this.context); } } }
定制弹出的对话框,并显示
result.message
的错误信息。toastUtils.alert(LoginActivity.this, "", result.message, postive, postiveListener, accountName, negativeListener);
新增控件和单击事件
当您需要在App中新增一个控件,并添加相应的单击事件时,可以根据以下步骤来操作。
在界面上新增一个控件,并在重写的xml文件中添加控件信息。
在activity中添加该控件的单击事件。
新增邮箱登录方式
如果您需要App支持通过邮箱方式登录,您需要开发邮箱相关的功能,包括邮箱登录(图示中①)、邮箱注册(图示中②)、邮箱重置密码(图示中③)等。
在App登录页面增加邮箱登录的方式。
Android账号及用户SDK的OALoginActivity已默认支持手机号登录和邮箱登录。此时您只需要将手机区号隐藏,并修改登录提示即可。
隐藏手机区号。
//隐藏手机区号 OpenAccountUIConfigs.AccountPasswordLoginFlow.supportForeignMobileNumbers = false;
修改邮箱登录信息。
//修改登录提示信息 this.loginIdEdit.getEditText().setHint("请输入手机号或邮箱账号");
新增邮箱注册功能。
在登录页面增加邮箱注册按钮。
请参见本文档中新增控件和单击事件来实现。
定义注册的回调函数。
//注册的回调函数 private EmailRegisterCallback getEmailRegisterCallback() { return new EmailRegisterCallback() { @Override public void onSuccess(OpenAccountSession session) { //注册成功 } @Override public void onFailure(int code, String message) { //注册失败 } @Override public void onEmailSent(String email) { } }; }
跳转到邮箱注册界面。
//跳转到邮箱注册界面 OpenAccountUIService openAccountUIService = OpenAccountSDK.getService(OpenAccountUIService.class); openAccountUIService.showEmailRegister(OALoginActivity.this, getEmailRegisterCallback());
新增邮箱重置密码功能。
通过邮箱方式登录App时,如果忘记了邮箱注册的密码,需要通过邮箱重置密码的功能来找回密码。
在登录页面增加邮箱找回按钮。
请参见本文档中新增控件和单击事件来实现。
定义邮箱密码找回的回调方法。
private EmailResetPasswordCallback getEmailResetPasswordCallback() { return new EmailResetPasswordCallback() { @Override public void onSuccess(OpenAccountSession session) { //修改成功 } @Override public void onFailure(int code, String message) { //修改失败 } @Override public void onEmailSent(String email) { //发送验证码邮件 } }; }
跳转到修改密码界面。
OpenAccountUIService openAccountUIService = (OpenAccountUIService) OpenAccountSDK.getService(OpenAccountUIService.class); openAccountUIService.showEmailResetPassword(this, this.getEmailResetPasswordCallback());
更多UI定制参考
如果您还需定制更多的UI,例如修改更多原生元素,您可以根据以下内容来自行实现。
修改更多组件的样式
账号及用户SDK开放了所有组件的样式,在SDK的deali_sdk_openaccount_styles.xml里定义了可以直接覆盖的所有样式。您可以继承对应的style再修改AndroidManifest.xml中activity的配置。详细操作请参见本文档中修改登录和注册按钮的颜色来实现。
修改OA界面布局
控件或Activity通过LayoutMapping类来加载layout文件。建议您不要修改现有控件的ID,直接新增控件来加载自定义的layout文件。
com.alibaba.sdk.android.openaccount.ui.LayoutMapping.put(控件(或activity).class,R.layout.xxx);
您可以在下图所示目录下查找所需的layout文件。
定制OA模块界面
如果您需要自定义整个界面,建议您集成原先界面的activity后,再替换SDK中整个界面的内容。您可以参照以下示例代码来实现。
//以登录界面为例 //1.继承LoginActivity,重写登录界面为OALoginActivity public class OALoginActivity extends LoginActivity{} //2.在 OALoginActivity中重写getLayoutName方法,将布局文件的名称返回 @Override protected String getLayoutName() { //替换成自己的布局文件名称 return "ali_sdk_openaccount_login2"; } //3.在账号及用户SDK初始化后,将登录界面替换到SDK中 OALoginAdapter adapter = (OALoginAdapter) LoginBusiness.getLoginAdapter(); adapter.setDefaultLoginClass(OALoginActivity.class);
说明在重写界面时,需将原界面中的控件全部添加上,且保持ID不变。不需要的控件隐藏处理,请勿删除,否则可能出现找不到控件的错误。
如果您还需定制除原生元素以外的内容,可以参考以下信息来实现。