XmagicApi.java, utilized for initializing the SDK, updating beauty metric values, invoking animated effects, amongst other features.
API | Description |
VERSION | The SDK version number can be retrieved via XmagicApi.VERSION (added in V3.5.0). |
Set the path of the '.so' Library. If the '.so' Library is built into the apk package, this interface is not needed. | |
Transfer the content located within the directories Light3DPlugin, LightCore, LightHandPlugin, LightBodyPlugin, LightSegmentPlugin under application assets to your designated directory. | |
Copy the AI model files downloaded by the client to the corresponding folders. | |
Get the device level. |
API | Description |
constructor. | |
Methods for rendering data with the SDK, used for processing images or video streams. | |
Set effects such as beauty, aesthetic shape, filters, makeup, stickers, and segmentation, and can be invoked in any thread. | |
Set the SDK's log level, which defaults to Log.WARN. During development and debugging, it can be set to Log.DEBUG if necessary. For official release, make sure to set it to Log.WARN or Log.ERROR to avoid performance issues caused by excessive logging.Invoke after new XmagicApi(). | |
Invoke this method to enable the high-performance pattern. Upon the activation of the high-performance pattern, the system CPU/GPU resources occupied by beauty filters are minimized, thereby reducing heat generation and latency issues in the mobile device. It is particularly suitable for prolonged use on low-end devices. Invoke after new XmagicApi(). | |
Enable or disable specific capability. | |
Set the input data type; there are two types: camera data and image data. The default is camera data stream. | |
Configure the callback for face, gesture, and body detection statuses. | |
Toggle mute when using motion effect material. Parameter: true means mute, false means not mute. | |
Pause the sound playback in the special effects, can be bound to the Activity onPause lifecycle. | |
Resume the sound playback in the special effects, can be bound to the Activity onResume lifecycle. | |
Terminate `xmagic`, which necessitates its invocation within the `GL` thread. | |
Set the image orientation so that AI can recognize faces from different directions. If set, the direction provided by sensorChanged will be ignored. | |
Use the system sensor to judge the current phone's rotation angle, so that the AI can recognize faces in different orientations. | |
Pass the path of a dynamic effect material to the SDK, and detect whether the current device fully supports this dynamic effect. | |
Determine whether the current device supports refinement (OpenGL3.0). | |
Retrieve the screen on the current texture | |
Setting up callback functions for animated hint text, designated to display hints on the frontend page. | |
Set up synchronized video frame processing. |
new XmagicApi(). data/data/package name/files/xmagic_libs, the so will be loaded from this directory.static boolean setLibPathAndLoad(String path)
static int addAiModeFilesFromAssets(Context context, String resDir)
static int addAiModeFiles(String inputResDir, String resDir)
getDeviceLevel method before new XmagicApi, you must include the benchmark folder from the SDK's assets directory into your APK's assets. If you call getDeviceLevel after new XmagicApi, there is no need to include it.static DeviceLevel getDevicLevel(Context context)public enum DeviceLevel {DEVICE_LEVEL_VERY_LOW(1),DEVICE_LEVEL_LOW(2),DEVICE_LEVEL_MIDDLE(3),DEVICE_LEVEL_MIDDLE_HIGH(4),DEVICE_LEVEL_HIGH(5);private final int value;DeviceLevel(int value) {this.value = value;}public int getValue() {return value;}}
public XmagicApi(Context context, EffectMode effectMode, String resDir)public XmagicApi(Context context, EffectMode effectMode, String resDir,OnXmagicPropertyErrorListener xmagicPropertyErrorListener)@Deprecatedpublic XmagicApi(Context context, String resDir)@Deprecatedpublic XmagicApi(Context context, String resDir,OnXmagicPropertyErrorListener xmagicPropertyErrorListener)public interface OnXmagicPropertyErrorListener {void onXmagicPropertyError(String errorMsg, int code);}public enum EffectMode{NORMAL(0),PRO(1);private final int value;EffectMode(int value) {this.value = value;}public int getValue() {return value;}}
Parameter | Type | Meaning |
context | Context | context. |
effectMode | EffectMode | This parameter was added in V3.9.0. It is used to specify performance and effect modes, with possible values being NORMAL and PRO. NORMAL can meet most scenarios with better performance but fewer features. Please choose according to your needs. |
resDir | String | SDK model resource file directory. Before using the SDK, you need to designate a directory to store the SDK's model resource files. It is recommended to use the app's private directory: resDir = context.getFilesDir().getAbsolutePath() + "/xmagic" Additionally, before instantiating XmagicApi, please first invoke the static method addAiModeFilesFromAssets or addAiModeFiles of XmagicApi to copy the model resource files to resDir. |
xmagicPropertyErrorListener | OnXmagicPropertyErrorListener | Error Callback Interface. During the use of the SDK, this interface will callback some internal error information. Generally used during development and debugging. |
Error code | Meaning |
-1 | Unknown error. |
-100 | 3D engine resource initialization failed. |
-200 | GAN materials are not supported. |
-300 | This device does not support this material component. |
-400 | The template JSON content is empty. |
-500 | The SDK version is too low. |
-600 | Splitting is not supported. |
-700 | OpenGL is not supported. |
-800 | Scripting is not supported. |
5,000 | The resolution of the split background image exceeds 2160x3840. |
5001 | Insufficient memory required to segment the background image. |
5002 | Failed to parse the video segmentation of the background. |
5003 | Background video segment exceeds 200 seconds. |
5004 | Background video segment format unsupported. |
5005 | Background image segment possesses rotation angle |
// Render the textureint process(int srcTextureId, int srcTextureWidth, int srcTextureHeight)// Render the bitmapBitmap process(Bitmap bitmap, boolean needReset)
Parameter | Meaning |
int srcTextureId | The texture that needs to be rendered. The type is: OpenGL 2D texture format, and the pixel format is RGBA. |
int srcTextureWidth | Width of the texture that needs to be rendered. |
int srcTextureHeight | Height of the texture that needs to be rendered. |
Bitmap bitmap | The recommended maximum size is 2160 x 4096. Larger images have poor face recognition results or cannot get faces recognized and are likely to cause OOM problems. Shrink such images first before passing them in. |
boolean needReset | In the following scenarios, set needReset to true: Processing an image for the first time, or switching images. First time using partition. Initial use of animated effects. First-time usage of makeup. |
void setEffect(String effectName, int effectValue, String resourcePath, Map<String, String> extraInfo)
Log.WARN. During development and debugging, it can be set to Log.DEBUG if necessary. For official release, make sure to set it to Log.WARN or Log.ERROR to avoid performance issues caused by excessive logging.ITELogger is set, the SDK's internal logs will be redirected to the user.public void setXmagicLogLevel(int level);public void setXmagicLogLevel(int level, final ITELogger logger);public interface ITELogger{void log(int severity, String tag, String msg);void log(int severity, String tag, String msg, Throwable throwable);}
void enableHighPerformance()
void setFeatureEnableDisable(String featureName, boolean enable)
Parameter | Meaning |
String featureName | Name of the atomic capability Valid values: XmagicConstant.FeatureName.SEGMENTATION_SKIN Skin Segmentation Capability, after enabling, can make the skin smoothing and whitening areas more accurate.XmagicConstant.FeatureName.SEGMENTATION_FACE_BLOCK Face Occlusion Detection Capability, after enabling, can avoid makeup being applied to occluded areas.XmagicConstant.FeatureName.WHITEN_ONLY_SKIN_AREA Whitening only works on skinXmagicConstant.FeatureName.SMART_BEAUTY Intelligent Beauty (reduces beauty and makeup effects for men and babies)XmagicConstant.FeatureName.ANIMOJI_52_EXPRESSION Face Expression CapabilityXmagicConstant.FeatureName.BODY_3D_POINT Body Point CapabilityXmagicConstant.FeatureName.HAND_DETECT Gesture Detection Capability |
boolean enable | true indicates to enable this capability, false indicates to disable this capability |
SEGMENTATION_SKIN and SEGMENTATION_FACE_BLOCK. The SDK will enable these two capabilities by default based on the value of getDeviceLevel. If you need to enable them manually, it is recommended to enable SEGMENTATION_SKIN when level >= 4, and enable SEGMENTATION_FACE_BLOCK when level >= 5.void setXmagicStreamType(int type)
Parameter | Meaning |
int type | Data source type, there are two options: XmagicApi.PROCESS_TYPE_CAMERA_STREAM: camera data source.XmagicApi.PROCESS_TYPE_PICTURE_DATA: Image data source. |
public void setAIDataListener(final XmagicAIDataListener aiDataListener);public interface OnAIDataListener {void onFaceDataUpdated(List<TEFaceData> faceDataList);void onBodyDataUpdated(List<TEBodyData> bodyDataList);void onAIDataUpdated(String jsonString);@Deprecatedvoid onHandDataUpdated(List<TEHandData> handDataList);}
onAIDataUpdated callback.public class TEFaceData {public float[] points;public TEFaceData() {}public TEFaceData(float[] points) {this.points = points;}}
onAIDataUpdated callback.
face_info, please check Facial Keypoint Detection.hand_info, please check Gesture Recognition.body_3d_info, please check Body Keypoints Android and Body Keypoints iOS.{"face_info": [{"expression_weights": [0.001172, 0, 0.029249, ... , 0.060041, 0],"face_256_point": [211.844238, 673.247192, ... , 339.247925, 654.792603],"face_256_visible": [0.163925, 0.14921, ... , 0.99887, 0.99887],"face_3d_info": {"pitch": -3.860844850540161,"pitch_fixed": 2.1123428344726562,"roll": -12.797032356262207,"roll_fixed": 1.3187808990478516,"transform": [[0.8919625878334045, 0.2843534052371979, 0.3514907658100128, 0],[-0.17628398537635803, 0.9346542954444885, -0.3087802827358246, 0],[-0.41632509231567383, 0.21345829963684082, 0.88380366563797, 0],[-0.020958196371793747, -0.04502145200967789, -0.6078543663024902, 1]],"yaw": 24.824481964111328,"yaw_fixed": 25.02082061767578},"left_eye_high_vis_ratio": 0,"left_eyebrow_high_vis_ratio": 0,"mouth_high_vis_ratio": 1,"out_of_screen": false,"right_eye_high_vis_ratio": 1,"right_eyebrow_high_vis_ratio": 0.821429,"trace_id": 21}],"hand_info": {"gesture": "PAPER","hand_point_2d": [180.71888732910156, 569.2958984375, ... , 353.8714294433594, 836.246826171875]},"body_3d_info": {"imageHeight": 652,"imageWidth": 320,"items": [{"index": 1,"pose": [0.049122653901576996, ... , 0],"position_x": [190.47494506835938, 235.23098754882812, ... , 4.948424339294434, 173.59298706054688],"position_y": [777.2109375, 836.488037109375, ... , 161.19752502441406, 405.83905029296875],"position_z": [0, 0, ... , 0, 0],"rotation": [{"data": [0.9944382905960083, -0.09695644676685333, -0.0411277711391449, 0.000708006089553237]},......{"data": [0.9907779693603516, 0.13549542427062988, 0, 0]}, {"data": [1, 0, 0, 0]}]}]}}
void onPause()
void onResume()
// Refer to the sample code in `TECameraBaseActivity.java`public void onGLContextDestroy() {if (this.mXMagicApi != null) {this.mXMagicApi.onDestroy();this.mXMagicApi = null;}}
void setImageOrientation(TEImageOrientation orientation)public enum TEImageOrientation {ROTATION_0,ROTATION_90,ROTATION_180,ROTATION_270}
sensorChanged will be ignored. Example directions are as follows:
void sensorChanged(android.hardware.SensorEvent event, android.hardware.Sensor accelerometer)
setImageOrientation, the direction provided by sensorChanged will be ignored.public class MyActivity implements SensorEventListener {private SensorManager mSensorManager;private Sensor mAccelerometer;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);}@Overrideprotected void onResume() {super.onResume();mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);}@Overrideprotected void onPause() {super.onPause();mSensorManager.unregisterListener(this);}@Overridepublic void onSensorChanged(SensorEvent event) {if (mXMagicApi != null) {mXMagicApi.sensorChanged(event, mAccelerometer);}}}
boolean isDeviceSupport(String motionResPath)
boolean isSupportBeauty()
void exportCurrentTexture(ExportTextureCallback callback)public interface ExportTextureCallback {void onCallback(Bitmap bitmap);}
void setTipsListener(XmagicApi.XmagicTipsListener effectTipsListener)
public interface XmagicTipsListener {/*** Display tips.* @param tips The returned prompt text information.* @param tipsIcon The file path of the tips icon. You can parse the corresponding image based on the file path. If it's a pag file, you need to use pagView to display it.* Note: tipsIcon may be empty, return null if not configured in the material.* @param type Tips category, 0 means both tips and tipsIcon have values, 1 means it is a pag material and only tipsIcon has values.* @param duration Tips display duration, in milliseconds.*/void tipsNeedShow(String tips, String tipsIcon, int type, int duration);/*** Hide tips.* @param tips The returned prompt text information.* @param tipsIcon The file path of the tips icon. You can parse the corresponding image based on the file path. If it's a pag file, you need to use pagView to display it.* Note: tipsIcon may be empty, return null if not configured in the material.* @param type Tips category, 0 means both tips and tipsIcon have values, 1 means it is a pag material and only tipsIcon has values.*/void tipsNeedHide(String tips, String tipsIcon, int type);}
public void tipsNeedShow(final String tips, String tipsIcon, int type, int duration) {final int tipsType = type;final String tipsIconPath = tipsIcon;mMainThreadHandler.post(new Runnable() {@Overridepublic void run() {if (tipsType == 0) {if (!TextUtils.isEmpty(tipsIconPath) && !mImageTipsIsShow) {mTipsImageView.setVisibility(View.VISIBLE);Bitmap bitmap = BitmapUtils.decodeSampleBitmap(AEModule.getContext(), tipsIconPath, Integer.MAX_VALUE, Integer.MAX_VALUE);mTipsImageView.setImageBitmap(bitmap);mImageTipsIsShow = true;} else {mTipsImageView.setVisibility(View.GONE);}mTipsTextView.setText(tips);} else {pagFile = PAGFile.Load(tipsIconPath);tipsPAGView.post(new Runnable() {@Overridepublic void run() {if (pagFile != null) {tipsPAGView.setRepeatCount(-1);tipsPAGView.setComposition(pagFile);tipsPAGView.setProgress(0);tipsPAGView.play();tipsPAGView.setVisibility(View.VISIBLE);}}});}}});}public void tipsNeedHide(String tips, String tipsIcon, int type) {final int tipsType = type;final String tipsIconPath = tipsIcon;mMainThreadHandler.post(new Runnable() {@Overridepublic void run() {if (tipsType == 0) {mTipsContainer.setVisibility(View.GONE);mImageTipsIsShow = false;} else {tipsPAGView.post(new Runnable() {@Overridepublic void run() {tipsPAGView.stop();tipsPAGView.setVisibility(View.GONE);}});}}});}
syncFrameCount frames to meet specific requirements in certain scenarios. For example, before processing the first frame, calling this interface allows the SDK to process several frames synchronously, which can prevent unfiltered images from being displayed. However, this may increase the black screen duration before the first frame is rendered, so please use it as needed.void setSyncMode(boolean isSync, int syncFrameCount)
Parameter | Meaning |
isSync | Whether to process image frames synchronously. |
syncFrameCount | The number of frames to be processed synchronously. The value must be >= 0. If set to -1, it indicates an unlimited number of frames. |
Feedback