Android FAQ
1.Frequently asked questions when integrating
1.1 What is the minimum environment configuration required to integrate the SDK?
A: The integration SDK requires Android SDK version 19 (Android 4.4) and above.
1.2 What are the specific integration steps?
A: Please refer to the SDK integration documentation
1.3 Do I need to configure obfuscation rules to integrate with the SDK?
A: Configuration is required and the rules for confusion are as follows.
-keep class com.finogeeks.** {*;}1.4 What are the parameters that must be configured when initialising the SDK?
A: At least SDK Key, SDK Secret, server address, server interface request routing prefix, encryption method need to be passed in when initializing the SDK, and the configuration parameters are passed in via the FinAppConfig instance. Prior to version 2.13.102, the SDK only supported the configuration of one server message and could only open applets in a single environment, as follows.
FinAppConfig config = new FinAppConfig.Builder()
.setSdkKey(BuildConfig.SDK_KEY) // SDK Key, issued by the platform after the successful addition of a collaborative application
.setSdkSecret(BuildConfig.APP_SECRET) // SDK Secret, issued by the platform after adding a successful collaborative application
.setApiUrl(BuildConfig.API_URL) // Server address
.setApiPrefix(BuildConfig.API_PREFIX) // Server interface request routing prefix
.setEncryptionType(ENCRYPTION_TYPE_SM) // encryption method, national:SM, md5: MD5
.build();Subscribe to DeepL Pro to edit this document. Visit www.DeepL.com/profor more information. From version 2.13.102 onwards, it supports the configuration of multiple server information, allowing the simultaneous opening of applets in different environments, as follows.
// Collection of server information
List< FinStoreConfig> storeConfigs = new ArrayList<>();
// Information on Server 1
FinStoreConfig storeConfig1 = new FinStoreConfig(
"SDK Key Information", // SDK Key
"SDK Secret information", // SDK Secret
"Address of server 1", // Server address
"Server 1's data upload server address", // the address of the data upload server
"/api/v1/mop/", // Server interface request routing prefix
"",
"encryption method" // encryption method, national:SM, md5: MD5
);
storeConfigs.add(storeConfig1);
// Information on Server 2
FinStoreConfig storeConfig2 = new FinStoreConfig(
"SDK Key Information", // SDK Key
"SDK Secret information", // SDK Secret
"Address of server 2", // Server address
"Server 2's data upload server address", // the address of the data upload server
"/api/v1/mop/", // Server interface request routing prefix
"",
"encryption method" // encryption method, national:SM, md5: MD5
);
storeConfigs.add(storeConfig2);
FinAppConfig config = new FinAppConfig.Builder()
.setFinStoreConfigs(storeConfigs) // A collection of server information
.build();1.5 What parameters are optionally configured when initialising the SDK?
A: Apart from the mandatory parameters mentioned above, all other parameters are configured according to your own choice, mainly including UI configuration and grey scale release rule configuration. The UI configuration is as follows.
// UI configuration
FinAppConfig.UIConfig uiConfig = new FinAppConfig.UIConfig();
// Whether to hide the top right corner close button
uiConfig.setHideNavigationBarCloseButton(false);
// Whether to hide the "Forward" button in the "More" menu
uiConfig.setHideForwardMenu(false);
// Whether to hide "Feedback & Complaints" in the More menu
uiConfig.setHideFeedbackAndComplaints(false);
// Whether to hide the "Back to Home" button in the navigation bar
uiConfig.setHideBackHome(false);
// Whether the back button is always displayed when the navigation bar is the default navigation bar
uiConfig.setAlwaysShowBackInDefaultNavigationBar(false);
// Navigation bar title text style
uiConfig.setNavigationBarTitleTextAppearance(R.style.TextAppearance_AppCompat);
// Gravity of the navigation bar title relative to the parent control
uiConfig.setNavigationBarTitleTextLayoutGravity(Gravity.CENTER);
// Whether to clear the background of the navigation buttons in the navigation bar
uiConfig.setClearNavigationBarNavButtonBackground(true);
// "More" menu style
uiConfig.setMoreMenuStyle(UIConfig.MORE_MENU_DEFAULT);
// Capsule button configuration
uiConfig.setCapsuleConfig(new CapsuleConfig());APM data reporting extensions are as follows.
// APM data reporting extended information
Map< String, Object> apmExtendInfo = new HashMap<>();
apmExtendInfo.put("key1", "value1");
apmExtendInfo.put("key2", "value2");The optional parameters are passed to the SDK via the FinAppConfig instance along with the mandatory parameters as follows.
// UI configuration
FinAppConfig.UIConfig uiConfig = new FinAppConfig.UIConfig();
// Whether to hide the top right corner close button
uiConfig.setHideNavigationBarCloseButton(false);
// Whether to hide the "Forward" button in the "More" menu
uiConfig.setHideForwardMenu(false);
// Whether to hide the "Settings" button in the "More" menu
uiConfig.setHideSettingMenu(false);
// Whether to hide "Feedback & Complaints" in the More menu
uiConfig.setHideFeedbackAndComplaints(false);
// Whether to hide the "Back to Home" button in the navigation bar
uiConfig.setHideBackHome(false);
// Whether the back button is always displayed when the navigation bar is the default navigation bar
uiConfig.setAlwaysShowBackInDefaultNavigationBar(false);
// Navigation bar title text style
uiConfig.setNavigationBarTitleTextAppearance(R.style.TextAppearance_AppCompat);
// Gravity of the navigation bar title relative to the parent control
uiConfig.setNavigationBarTitleTextLayoutGravity(Gravity.CENTER);
// Whether to clear the background of the navigation buttons in the navigation bar
uiConfig.setClearNavigationBarNavButtonBackground(true);
// "More" menu style
uiConfig.setMoreMenuStyle(UIConfig.MORE_MENU_DEFAULT);
// Capsule button configuration
uiConfig.setCapsuleConfig(new CapsuleConfig());
// APM data reporting extended information
Map< String, Object> apmExtendInfo = new HashMap<>();
apmExtendInfo.put("key1", "value1");
apmExtendInfo.put("key2", "value2");
// Domains where cookies need to be removed
List< String> needToRemoveCookiesDomains = new ArrayList<>();
needToRemoveCookiesDomains.add("https://aaa.bbb.ccc");
FinAppConfig config = new FinAppConfig.Builder()
.setSdkKey(BuildConfig.SDK_KEY) // SDK Key, issued by the platform after the successful addition of a collaborative application
.setSdkSecret(BuildConfig.APP_SECRET) // SDK Secret, issued by the platform after adding a successful collaborative application
.setApiUrl(BuildConfig.API_URL) // Server address
.setApiPrefix(BuildConfig.API_PREFIX) // Server interface request routing prefix
.setDebugMode(BuildConfig.DEBUG) // Whether the application is currently in Debug mode
.setUiConfig(uiConfig) // UI configuration
.setApmExtendInfo(apmExtendInfo) // APM data upload extension information
.setEncryptionType(ENCRYPTION_TYPE_SM) // encryption method, national:SM, md5: MD5
.setDisableRequestPermissions(true) // disable requesting runtime permissions, not by default
.setAppletAutoAuthorize(false) // whether to enable automatic granting of applet Scope permissions, not enabled by default
.setNeedToRemoveCookiesDomains(needToRemoveCookiesDomains) // Domains from which cookies need to be removed
.setDisableTbs(true) // whether to disable the Tbs SDK, not by default
.setCustomWebViewUserAgent("aaa/111; bbb") // Custom WebView UserAgent
.setAppletIntervalUpdateLimit(6) // Timed batch update of the number of applets
.setForegroundServiceConfig(new FinAppConfig.ForegroundServiceConfig(true, R.drawable.ic_launcher, "applet is running", "")) // Whether to launch foreground services when the applet is running in the foreground
.setBindAppletWithMainProcess(true) // The applet is bound to the app process, the app is killed, whether the applet is closed simultaneously, default is false
.setWebViewMixedContentMode(MIXED_CONTENT_ALWAYS_ALLOW) // Set WebView mixed content mode
.setAppletText("X app") // Replace the "applet" text in the SDK with "X app"
.setEnableApmDataCompression(true) // whether to compress data when reporting data, default is no compression
.setDisableGetSuperviseInfo(true) // Whether to disable calls to the applet API for getting supervise information, default no
.setUserId("UserId") // Set the user ID
.build();1.6 Is there anything in particular that needs attention when initialising the SDK?
A: The SDK is implemented using a multi-process mechanism, with each applet running in a separate process, i.e.one applet corresponds to one process.When initialising the SDK, one point to note in particular is that the applet process does not need to perform any initialisation operations when it is created, even if the initialisation of the applet SDK is not performed in the applet process. For example, if the application uses some third-party libraries that need to be initialized when the application starts, then when the initialization is performed in Application, only the current process needs to initialize these third-party libraries if it is the host process, the applet process does not need to initialize these libraries. Therefore, before initializing the SDK, be sure to determine which process the current process is, if it is an applet process and does not need to handle cross-process call interfaces or register api in applet process, no action will be taken:.
/**
* Application of {@link android.app.}
*/
public class AppletApplication extends MultiDexApplication {
@Override
public void onCreate() {
super.onCreate();
// The code to determine if it is an applet process is placed at the top
if (FinAppClient.INSTANCE.isFinAppProcess(this)) {
return;
}
// Other codes to follow
................................................
................................................
}
}1.7 How do I resolve a dependency conflict problem when integrating?
A: Third-party libraries that the Android applet SDK relies on
// appcompat-v7
implementation "com.android.support:appcompat-v7:23.0.0"
// support-v4
implementation "com.android.support:support-v4:23.0.0"
// Recyclerview
implementation "com.android.support:recyclerview-v7:23.2.0"
// Kotlin
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.3.61"
// Gson
implementation "com.google.code.gson:gson:2.2.2"
// zxing
implementation "com.google.zxing:core:3.3.0"
implementation "com.google.zxing:android-core:3.3.0"
// SdkCore
implementation "com.finogeeks.finochat.sdk:sdkcore:2.15.1"The sdk dependencies are managed using gradle.When the app and sdk depend on the same library, gradle will automatically handle the conflict and use the library with the higher version number. If a library in the app that is dependent on the sdk via a jar package or source code conflicts with the sdk, you can exclude the sdk dependency by using the exclude command. For example.
implementation('com.finogeeks.lib:finapplet:2.21.1') {
exclude group: "com.tecent.smtt"
}It is also advisable to use gradle to manage dependencies
1.7.1 What if I encounter a duplicate class in zxing:android-core?
sdk uses the zxing:android-core library, because the zxing-android-embedded library duplicates the CameraConfigurationUtils class name in android-core, some users may have a class name conflict after using the zxing-android-embedded library.Some users may experience class name conflicts after using the zxing-android-embedded library. In this case the dependencies can be removed with the exclude command For example.
implementation('com.finogeeks.lib:finapplet:2.21.1') {
exclude group: "com.google.zxing" , module: "android-core"
}2.Frequently asked questions when using
2.1 How do I start the applet?
1.If the applet is started without start parameters, it is started by calling the startApplet(context: Context, appId: String) method of the IAppletApiManager interface, as follows.
FinAppClient.INSTANCE.getAppletApiManager().startApplet(context,
"appId");2.If the applet is started with start parameters, it is started by calling the startApplet(context: Context, appId: String, startParams: Map<String, String>) method of the IAppletApiManager interface.As follows.
Map< String, String> params = new HashMap<>();
// path is the path to the applet page
params.put("path", "/pages/index/index");
// query is the start parameter, with the content
"key1=value1&key2=value2 ..." in the form of
params.put("query", "aaa=test&bbb=123");
FinAppClient.INSTANCE.getAppletApiManager().startApplet(this,
"appId", params);2.2 After launching multiple applets in the host app, why do I see multiple applet tasks in addition to the host app inside the recent taskbar list on Android?
A: Because the Android applet SDK is implemented using a multi-process mechanism, the host application is a process, and each applet is also divided into a separate process.In the recent taskbar of Android, different processes will be displayed separately, so you will see multiple applets being opened. This is also the case with the mainstream applets, such as Phiz applet for Android and Baidu Smart applet for Android.
2.3 Does the applet interface support extensions? I.e.is it possible for applets to call their own interfaces in addition to the standard set of interfaces provided internally by the SDK? If so, how would it be implemented?
A: The SDK allows you to register a custom applet interface, which is the same as the standard interface inside the SDK and can be called by the applet. The steps to achieve this are as follows. 1.Implement a custom applet interface.
IApi declares the two most core methods that the applet interface needs to implement, namely apis(); and invoke(String event, JSONObject param, ICallback callback);, with the following code.
/**
* :: API interface for the applet, which is required to implement the
API for the corresponding function
*/
public interface IApi extends ILifecycle {
/**
* @return An array of names of callable APIs
*/
String[] apis();
/**
* This method is triggered when an API call is received, in which specific business logic is implemented
*
* @param event event name, i.e.API name
* @param param Parameters
* @param callback Callback interface
*/
void invoke(String event, JSONObject param, ICallback callback);
}Implementing a custom interface requires creating a class and having that class inherit from AbsApi, a subclass of IApi, and then overriding the apis() method and the invoke() method.apis() returns an array of the names of all the APIs that can be called, by implementing apis() to declare all the APIs that need to be implemented. invoke() will be triggered when the applet calls the API, where event is the name of the API, param is the parameter corresponding to the API, and callback is used to call back data to the applet after the call logic is executed. For example, we customize an applet interface for a simple page jump function with the following code.
/**
* Custom applet interface for a simple page jump
*/
public class ApiOpenPage extends AbsApi {
private static final String API_NAME_OPEN_PAGE = "openPage";
private Context mContext;
public ApiOpenPage(Context context) {
mContext = context;
}
/**
* @return An array of names of callable APIs
*/
@Override
public String[] apis() {
return new String[]{API_NAME_OPEN_PAGE};
}
/**
* This method is triggered when an API call is received, in which
specific business logic is implemented
*
* @param event event name, i.e.the name of the API
* @param param Parameters
* @param callback Callback interface
*/
@Override
public void invoke(String event, JSONObject param, ICallback
callback) {
if (API_NAME_OPEN_PAGE.equals(event)) {
String url = param.optString("url");
if (! TextUtils.isEmpty(url)) {
Intent intent = new Intent();
intent.setClass(mContext, SecondActivity.class);
if (! (mContext instanceof Activity)) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
mContext.startActivity(intent);
callback.onSuccess(null);
} else {
callback.onFail();
}
}
}
}2.Register the custom applet interface.
Registration is achieved by calling the registerApi method of the IExtensionApiManager interface.As follows.
FinAppClient.INSTANCE.getExtensionApiManager().registerApi(new
ApiOpenPage(context));If you need to register more than one interface at a time, you can call registerApis, passing in a collection of interfaces as an argument. After registering the custom applet interface in the SDK, you need to create a PhizClipConf.js file in the root directory of the applet project and configure the corresponding custom interface in PhizClipConf.js.An example configuration is as follows.
module.exports = {
extApi:[
{
name: 'openPage', // extension interface name
params: { // extend the interface parameters, you can list
only the required parameters
url: '',
title: '',
description: ''
}
}
]
}4.call the individual APIs in the registered interfaces in the applet.
2.4 Can a web page call native code when the applet loads a web page?
A: Native code can be called from within the web pages of the applet, and the JSSDK provides a series of interfaces that enable native code to be called from within the web pages.
2.5 Does the JSSDK interface support extensions? I.e.is it possible for an applet to call its own provided interface in a web page, in addition to the standard set of interfaces provided within the JSSDK? If so how would this be achieved?
A: JSSDK interface support is extended.sdk allows for the registration of custom JSSDK interfaces, after registration the custom JSSDK interfaces are the same as the standard interfaces provided within JSSDK and can be called by applets in web pages. The steps to achieve this are as follows. 1.Implement the custom JSSDK interface.
This step is the same as implementing a custom applet interface, by inheriting AbsApi and overriding the apis() method and invoke() method to implement the custom JSSDK interface. 1.Register the custom JSSDK interface.
Registration is achieved by calling the registerApi method of the IExtensionWebApiManager interface.As follows.
FinAppClient.INSTANCE.getExtensionWebApiManager().registerApi(new
ApiOpenPage(context));If you need to register more than one interface at a time, you can call registerApis, passing in a collection of interfaces as an argument. For details, you can check Register applet WebView component API.
2.6 After jumping to other pages of the host app in the invoke() method of the custom interface, and doing a series of operations, pressing the system return button to return to the applet, it ends up returning to the page in the host app where the applet was launched, why?
1.Reason. The step of jumping to other pages of the host App starts the Activity through the Context instance in the host App and does not press the Activity into a new task stack. The Android applet SDK is a multi-process architecture, the applet and the host app are in different processes, and the task stacks they are in are naturally different.When the applet jumps to the host App's page, the newly opened page is added to the original task stack of the host App.When returning from the page, the logic executed is to pop up the page in the original task stack in the native App, so you will see the pages of the native App being closed one by one, and finally return to the page where the native App launches the applet, and does not return to the applet. 2.Solutions. Option 1 (recommended):
Jump to other pages of the host app via startActivity or startActivityForResult of ICallback. This is the recommended solution, as this opens the Activity of the new host app in the task stack where the applet is located, and the in-stacking and out-stacking of the Activity is done in the same task stack, without the process of task stack switching. A more important reason is that if you need to start the Activity by startingActivityForResult and get the returned data when the page returns, only with this solution will the custom interface's onActivityResult be executed to get the returned data. Examples of the use of this programme.
@Override
public void invoke(String event, JSONObject param, ICallback callback) {
Intent intent = new Intent();
intent.setClass(mContext, SecondActivity.class);
callback.startActivityForResult(intent, 100);
}Option 2 (not recommended):
If you must use the Context instance in the host App to start the Activity, you need to set the Intent flags of "Support multi-task stack" and "Open new task stack" for the Intent that starts the native page, so that a new task stack can be opened in the native After the new task stack is opened, the newly opened pages will be pressed into this new task stack one by one, and when all the operations of the native pages are finished and returned one by one, the pages will be ejected one by one from this new task stack, and when all the pages in this new task stack are ejected, it will return to the task stack of the applet process.
Therefore, in the invoke() method of the custom interface, if you need to jump to other pages of the native application to perform certain actions and expect to return to the applet when these native pages are closed, then it is recommended to add both Intent.FLAG_ACTIVITY_MULTIPLE_TASK ' and FLAG_ACTIVITY_NEW_TASKto theIntent` object when executing the jump, as follows.
Intent intent = new Intent();
intent.setClass(context, SecondActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent); // context is the Context instance in the host AppWith this solution, if the Activity is started via startActivityForResult, the custom interface's onActivityResult will not be called when the page returns, so it is not recommended.
2.7 Can I call JS functions in a web page in native code?
A: The SDK supports native code calling js functions.The call can be achieved by calling the callJS method of the IAppletApiManager interface, as follows.
JSONObject funcParams = new JSONObject();
try {
funcParams.put("param1", "value1");
funcParams.put("param2", "value2");
FinAppClient.INSTANCE.getAppletApiManager().callJS(
"appId",
"funcName",
funcParams.toString(),
-1,
new FinCallback< String>() {
@Override
public void onSuccess(String result) {
Log.d(TAG, "callJS onSuccess : " + result);
}
@Override
public void onError(int code, String error) {
Log.d(TAG, "callJS onError : " + code + ", " +
error);
}
@Override
public void onProgress(int status, String info) {
}
});
} catch (JSONException e) {
e.printStackTrace();
}2.8 How do I set the transition animation of an Activity in an applet?
A: Set the transition animation of the Activity in the applet by calling the setActivityTransitionAnim method of the IAppletApiManager interface, as follows.
FinAppClient.INSTANCE.getAppletApiManager().
setActivityTransitionAnim(SlideFromRightToLeftAnim.INSTANCE);Five types of animation are currently available for setting. 1.NoneAnim: no animation. 1.SlideFromLeftToRightAnim: slide animation - left in, right out. 1.SlideFromRightToLeftAnim: slide animation - right in, left out. 1.SlideFromTopToBottomAnim: slide animation - top in, bottom out. 1.SlideFromBottomToTopAnim: slide animation - bottom in, top out.
2.9 How do I share an applet to a platform that supports it, such as Phiz?
A: To implement the applet sharing function, the general idea is to first obtain the relevant information needed to share the applet, then convert the obtained information into the parameters of the sharing interface, and finally call the sharing interface to share the applet to the corresponding platform.There are two main implementation options. 1.Implement the shareAppMessage method of the applet abstract business callback interface IAppletHandler and pass the IAppletHandler instance into the SDK.
When you click "Forward" in the applet more menu, the shareAppMessage method of the IAppletHandler instance will be called.Once the parameters are obtained, the third-party sharing SDK can be called to enable sharing.
The shareAppMessage method is as follows.
/**
* Forwarding applets
*
* @param appInfo applet information, a string of json containing
information such as applet id, applet name, applet icon, user id, and
the content of the data forwarded.
* The content of [appInfo] is in the following format.
* {
* "appTitle": "Vantaa Applet",
* "appAvatar":
"https:\/\/www.finogeeks.club\/statics\/images\/swan_mini\/swan_logo.pn
g",
* "appId": "5df36b3f687c5c00013e9fd1",
* "appType": "trial",
* "userId": "finogeeks",
* "cryptInfo":
"SFODj9IW1ENO8OA0El8P79aMuxB1DJvfKenZd7hrnemVCNcJ+Uj9PzkRkf/Pu5nMz0cGjj
0Ne4fcchBRCmJO+
As0XFqMrOclsqrXaogsaUPq2jJKCCao03vI8rkHilrWxSDdzopz1ifJCgFC9d6v29m9jU29
wTxlHsQUtKsk/wz0BROa+aDGWh0rKvUEPgo8mB+40/
zZFNsRZ0PjsQsi7GdLg8p4igKyRYtRgOxUq37wgDU4Ymn/yeXvOv7KrzUT",
* "params": {
* "title": "apt-test-tweet-Interface-test-released-dynamics!
@#$%......&*(",
* "desc": "Service Experts by Your Side",
* "imageUrl": "finfile:\/\/tmp_fc15edd8-2ff6-4c54-9ee9-
fe5ee034033d1576550313667.png",
* "path": "pages\/tweet\/tweet-detail.html?fcid=%40staff_staff1%3A000000.finogeeks.com&timelineId=db0c
2098-031e-41c4-b9c6- 87a5bbcf681d&shareId=3dfa2f78-19fc-42fc-b3a9-
4779a6dac654",
* "appInfo": {
* "weixin": {
* "path":"\/studio\/pages\/tweet\/tweet-detail",
* "query": {
* "fcid":"@staff_staff1:000000.finogeeks.com",
* "timelineId": "db0c2098-031e-41c4-b9c6-87a5bbcf681d"
* }
* }
* }
* }
* }
* Description of the fields in [appInfo].
* appId applet ID
* appTitle applet name
* appAvatar applet avatar
* appType applet type, where trial means experience, temporary
means temporary, review means review, release means online and
development means development
* userId User ID
* cryptInfo Applet encryption information
* other parameters attached to params, passed by the applet itself
*
* @param bitmap The applet cover image.If the
[appInfo].params.imageUrl field is a link address of http, https, then
the applet cover image
* Just take the image corresponding to [appInfo].params.imageUrl,
otherwise the cover image of the applet is taken as [bitmap].
* @param callback Callback for forwarding applet results.
*/
fun shareAppMessage(appInfo: String, bitmap: Bitmap?, callback:
IAppletCallback)An instance of IAppletHandler is passed in by calling the setAppletHandler(appletHandler: IAppletHandler) method of the IAppletApiManager as follows.
FinAppClient.INSTANCE.getAppletApiManager().setAppletHandler(new
IAppletHandler() {
@Override
public void shareAppMessage(@NotNull String appInfo,
@org.jetbrains.annotations.Nullable
Bitmap bitmap,
@NotNull IAppletCallback callback) {
// Implementing the logic of the sharing applet
...........................................................
.
............................................................
}
});2.Implemented through a custom interface.Receive the parameters passed by the applet in the invoke method of the custom interface, and then call the third-party sharing SDK to implement applet sharing.
2.10 How can I inject my own menu items into the "More" menu?
A: As with the abstract business callback interface IAppletHandler, the injection of menu items in the "More" menu is also implemented through IAppletHandler, where IAppletHandler will call back to the host application the interface method getRegisteredMoreMenuItems and the interface method onRegisteredMenuItemClicked for the injected menu items.method getRegisteredMoreMenuItems and the interface method onRegisteredMoreMenuItemClicked for injecting menu items to the host application, which will implement the specific business logic. getRegisteredMoreMenuItems and onRegisteredMoreMenuItemClicked are as follows.
/**
* Get the registered "More" menu item
*
* @param appId applet ID
* @return registered "More" menu item
*/
fun getRegisteredMoreMenuItems(appId: String): List<MoreMenuItem>?
/**
* The "More" menu item of the registration is clicked
*
* @param appId applet ID
* @param path applet page path
* @param menuItemId The ID of the clicked menu item
* @param appInfo applet information, a string of json containing
information such as applet id, applet name, applet icon, user id, and
the content of the data forwarded.
* The content of [appInfo] is in the following format.
* {
* "appTitle": "Vantaa Applet",
* "appAvatar":
"https:\/\/www.finogeeks.club\/statics\/images\/swan_mini\/swan_logo.pn
g",
* "appId": "5df36b3f687c5c00013e9fd1",
* "appType": "trial",
* "userId": "finogeeks",
* "cryptInfo":
"SFODj9IW1ENO8OA0El8P79aMuxB1DJvfKenZd7hrnemVCNcJ+Uj9PzkRkf/Pu5nMz0cGjj
0Ne4fcchBRCmJO+
As0XFqMrOclsqrXaogsaUPq2jJKCCao03vI8rkHilrWxSDdzopz1ifJCgFC9d6v29m9jU29
wTxlHsQUtKsk/wz0BROa+aDGWh0rKvUEPgo8mB+40/
zZFNsRZ0PjsQsi7GdLg8p4igKyRYtRgOxUq37wgDU4Ymn/yeXvOv7KrzUT",
* "params": {
* "title": "apt-test-tweet-Interface-test-released-dynamics!
@#$%......&*(",
* "desc": "Service Experts by Your Side",
* "imageUrl": "finfile:\/\/tmp_fc15edd8-2ff6-4c54-9ee9-
fe5ee034033d1576550313667.png",
* "path": "pages\/tweet\/tweet-detail.html?fcid=%40staff_staff1%3A000000.finogeeks.com&timelineId=db0c
2098-031e-41c4-b9c6- 87a5bbcf681d&shareId=3dfa2f78-19fc-42fc-b3a9-
4779a6dac654",
* "appInfo": {
* "weixin": {
* "path":"\/studio\/pages\/tweet\/tweet-detail",
* "query": {
* "fcid":"@staff_staff1:000000.finogeeks.com",
* "timelineId": "db0c2098-031e-41c4-b9c6-87a5bbcf681d"
* }
* }
* }
* }
* }
* Description of the fields in [appInfo].
* appId applet ID
* appTitle applet name
* appAvatar applet avatar
* appType applet type, where trial means experience, temporary means
temporary, review means review, release means online and development
means development
* userId User ID
* cryptInfo Applet encryption information
* other parameters attached to params, passed by the applet itself
*
* @param bitmap The applet cover image.If the
[appInfo].params.imageUrl field is a link address of http, https, then
the applet cover image
* Just take the image corresponding to [appInfo].params.imageUrl,
otherwise the cover image of the applet is taken as [bitmap].
* @param callback The result callback.
*/
fun onRegisteredMoreMenuItemClicked(appId: String, path: String,
menuItemId: String, appInfo: String?, bitmap: Bitmap?, callback:
IAppletCallback)Similarly, the IAppletHandler instance needs to be passed in by calling the setAppletHandler(appletHandler: IAppletHandler) method of the IAppletApiManager. The getRegisteredMoreMenuItems method and the onRegisteredMoreMenuItemClicked method are implemented as follows.
/**
* {@link IAppletHandler} implementation class, used to implement some
business scenarios, such as registering "more" menu items, forwarding
applets, etc.
*/
public class AppletHandler implements IAppletHandler {
@NonNull
private Context mContext;
private AppletHandler() {
}
public AppletHandler(@NonNull Context context) {
this.mContext = context;
}
@Nullable
@Override
public List< MoreMenuItem> getRegisteredMoreMenuItems(@NotNull
String appId) {
List< MoreMenuItem> items = new ArrayList<>();
MoreMenuItem item0 = new MoreMenuItem("WXShareAPPFriends",
"Phiz Good Friends", MoreMenuType.ON_MINI_PROGRAM);
items.add(item0);
MoreMenuItem item1 = new MoreMenuItem("WXShareAPPMoments",
"Phiz Friends", MoreMenuType.ON_MINI_PROGRAM, true);
items.add(item1);
MoreMenuItem item2 = new MoreMenuItem("ShareSinaWeibo", "Sina Weibo
", MoreMenuType.ON_MINI_PROGRAM);
items.add(item2);
MoreMenuItem item3 = new MoreMenuItem("ShareQQFriends", "QQ",
MoreMenuType.ON_MINI_PROGRAM);
items.add(item3);
MoreMenuItem item4 = new MoreMenuItem("ShareDingDing",
"Dingding", MoreMenuType.ON_MINI_PROGRAM);
items.add(item4);
MoreMenuItem item5 = new MoreMenuItem("ShareLinks", "Title
subject to backend configuration", MoreMenuType.ON_MINI_PROGRAM);
items.add(item5);
MoreMenuItem item6 = new MoreMenuItem("SharePicture",
"SharePicture", MoreMenuType.ON_MINI_PROGRAM);
items.add(item6);
MoreMenuItem item7 = new MoreMenuItem("Restart", "Restart",
MoreMenuType.COMMON);
items.add(item7);
MoreMenuItem item8 = new MoreMenuItem("Desktop", "Desktop",
MoreMenuType.COMMON);
items.add(item8);
return items;
}
@Override
public void onRegisteredMoreMenuItemClicked(@NotNull String appId,
@NotNull String path, @NotNull String menuItemId, @Nullable String
appInfo, @ Nullable Bitmap bitmap, @NotNull IAppletCallback callback) {
Toast.makeText(mContext, "applet " + appId + "of " + path +
"page's menu" + menuItemId + "was clicked, appInfo : " + appInfo + "
bitmap : " + bitmap, Toast.LENGTH_SHORT).show();
callback.onSuccess(null);
}
}MoreMenuItem is the menu entry data class, as follows.
/**
* More menu entries
*
* @param id Menu entry ID
* @param title Menu entry title
* @param image Menu entry icon address
* @param icon The resource ID of the menu item icon
* @param type Menu entry type
* @param isEnable whether the menu entry is available
*/
data class MoreMenuItem(val id: String,
val title: String,
val image: String,
@DrawableRes val icon: Int,
val type: MoreMenuType = MoreMenuType.COMMON,
val isEnable: Boolean = true) {
/**
* Constructing methods
* @param id Menu entry ID
* @param title Menu entry title
* @param type Menu entry type [MoreMenuType.COMMON] or
[MoreMenuType.ON_MINI_PROGRAM]
*/
constructor(id: String, title: String, type: MoreMenuType) :
this(id, title, "", -1, type, true)
}MoreMenuType is an enumeration class, as follows.
/**
* More menu types
* [COMMON] is the normal menu type, no interaction with the applet is
required
* [ON_MINI_PROGRAM] is the type of menu that needs to interact with
the applet, such as the share applet button, when you click the button
to share the applet, you may need to get some data about the applet
*/
enum class MoreMenuType {
COMMON, ON_MINI_PROGRAM
}2.11 How to get a screenshot of the current page of the applet?
A: Obtained by calling the captureAppletPicture method of the IAppletApiManager interface, as follows.
FinAppClient.appletApiManager.captureAppletPicture("appId",
object :FinCallback<Bitmap? >{
override fun onSuccess(result: Bitmap? ) {
Log.d(TAG, "Get screenshot of applet page successfully:
$result")
}
override fun onError(code: Int, error: String? ) {
Log.e(TAG, "Failed to get screenshot of applet page: $code,
$error")
}
override fun onProgress(status: Int, info: String? ) {
}
})2.12 How do I block the "Forward" button in the More menu?
A: The initialization of the SDK is configured through UI configuration items as follows.
// UI configuration
FinAppConfig.UIConfig uiConfig = new FinAppConfig.UIConfig();
// Whether to hide the "Forward" button in the "More" menu
uiConfig.setHideForwardMenu(true);2.13 How do I block the "Settings" button in the More menu?
A: The "Settings" menu shows each applet's own Scope permissions.If you want to block the "Settings" portal, you can configure it through the UI configuration item when initializing the SDK, as follows.
// UI configuration
FinAppConfig.UIConfig uiConfig = new FinAppConfig.UIConfig();
// Whether to hide the "Settings" button in the "More" menu
uiConfig.setHideSettingMenu(true);2.14 How do I block the "Back to Home" button in the More menu?
A: The initialization of the SDK is configured through UI configuration items as follows.
// UI configuration
FinAppConfig.UIConfig uiConfig = new FinAppConfig.UIConfig();
// Whether to hide the "Back to Home" menu entry in the "More" menu
uiConfig.setHideBackHome(true);Notes.
The "Back to Home" button in the More menu has been deprecated since version 2.36.1 and has been replaced with a "Back to Home" button on the control navigation bar.
2.15 How do I block the "Feedback & Complaints" portal in the More
menu? A: The initialization of the SDK is configured through UI configuration items as follows.
// UI configuration
FinAppConfig.UIConfig uiConfig = new FinAppConfig.UIConfig();
// Whether to hide "Feedback & Complaints" in the More menu
uiConfig.setHideFeedbackAndComplaints(true);2.16 How do I hide the close button in the navigation bar?
A: The initialization of the SDK is configured through UI configuration items as follows.
// UI configuration
FinAppConfig.UIConfig uiConfig = new FinAppConfig.UIConfig();
// Whether to hide the top right corner close button
uiConfig.setHideNavigationBarCloseButton(true);2.17 How can I display the back button on the home page as well
when the navigation bar is the default style? A: The initialization of the SDK is configured through UI configuration items as follows.
// UI configuration
FinAppConfig.UIConfig uiConfig = new FinAppConfig.UIConfig();
// Whether the back button is always displayed when the navigation bar
is the default navigation bar
uiConfig.setAlwaysShowBackInDefaultNavigationBar(false);2.18 How do I configure the grey scale publishing rules?
A: The same as the abstract business callback interface IAppletHandler, the injection of the grey release configuration parameters is also implemented through IAppletHandler, IAppletHandler will send the interface method getGrayAppletVersionConfigs to the host application to obtain the grey release configuration parameters.getGrayAppletVersionConfigs will be called back to the host application, which will implement the specific business logic.getGrayAppletVersionConfigs` as follows.
/**
* Get the grey-scale release configuration parameters
*
* @param appId applet ID
* @return grayscale release configuration parameters
*/
fun getGrayAppletVersionConfigs(appId: String):
List<GrayAppletVersionConfig>?Similarly, the IAppletHandler instance needs to be passed in by calling the setAppletHandler(appletHandler: IAppletHandler) method of the IAppletApiManager.
2.19 How do I implement a custom navigation bar?
A: Three navigation bar styles are currently available, which are. 1.the default style (default). 1.retain only the custom style (custom) for the "more off" button. 1.Custom style (hide) without the "more close" button and with the native navigation bar completely hidden. By default, the navigationStyle of page and navigationStyle of window in the applet are both default, if developers need to customize the navigation bar style, they can do so by configuring the navigationStyle of page or window .
2.20 Is there support for disabling the SDK from initiating SDK permission requests?
A:** Support.** If the host application wants all SDK permission requests to be managed by itself and does not want the SDK to initiate requests when the permission is used, this can be achieved by configuring parameters when initialising the SDK, as follows.
FinAppConfig finAppConfig = new FinAppConfig.Builder()
.setDisableRequestPermissions(true) // Disable the SDK from
initiating runtime permission requests
.build();2.21 Is there support for configuring applets to automatically grant Scope permissions when they are requested?
A: Support. Scope permissions can be viewed, turned on and off in the applet's "More" - "Settings".By default, each applet will pop up a dialog box to the user when applying for Scope permissions for the first time.If the SDK wants to automatically grant Scope permissions without pop-ups to the user, you can configure parameters to achieve this when initialising the SDK, as follows.
FinAppConfig finAppConfig = new FinAppConfig.Builder()
.setAppletAutoAuthorize(true) // automatically grant
permission to Scope
.build();2.22 How do I adjust the text style of the navigation bar title?
A: The initialization of the SDK is configured through UI configuration items as follows.
// UI configuration
FinAppConfig.UIConfig uiConfig = new FinAppConfig.UIConfig();
// Navigation bar title text style
uiConfig.setNavigationBarTitleTextAppearance(R.style.
TextAppearance_AppCompat);2.23 How do I centre the navigation bar title?
A: The initialization of the SDK is configured through UI configuration items as follows.
// UI configuration
FinAppConfig.UIConfig uiConfig = new FinAppConfig.UIConfig();
// Gravity of the navigation bar title relative to the parent control
uiConfig.setNavigationBarTitleTextLayoutGravity(Gravity.CENTER);2.24 How do I remove the background animation when the back button is pressed in the navigation bar?
A: The initialization of the SDK is configured through UI configuration items as follows.
// UI configuration
FinAppConfig.UIConfig uiConfig = new FinAppConfig.UIConfig();
// Whether to clear the background of the navigation buttons in the
navigation bar
uiConfig.setClearNavigationBarNavButtonBackground(true);2.25 Does the applet support switching between horizontal and vertical screens?
A:** Support.** The applet supports horizontal, vertical and portrait screen switching freely.The screen rotation settings of the applet can be configured globally in window in the app.json file of the applet project, or individually in the .json file of each page. 1.Global configuration in app.json.
{
"window": {
"pageOrientation": "auto" // auto: switch freely between landscape
and portrait, portrait: portrait, landscape: landscape
}
}2.configured separately in the .json file of the page.
{
"pageOrientation": "auto" // auto: switch freely between landscape and
portrait, portrait: portrait, landscape: landscape
}3.The page configuration will override the same configuration in window of app.json on the current page.
2.26 How do I disable the use of the TBS SDK?
A: This is achieved by configuring parameters when initialising the SDK, as follows.
FinAppConfig finAppConfig = new FinAppConfig.Builder()
.setDisableTbs(true) // Set whether to disable the Tbs SDK
.build();2.27 How do I set the number of scheduled batch updates of applets?
A: This is achieved by configuring parameters when initialising the SDK, as follows.
FinAppConfig finAppConfig = new FinAppConfig.Builder()
.setAppletIntervalUpdateLimit(3) // Set the number of
scheduled batch updates to the applet
.build();2.28 How do I set the number of applets that can be opened at the same time?
A: This is achieved by configuring parameters when initialising the SDK, as follows.
FinAppConfig finAppConfig = new FinAppConfig.Builder()
.setMaxRunningApplet(3) // the number of applets that can be
opened at the same time
.build();2.29 Does the applet support control over showing and hiding theMore button in the top right corner?
A:** Support.** This can be achieved by configuring the navigationBarHideMoreButton property.navigationBarHideMoreButton can be configured globally in the window of the app.json file of the applet project, or individually in the .json file of each page. 1.Global configuration in app.json.
{
"window": {
"navigationBarHideMoreButton": true // true: hide the top-right more
button, false: show the top-right more button, default is false.
}
}2.configured separately in the .json file of the page.
{
"navigationBarHideMoreButton": true // true: hide the top-right more
button, false: show the top-right more button, default is false.
}2.30 Can applets control the display and hiding of the close button in the top right corner?
You can.Configure the navigationBarHideCloseButton property to achieve this.navigationBarHideCloseButton can be configured globally in the window of the app.json file of the applet project, or individually in the .json file of each page. 1.Global configuration in app.json.
{
"window": {
"navigationBarHideCloseButton": true // true: hide the top right
close button, false: show the top right close button, default is false.
}
}2.configured separately in the .json file of the page.
{
"navigationBarHideCloseButton": true // true: hide the top right close
button, false: show the top right close button, default is false.
}2.31 Does it support replacing the "applet" text in the SDK with another name?
A:** Support.** This is achieved through the SDK initialisation configuration parameters, as follows.
FinAppConfig finAppConfig = new FinAppConfig.Builder()
.setAppletText("X app") // Replace the "applet" text in the
SDK with "X app"
.build();2.32 When data is reported, is the reported data compressed?
A: When data is reported, the SDK does not compress the reported data by default, if you want to turn on compression, you can do so through the SDK initialization configuration parameters as follows.
FinAppConfig finAppConfig = new FinAppConfig.Builder()
.setEnableApmDataCompression(true) // Set the data to be
compressed when the data is reported
.build();2.33 Does it support disabling the applet API for obtaining regulatory information?
A:** Support.** The SDK by default allows applets to call the applet API (getSuperviseInfo) that obtains regulatory information, to disable this can be done via the SDK initialisation configuration parameters as follows.
FinAppConfig finAppConfig = new FinAppConfig.Builder()
.setDisableGetSuperviseInfo(true) // Set whether to disable
applets from calling the applet API that gets supervise information
.build();When disabled, the applet will receive a getSuperviseInfo:fail disabled callback when it calls getSuperviseInfo.
2.34 Does it support opening the Experience applet?
A:** Support.** The platform supports the configuration of experience versions and experience members for the applet, and members with experience access are able to open the experience version of the applet. Steps for using the Experience applet. 1.Upload the applet in the platform and configure the experience version for the applet, please refer to Enterprise Side Operation Guidelines - 4.4 Debugging 2.Pass in the user ID when initialising the SDK.
val config = FinAppConfig.
.setUserId("User ID")
.build()Only if the user ID is in the list of members configured in the applet can the experience version of the applet be opened, otherwise when the applet is opened, the front page will say "No experience permission". 3.Open the applet by calling the interface provided by the SDK, which is as follows.
/**
* Launch the applet
*
* @param context context
* @param startAppletDecryptRequest request body
*/
fun startApplet(context: Context, startAppletDecryptRequest:
StartAppletDecryptRequest)`The structure of StartAppletDecryptRequest is as follows.
/**
* :: Launch applet request entity class
*
* @param info Applet encryption information
*/
data class StartAppletDecryptRequest(val info: String)The info field of StartAppletDecryptRequest represents the encrypted information of the applet and corresponds to the info field in the QR code of the applet experience.So when you open the applet experience, the info field of StartAppletDecryptRequest should be passed to the value corresponding to the info field in the applet experience QR code. As an example, here is the content of the experiential version of the applet QR code.
https://finchat-mop.finogeeks.club/mop/scattered-page/#/sdktip?type=scanOpen&info=SFODj9IW1ENO8OA0El8P79aMuxB1DJvfKenZd7hrnemVCNcJ+Uj9PzkRkf/Pu5nMz0cGjj0Ne4fcchBRCmJO+As0XFqMrOclsqrXaogsaUPq2jJKCCao03vI8rkHilrWxSDdzopz1ifJCgFC9d6v29m9jU29wTxlHsQUtKsk/wz0BROa+aDGWh0rKvUEPgo8mB+40/zZFNsRZ0PjsQsi7GdLg8p4igKyRYtRgOxUq37wgDU4Ymn/yeXvOv7KrzUT&codeType=trialThe value of the info field should then be
SFODj9IW1ENO8OA0El8P79aMuxB1DJvfKenZd7hrnemVCNcJ+Uj9PzkRkf/Pu5nMz0cGjj0
Ne4fcchBRCmJO+
As0XFqMrOclsqrXaogsaUPq2jJKCCao03vI8rkHilrWxSDdzopz1ifJCgFC9d6v29m9jU29
wTxlHsQUtKsk/wz0BROa+aDGWh0rKvUEPgo8mB+40/
zZFNsRZ0PjsQsi7GdLg8p4igKyRYtRgOxUq37wgDU4Ymn/yeXvOv7KrzUT2.35 How to implement third party login in an applet?
2.35.1 Integration of PhizClip Applet SDK (Vantaa Applet SDK)
Developers first need to integrate PhizClip applet SDK, please refer to PhizClip applet open platform Android integration documentation, the open platform has a detailed Android integration documentation, here is not repeated The Open Platform has detailed documentation on Android integration, so I won't go over it here.
2.35.2 Customising the applet interface to enable authorised
logins In order for the applet to get APP data other than the applet, you need to register the applet custom interface, please refer to PhizClip Applet Open Platform - Custom Applet Interface.
Note
The parameters in this example are left to the developer's discretion in actual development, and this example is for demonstration purposes only.
- Customised authorised login login interface
As this example needs to display the Authorisation Dialog when authorising login, we need to get an instance of the Activity, so we need the Api to be registered in the applet process so that we can easily get an instance of the Activity to display the applet.
public class LoginApi extends AbsApi {
// Definition code omitted
private void showAuthDialog(ICallback iCallback) {
new AlertDialog.Builder(activity)
.setTitle("Authorized Login")
.setMessage("Is this applet authorized to get user
information?")
.setCancelable(false)
.setPositiveButton("OK", (dialog, which) ->
authLoginOnMainProcess(iCallback))
.setNegativeButton("Cancel", (dialog, which) ->
iCallback.onFail())
.show();
}
/**
* Since user information is generally only stored in the main
process, it cannot be fetched by direct calls in the applet process
* So use the callInMainProcess method to call across the
process, get the information in the main process and then pass it back
to the applet process
*/
private void authLoginOnMainProcess(ICallback iCallback) {
// Cross-process call code omitted
}
}Cross-process api calls can be found in the documentation: applet process calls main processRegister custom api in applet process
if (FinAppClient.INSTANCE.isFinAppProcess(this)) {
// Applet process
initPhizClipOnAppletProcess();
} else {
// Main process initialization code omitted
}/**
* :: Register the applet to the applet process
*/
private void initPhizClipOnAppletProcess() {
FinAppProcessClient.INSTANCE.setCallback(new FinAppProcessClient.Callback() {
@Override
public List<IApi> getRegisterExtensionApis(@NotNull Activity activity) {
List< IApi> extensionApis = new ArrayList<>();
extensionApis.add(new LoginApi(activity));
return extensionApis;
}
@Override
public List<IApi> getRegisterExtensionWebApis(@NotNull
Activity activity) {
return null;
}
});
}At this point, the entire process of obtaining a user token from the APP via a custom Api is complete.
Note
If the product requirements do not require the display of a user authorisation prompt Dialog, it is recommended that a custom Api be registered with the main process, thus eliminating the need for the above cross-process call.
2.35.3 Customizing the applet interface to enable access to user
information
The parameters in this example will be developed by the developer in practice, and this example is for demonstration purposes only. Custom getUserProfile interface
public class ProfileApi extends AbsApi {
// Definition code omitted
/**
* In this example the ProfileApi is registered directly in the
extension api of the main process
* So the api is executed in the main process and can fetch data
directly
*/
private void getUserProfile(JSONObject jsonObject, ICallback
iCallback) {
// The process of obtaining user information is omitted
}
}Register the api in the main process
FinCallback< Object> initCallback = new FinCallback< Object>() {
@Override
public void onSuccess(Object result) {
// Register the extended Api, the Api registered here will be
executed in the main process
FinAppClient.INSTANCE
.getExtensionApiManager()
.registerApi(new ProfileApi());
}
@Override
public void onError(int code, String error) {
}
@Override
public void onProgress(int status, String error) {
}
};
FinAppClient.INSTANCE.init(this, finAppConfig, initCallback);At this point, the entire process of the applet obtaining user information from the APP via a custom Api is complete.
2.35.4 Customizing the applet interface to check if the user token
has expired
The parameters in this example will be developed by the developer in practice, and this example is for demonstration purposes only. Custom checkSession interface for checking user token
public class AppletSessionApi extends AbsApi {
// Definition code omitted
private void checkSession(JSONObject jsonObject, ICallback
iCallback) {
// Check procedure code omitted
}
}Register the api in the main process
FinCallback< Object> initCallback = new FinCallback< Object>() {
@Override
public void onSuccess(Object result) {
// Register the extended Api, the Api registered here will
be executed in the main process
FinAppClient.INSTANCE
.getExtensionApiManager()
.registerApi(new ProfileApi());
FinAppClient.INSTANCE
.getExtensionApiManager()
.registerApi(new AppletSessionApi());
}
@Override
public void onError(int code, String error) {
}
@Override
public void onProgress(int status, String error) {
}
};
FinAppClient.INSTANCE.init(this, finAppConfig, initCallback);At this point, the entire process of checking the user token from the APP via the custom Api is complete.
2.36 Is WebRTC supported?
Support.
2.36.1 Using WebRTC in an applet-loaded H5
If you are using WebRTC directly in an H5 loaded by an applet, please refer to WebRTC FAQ
2.36.2 Using WebRTC in applets
If you are using WebRTC in an applet, you need to integrate 2.35.0- alpha20211023v01 and above SDK.the specific instructions are as follows.
2.36.2.1 PhizClip Android SDK version with WebRTC support
- Core SDK: 2.35.0-alpha20211023v01
- Extended SDK: 2.35.0-alpha20211023v01
2.36.2.2 API documentation
2.36.3 What libraries are relied upon?
- google-webrtc:1.0.32006
2.36.4 Incremental App volume after SDK integration
- original size of google-webrtc library.
armeabi-v7a : 4.4 MB(.so library) + 0.9MB(jar file) = 5.3MB
arm64-v8a: 7.1MB(.so library) + 0.9MB(jar file) = 8MB- Up to 6.2MB increase in size after App integration with SDK
2.37 Whether to support offline applets and use local applets to
improve first load speed From version 2.35.1 onwards, sdk supports specifying the path to the local base library and applet zip when opening the applet, at which point the applet will be opened directly using the local code package to improve loading speed. Subsequent applets still get updates from the backend normally Interface definitions
/**
* Launch the applet
*
* @param context context
* @param apiServer Server address of the application marketplace
where the applet is hosted
* @param appId applet id
* @param startParams Parameters to be carried when starting the
applet
* @param offlineLibraryPath The offline base library path
* @param offlineAppletPath Path to the local applet package
*/
fun startApplet(context: Context, apiServer: String, appId: String,
startParams: FinAppInfo.StartParams? = null, offlineLibraryPath:
String, offlineAppletPath: String)Example of a call
FinAppClient.appletApiManager.startApplet(this,
"https://api.PhizClip.com",
"617bb42f530fb30001509b27", null,
"$filesDir/framework-2.11.4-alpha20211101v01.zip",
"$filesDir/Subpackage Jump Test-1.1.1.zip")2.38 Do applets support custom menus?
A:** Support.** By implementing proxy method and overriding the onNavigationBarMoreButtonClicked() ' method to display the custom menu. 1.Pass in the IAppletProcessHandler instance by calling the IAppletProcessApiManager's setAppletProcessHandler(appletProcessHandler: IAppletProcessHandler) method, and implement the display of the custom menu in the onNavigationBarMoreButtonClicked()` method to implement the display of a custom menu, as follows.
FinAppProcessClient.INSTANCE.getAppletProcessApiManager().
setAppletProcessHandler(new IAppletProcessHandler() {
@Override
public boolean onNavigationBarMoreButtonClicked(@NonNull Context
context, @NonNull String appId) {
// Show custom menu
................................................
................................................
return true; // return true means that the "more" button click
event is handled by itself, blocking the default menu display logic.
}
});Note
- The FinAppProcessClient class needs to be used in the applet process. Please use the
FinAppClient.INSTANCE.isFinAppProcess()method to determine if you are in an applet process - The IAppletProcessHandler interface method is executed in the applet process.
2.Use the methods provided by the MoreMenuHelper class to implement the SDK default menu items. The method is defined as follows.
/**
* Triggers a forwarding action, consistent with the SDK default menu
"forward" behaviour, and requires forwarding logic to be handled in the
proxy method shareAppMessage()
*/
fun invokeForwardMenuAction(context: Context)
/**
* Feedback and Casting
*/
fun goToFeedbackPage(context: Context)
/**
* Open the About page
*/
fun goToAboutPage(context: Context)
/**
* Open the settings page
*/
fun goToSettingPage(context: Context)
/**
* Turn on or off applet debugging (vConsole)
*
* @param enableAppletDebug true on, false off
*/
fun setEnableAppletDebug(context: Context, enableAppletDebug: Boolean)
/**
* :: Whether applet debugging (vConsole) is turned on or off
*/
fun isEnableAppletDebug(context: Context): Boolean
/**
* Get menu data of type [MoreMenuType.ON_MINI_PROGRAM]
*
* @param callback Please refer to the proxy method
onRegisteredMoreMenuItemClicked() for the description of the parameter
field.
*/
fun getMiniProgramTypeMenuData(
context: Context,
menuId: String?
callback: (appId: String, path: String, menuItemId: String,
appInfo: String?, bitmap: Bitmap?) -> Unit
)
/**
* :: Check if the applet implements custom menu functionality
* where the onShareAppMessage event is affected by whether the applet
has called the showShareMenu/hideShareMenu API
* If this method is called after the applet has called showShareMenu,
the value of this event is true, regardless of whether the applet
implements the onShareAppMessage event.
* If this method is called after the applet has called hideShareMenu,
the value of the event is false, regardless of whether the applet
implements the onShareAppMessage event.
*
* @param callback result JSONArray element for {"eventName": "applet
event name", "menuId": "menu id", "value": "whether the event is
implemented"}
*/
fun checkMenus(
activity: FinAppHomeActivity,
pageWebViewId: Int?
menuIds: List<String>,
callback: (result: JSONArray) -> Unit
)Note
The MoreMenuHelper class needs to be used in the applet process.
Example.
public class App extends Application {
private final Handler handler = new Handler();
private static final String CUSTOM_MENU_ID = "customMenu";
@Override
public void onCreate() {
super.onCreate();
if (! FinAppClient.INSTANCE.isFinAppProcess(this)) {
initPhizClipOnMainProcess(); // main process
} else {
initPhizClipOnAppletProcess(); // applet process
}
}
private void initPhizClipOnMainProcess() {
// Initial configuration...
FinCallback< Object> callback = new FinCallback< Object>() {
@Override
public void onSuccess(Object result) { // SDK initialization
successful
setAppletHandler();
}
@Override
public void onError(int code, String error) { // SDK
initialization failed
Toast.makeText(App2.this, "SDK initialization failed",
Toast.LENGTH_SHORT).show();
}
@Override
public void onProgress(int status, String error) {
}
};
// Initialize PhizClipSDK
FinAppClient.INSTANCE.init(this, config, callback);
}
private void setAppletHandler() {
FinAppClient.INSTANCE.getAppletApiManager().
setAppletHandler(new IAppletHandler() {
/**
* Forwarding applets
*
* @param appInfo applet information, a string of json
containing information such as applet id, applet name, applet icon,
user id, and the content of the data forwarded.
* @param bitmap The applet cover image.If the
[appInfo].params.imageUrl field is a link address of http, https, then
the applet cover image
* Just take the image corresponding to
[appInfo].params.imageUrl, otherwise the cover image of the applet is
taken as [bitmap].
* @param callback Callback for forwarding applet results.
*
* For methodological instructions, please refer to:
/runtime-sdk/android/android-issue.html#_2-9-%E6%80%8E%E4%B9%88%E5%88%86%E4%BA%AB%E5%
B0%8F%E7%A8%8B%E5%BA%8F%E5%88%B0%E5%BE%AE%E4%BF%A1%E7%AD%89%E6%94%AF%E6
%8C%81%E5%B0%8F%E7%A8%8B%E5%BA%8F%E7%9A%84%E5%B9%B3%E5%8F% B0
*/
@Override
public void shareAppMessage(@NotNull String appInfo,
@Nullable Bitmap bitmap, @NotNull IAppletCallback callback) {
handler.post(new Runnable() {
@Override
public void run() {
// Retweet/share...
callback.onSuccess(null);
}
});
}
});
}
/**
* Set the proxy method to be executed in the applet process
*/
private void initPhizClipOnAppletProcess() {
FinAppProcessClient.INSTANCE.getAppletProcessApiManager().
setAppletProcessHandler(new IAppletProcessHandler() {
/**
* The "More" button in the applet navigation bar is
clicked
*
* @param appId applet ID
* @return returns true to indicate that the button click
event is handled by itself and no default action (popup menu) needs to
be performed.A return of false means that the default action needs to
be performed
*/
@Override
public boolean onNavigationBarMoreButtonClicked(@NotNull
Context context, @NotNull String appId) {
// Note: Here is the applet process
// For sharing configurations please refer to.
//
/develop/api/custom-menu.html#_2-
2-%E5%88%86%E4%BA%AB%E9%85%8D%E7%BD%AE
ArrayList< String> menuIds = new ArrayList<>();
menuIds.add("WXShareAPPFriends"); // Menu configuration
information is provided in the onShareAppMessage method of the applet
menuIds.add("WXShareAPPMoments"); // Menu configuration
information is provided in the onShareAppMessage method of the applet
menuIds.add(CUSTOM_MENU_ID); // Menu configuration
information is provided in the onCustomMenuButtonHandler method of the
applet
MoreMenuHelper.checkMenus(context, menuIds, new
Function1< JSONArray, Unit>() {
@Override
public Unit invoke(JSONArray result) {
// Note: Here is the applet process
boolean forwardMenuEnable = false; // whether the
forward menu is available
boolean customMenuEnable = false; // whether the
custom menu is available
// Iterate through to get the status of the
buttons available
for (int i = 0; i < result.length(); i++) {
JSONObject jsonObject = (JSONObject) result.
opt(i);
if (jsonObject ! = null) {
String eventName = jsonObject.
optString("eventName");
if(eventName.
equals("onShareAppMessage")) { // menuId is WXShareAPPFriends or
WXShareAPPMoments
boolean value = jsonObject.
optBoolean("value");
if (value) {
forwardMenuEnable = true;
}
}
if(eventName.
equals("onCustomMenuButtonHandler")) { // menuId is customMenu
boolean value = jsonObject.
optBoolean("value");
if (value) {
customMenuEnable = true;
}
}
}
}
showMenuDialog(context, forwardMenuEnable,
customMenuEnable);
return null;
}
});
return true;
}
});
}
private void showMenuDialog(Context context, boolean
forwardMenuEnable, boolean customMenuEnable) {
String enableAppletDebug;
if (MoreMenuHelper.isEnableAppletDebug(context)) {
enableAppletDebug = "Turn off debugging";
} else {
enableAppletDebug = "Turn on debugging";
}
new MenuDialog(context)
// Set the state of the menu buttons according to the
method parameters, omitted here...
.setListener(new BottomSheetListener() {
/**
* Menu button click events
*/
@Override
public void onSheetItemSelected(MenuItem item) {
int itemId = item.getItemId();
if (itemId == R.id.about) {
// About page
MoreMenuHelper.goToAboutPage(context);
} else if (itemId == R.id.setting) {
// Setup page
MoreMenuHelper.goToSettingPage(context);
} else if (itemId == R.id.feedback) {
/ / Feedback and complaints
MoreMenuHelper.goToFeedbackPage(context);
} else if (itemId == R.id.forward) {
// Triggers a forwarding action, consistent
with the SDK default menu "forward" behaviour, and requires forwarding
logic to be handled within the proxy method shareAppMessage()
//
/runtime-sdk/android/android-issue.html#_2-9-%E6%80%8E%E4%B9%88%E5%88%86%E4%BA%AB%E5%B0%8F%
E7%A8%8B%E5%BA%8F%E5%88%B0%E5%BE%AE%E4%BF%A1%E7%AD%89%E6%94%AF%E6%8C%81
%E5%B0%8F%E7%A8%8B%E5%BA%8F%E7%9A%84%E5%B9%B3%E5%8F%B0
MoreMenuHelper.
invokeForwardMenuAction(context);
} else if (itemId == R.id.customMenu) { //
This menu requires applet information
// Get the menu data of type
[MoreMenuType.ON_MINI_PROGRAM]
// Please refer to the proxy method
onRegisteredMoreMenuItemClicked() for a description of the parameter
fields:
//
/runtime-sdk/android/android-issue.html#_2-10-%E5%A6%82%E4%BD%95%E5%BE%80-%E6%9B%B4%E5%A4%9A
-%E8%8F%9C%E5%8D%95%E4%B8%AD%E6%B3%A8%E5%85%A5%E8%87%AA%E5%B7%B1%E7%9A%
84%E8%8F%9C%E5%8D%95%E9%A1%B9
MoreMenuHelper.
getMiniProgramTypeMenuData(context, CUSTOM_MENU_ID, new Function5<
String, String, String, String, Bitmap, Unit>() {
@Override
public Unit invoke(String appId, String
path, String menuItemId, String appInfo, Bitmap bitmap) {
// Note: Here is the applet process
// customMenu menu business logic...
return null;
}
});
} else {
// Turn applet debugging (vConsole) on or off
MoreMenuHelper.
setEnableAppletDebug(context, ! MoreMenuHelper.
isEnableAppletDebug(context));
}
}
})
.show();
}
}2.39 Can applets be run in a single task?
A:** Yes.** The SDK allows you to set the applet to run as a single task, i.e.the applet and the host applet are displayed in the same task in the system's recent tasks list.The setting method is as follows. Set the value of the isSingleTask field of the IFinAppletRequest object to true when the applet interface is called IFinAppletRequest.
/**
* Identifies if the applet is opened via a single task stack
*/
internal var isSingleTask: Boolean = false
/**
* Set whether to open the applet via the single task stack
*/
fun setSingleTask(isSingleTask: Boolean): IFinAppletRequest {
this.isSingleTask = isSingleTask
return this
}Example.
FinAppClient.INSTANCE.getAppletApiManager().startApplet(this,
IFinAppletRequest.Companion.fromAppId("applet ID").
setSingleTask(true), null);3.Commissioning aspects
3.1 What tools are used to debug applets when developing them?
A: The Android applet SDK uses Tencent's TBS browsing service (X5 kernel) and the debugging tool is TBS Studio, which can debug applets in the same way as web pages in Chrome browser.
Note
As of 2.33.3, the SDK has replaced the X5 kernel with the system webview.
3.2 Why is TBS Studio unable to enable debugging and keeps indicating that the current target app cannot be debugged by TBS, please check and do the following Make sure that the current target app's webview is based on TBS development Make sure that the previous steps are executed successfully?
A: This is usually because the device is a 64-bit processor device and the application is not running in 32-bit mode.43903 versions of the TBS SDK do not provide 64-bit so dynamic libraries, so if the device is still running in 64-bit mode on a 64-bit processor device, the TBS SDK will fail during initialisation and the X5 kernel will not be successfully enabled. To enable the X5 kernel properly for devices with 64-bit processors, you need to set the following in the defaultConfig of the build.gradle file of the current Android project to make the application run in 32-bit mode.
ndk {
// Set the supported SO library architecture
abiFilters "armeabi", 'armeabi-v7a'
}If the compile error is reported after configuration, this can be resolved by adding the following configuration to the project's gradle.properties file
Android.useDeprecatedNdk=true.3.3 Why does the applet keep getting a white screen when loading pages on some lower versions of systems, but not on higher versions?
A: This generally occurs because the browser version on lower versions of the system is also lower and the browser does not recognise the new syntax features properly.For example, some browser versions were released before ES6 was finalised and released.If the new ES6 features are used when coding, and the browser is not up to date with the version, then when opening a web page in the browser, the browser will not recognise the ES6 code and an error will occur. For this type of problem, it is generally recommended that
- when coding, use syntax that is as compatible as possible.
- If you inevitably need to use some new syntax features, try introducing syntax conversion tools such as babel-polyfill that automatically convert the new syntax to a lower version so that you can use the new syntax features without having to think about environment compatibility.
3.4 How to enable vConsole debugging applets?
If you need to debug your applet using vConsole, there are currently several ways to enable Debug mode.
setEnableAppletDebugin the SDK initialization configuration is true to enable all applets to display vconsole.please keep this configuration to false when the app is live.(When set to true, vConsole cannot be turned off via api within the applet).- When
setEnableAppletDebugin the SDK initialization configuration is false, each applet can be enabled in Debug mode independently.Non-online versions (e.g.Experience, Audit, Development, Preview) can enable Debug mode via [Turn on Debug] in the More menu. - When
setEnableAppletDebugin the SDK initialization configuration is false, Debug mode is enabled independently by calling api(pz.setEnableDebug) through the applet.