UI定制化开发文档
一、背景
部分客户希望授权页面自定义
二、目标
支持客户全部/部分 UI自定义
三、如何开发配置
3.1 Native场景
3.1.1 引入相关包
// in build.gradle
implementation "com.aliyun.emas.suite.foundation:mini-app-plugin-base:xxx"
3.1.2 预定义UI接口
public interface UIExtension {
public default Fragment createMoreDialogFragment(HashMap<String, Object> params) { return null; }
public default Fragment createFavoriteDialogFragment(HashMap<String, Object> params) { return null; }
public default Fragment createAuthDialogFragment(HashMap<String, Object> params) { return null; }
public default Fragment createLoadingFragment(HashMap<String, Object> params) { return null; }
public default Fragment createErrorPageFragment(HashMap<String, Object> params) { return null; }
public default Fragment createSplashFragment(HashMap<String, Object> params) { return null; }
public default void createStyle(HashMap<String, Object> params) { return ; }
public default void createTheme(HashMap<String, Object> params) { return ; }
}3.1.3 实现部分或全部接口
@Override
public Fragment createMoreDialogFragment(HashMap<String, Object> params) {
MoreDialogFragment fragment = MoreDialogFragment.newInstance("/ui/more", arguments);
return fragment;
}
@Override
public Fragment createAuthDialogFragment(HashMap<String, Object> params) {
AuthDialogFragment fragment = AuthDialogFragment.newInstance("/ui/auth", arguments);
return fragment;
}3.1.4 实现插件
public class CustomUIPlugin extends BasePlugin implements UIExtension {
public CustomUIPlugin(Context context) {
super(context);
}
@Override
public Fragment createMoreDialogFragment(HashMap<String, Object> params) {
MoreDialogFragment fragment = MoreDialogFragment.newInstance("/ui/more", arguments);
return fragment;
}
@Override
public Fragment createAuthDialogFragment(HashMap<String, Object> params) {
AuthDialogFragment fragment = AuthDialogFragment.newInstance("/ui/auth", arguments);
return fragment;
}
...
}3.1.5 注册插件
private void initWindVaneMiniApp() {
// 1. config the MiniAppService params
MiniAppInitConfig config = new MiniAppInitConfig.Builder()
.setUseWindVane(true)
.setUseUniApp(false)
.setHost("poc.superapp-intl.com")
.setAppCode("YourAppCode")
.setAccessKey("YourAccessKey")
.setSecretKey("YourSecretKey")
.build();
// 2. create miniAppService object and init it
IMiniAppService miniAppService = new MiniAppService();
miniAppService.initialize(application, config);
...
// 2. register plugin
miniAppService.registerPlugin("CustomUIPlugin", CustomUIPlugin(this));
}3.2 Flutter场景
3.2.1 引入相关包
// in build.gradle
implementation "com.aliyun.emas.suite.foundation:mini-app-plugin-base:xxx"
3.2.2 实现FlutterFragment容器 Implement FlutterFragment Container
对于想使用flutter页面展示弹框的客户需要先实现FlutterFragment容器
public class FlutterAuthDialogFragment extends FlutterFragment {
private static final String TAG = FlutterAuthDialogFragment.class.getName();
public FlutterAuthDialogFragment() {
// Required empty public constructor
}
// TODO: Rename and change types and number of parameters
public static FlutterFragment newInstance(String route, Map<String, Object> arguments) {
praseParams(arguments);
FlutterFragment flutterFragment = FlutterAuthDialogFragment.withNewEngine()
.initialRoute(route)
.dartEntrypoint(dartEntrypoint)
.build();
return flutterFragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_flutter_auth_dialog, container, false);
}
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
GeneratedPluginRegistrant.registerWith(flutterEngine);
// "flutter_auth_dialog" is flutter channel name
new MethodChannel(flutterEngine.getDartExecutor().getBinaryMessenger(), "flutter_auth_dialog").setMethodCallHandler(
new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
IAuthService authService = PluginEnv.getInstance().getContainerContext().getAuthService();
if (FlutterUIPluginConstant.FLUTTER_APPROVAL_AUTH_ACTION.equals(call.method)) {
Log.i(TAG, "approval auth");
Map<String, Object> arguments = (Map<String, Object>)call.arguments;
String permission = (String)arguments.get("permission");
String userId = (String)arguments.get("userId");
String miniAppId = (String)arguments.get("miniAppId");
// Handle approval authorization actions
authService.applyAuth(FlutterAuthDialogFragment.this.getActivity(), permission, userId, miniAppId)
// return 'result' to flutter code
result.success(true);
} else if (FlutterUIPluginConstant.FLUTTER_CHECK_AUTH_ACTION.equals(call.method)) {
Log.i(TAG, "check auth");
Map<String, Object> arguments = (Map<String, Object>)call.arguments;
String permission = (String)arguments.get("permission");
String userId = (String)arguments.get("userId");
String miniAppId = (String)arguments.get("miniAppId");
// Handle check authorization actions
boolean isAuthorized = authService.isAuthorized(FlutterAuthDialogFragment.this.getActivity(), permission, userId, miniAppId);
// return 'result' to flutter code
result.success(isAuthorized);
} else {
result.notImplemented();
}
}
}
);
}
}3.2.3 实现flutter授权页面
class AuthListPage extends StatelessWidget {
AuthListPage({super.key});
final List<String> permissionsItem = [
"location",
"album",
"camera",
"bluetooth",
"contacts",
"microphone",
"file",
"call",
"vibrate",
"screen",
];
final List<bool> approvalItem = [
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
];
@override
Widget build(BuildContext context) {
return SizedBox(
height: 1000,
child: ListView.builder(
itemCount: permissionsItem.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(permissionsItem[index]),
onTap: () {
print("click item:${permissionsItem[index]}");
Map<String, String> args = {
"permission": permissionsItem[index],
"userId": "123",
"miniAppId": "17856810363",
};
WindVaneMiniAppManager.authChannel.invokeMethod(approvalItem[index] ? "flutter_revoke_auth_action" : "flutter_approval_auth_action", args).then((result) {
approvalItem[index] = result;
});
},
);
},
),
);
}
}3.2.4 实现flutter method channel
class WindVaneMiniAppManager {
static const MethodChannel authChannel = const MethodChannel("flutter_auth_dialog");
}3.2.5 声明flutter页面路由
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
onGenerateRoute: (RouteSettings settings) {
final uri = Uri.parse(settings.name ?? '/');
Map<String, String> params = uri.queryParameters;
String path = uri.path;
if (path == "/ui/auth") {
return MaterialPageRoute(builder: (BuildContext context) {
return AuthListPage();
});
} else if (path == "/ui/more") {
return MaterialPageRoute(builder: (BuildContext context) {
return const MoreDialogPage();
});
} else {
...
}
},
initialRoute: 'home',
builder: EasyLoading.init(),
);
}
}3.2.6 实现UI接口
public class FlutterUIPlugin extends BasePlugin implements UIExtension {
public FlutterUIPlugin(Context context) {
super(context);
}
@Override
public Fragment createMoreDialogFragment(HashMap<String, Object> params) {
FlutterMoreDialogFragment fragment = FlutterMoreDialogFragment.newInstance("/ui/more", "");
return fragment;
}
@Override
public Fragment createAuthDialogFragment(HashMap<String, Object> params) {
// "/ui/auth" is flutter page route
FlutterFragment fragment = FlutterAuthDialogFragment.newInstance("/ui/auth", "");
return fragment;
}
}3.2.7 注册插件
private void initWindVaneMiniApp() {
// 1. config the MiniAppService params
MiniAppInitConfig config = new MiniAppInitConfig.Builder()
.setUseWindVane(true)
.setUseUniApp(false)
.setHost("poc.superapp-intl.com")
.setAppCode("YourAppCode")
.setAccessKey("YourAccessKey")
.setSecretKey("YourSecretKey")
.build();
// 2. create miniAppService object and init it
IMiniAppService miniAppService = new MiniAppService();
miniAppService.initialize(application, config);
...
// 2. register plugin
miniAppService.registerPlugin("FlutterUIPlugin", FlutterUIPlugin(this));
}3.3 授权库接口
3.3.1 预定义Auth接口
public interface IAuthService {
public void applyAuth(Context context, String permission, String userId, String miniAppId);
public void applyAuthList(Context context, List<String> permissions, String userId, String miniAppId);
public void revokeAuth(Context context, String permission, String userId, String miniAppId);
public void revokeAuthList(Context context, List<String> permissions, String userId, String miniAppId);
public String queryAuthInfo(Context context, String userId, String miniAppId);
public boolean isAuthorized(Context context, String permission, String userId, String miniAppId);
}3.3.2 引入AuthService
// in build.gradle
implementation "com.aliyun.emas.suite.foundation:mini-app-plugin-base:xxx"
3.3.3 使用AuthService
IAuthService authService = PluginEnv.getInstance().getContainerContext().getAuthService();
authService.authorize(context, permission, userId, miniAppId);