Top Related Projects
A memory leak detection library for Android.
A static analyzer for Java, C, C++, and Objective-C
Android and Java bytecode viewer
A library for performance traces from production.
A tool to help eliminate NullPointerExceptions (NPEs) in your Java code with low build-time overhead
Catch common Java mistakes as compile-time errors
Quick Overview
Matrix is an open-source APM (Application Performance Management) system developed by Tencent for mobile applications. It provides comprehensive performance monitoring and optimization tools for Android and iOS platforms, helping developers identify and resolve issues related to memory, battery, startup time, and more.
Pros
- Comprehensive performance monitoring for mobile apps
- Supports both Android and iOS platforms
- Provides detailed analysis and visualization of performance data
- Open-source and actively maintained by Tencent
Cons
- Documentation is primarily in Chinese, which may be challenging for non-Chinese speakers
- Setup and integration process can be complex for beginners
- Some features may be more tailored to the Chinese mobile app ecosystem
Code Examples
Here are a few examples of how to use Matrix in an Android application:
- Initializing Matrix:
Matrix.Builder builder = new Matrix.Builder(application);
builder.patchListener(new TestPluginListener(this))
.pluginListener(new TestPluginListener(this));
Matrix.init(builder.build());
- Adding a specific plugin (e.g., TracePlugin):
TracePlugin tracePlugin = new TracePlugin(new TraceConfig.Builder()
.enableFPS(true)
.enableEvilMethodTrace(true)
.enableAnrTrace(true)
.enableStartup(true)
.build());
builder.plugin(tracePlugin);
- Manually triggering an issue for testing:
MatrixLog.e(TAG, "manual trigger apm");
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(20000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
Getting Started
To integrate Matrix into your Android project:
- Add the Matrix dependency to your app's
build.gradle
:
dependencies {
implementation 'com.tencent.matrix:matrix-android-lib:2.0.0'
implementation 'com.tencent.matrix:matrix-android-commons:2.0.0'
}
- Initialize Matrix in your Application class:
public class YourApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Matrix.Builder builder = new Matrix.Builder(this);
builder.patchListener(new TestPluginListener(this));
Matrix.init(builder.build());
}
}
-
Add specific plugins as needed (e.g., TracePlugin, ResourceCanaryPlugin) and configure them according to your requirements.
-
Build and run your app to start collecting performance data.
Competitor Comparisons
A memory leak detection library for Android.
Pros of LeakCanary
- Focused specifically on memory leak detection in Android apps
- Easier setup and integration for Android developers
- More mature and widely adopted in the Android community
Cons of LeakCanary
- Limited to memory leak detection only
- Android-specific, not suitable for other platforms
- Less comprehensive performance monitoring compared to Matrix
Code Comparison
LeakCanary:
class ExampleApplication : Application() {
override fun onCreate() {
super.onCreate()
if (LeakCanary.isInAnalyzerProcess(this)) {
return
}
LeakCanary.install(this)
}
}
Matrix:
Matrix.Builder builder = new Matrix.Builder(application);
builder.patchListener(new TestPluginListener(this));
DynamicConfigImpl dynamicConfig = new DynamicConfigImpl();
builder.dynamicConfig(dynamicConfig);
builder.plugin(new TracePlugin(new TraceConfig.Builder()
.dynamicConfig(dynamicConfig)
.build()));
Matrix.init(builder.build());
LeakCanary focuses on simplicity for memory leak detection, while Matrix offers a more comprehensive suite of performance monitoring tools with a more complex setup. LeakCanary is ideal for Android developers primarily concerned with memory leaks, whereas Matrix provides a broader range of performance monitoring capabilities across multiple platforms.
A static analyzer for Java, C, C++, and Objective-C
Pros of Infer
- More comprehensive static analysis tool, supporting multiple languages (Java, C/C++, Objective-C)
- Advanced inter-procedural analysis capabilities
- Extensive documentation and active community support
Cons of Infer
- Steeper learning curve due to its complexity
- Potentially slower analysis for large codebases
- Requires more setup and configuration compared to Matrix
Code Comparison
Matrix (Android performance monitoring):
Matrix.Builder builder = new Matrix.Builder(context);
builder.patchListener(new TestPluginListener(this));
Matrix.init(builder.build());
Infer (Static analysis):
infer run -- javac MyFile.java
infer run -- gradle build
Key Differences
- Focus: Matrix primarily targets Android performance monitoring, while Infer is a general-purpose static analysis tool
- Language support: Matrix is Android-specific, whereas Infer supports multiple languages
- Use case: Matrix is better suited for runtime performance analysis, while Infer excels at detecting potential bugs before runtime
Conclusion
Choose Matrix for Android-specific performance monitoring and optimization. Opt for Infer when you need comprehensive static analysis across multiple languages and platforms.
Android and Java bytecode viewer
Pros of ClassyShark
- Focused specifically on Android APK analysis and reverse engineering
- Provides a user-friendly GUI for easier navigation and visualization
- Supports multiple file formats including DEX, APK, AAR, and SO files
Cons of ClassyShark
- Limited to Android platform analysis
- Less comprehensive in terms of performance monitoring and optimization
- Fewer active contributors and updates compared to Matrix
Code Comparison
ClassyShark (Java):
public class ClassySharkAndroid {
public static void main(String[] args) {
ClassesListActivity.start(context, apkPath);
}
}
Matrix (C++):
namespace matrix {
class WeChatMatrix {
public:
void Init();
void DeInit();
};
}
Key Differences
Matrix is a more comprehensive mobile performance optimization framework, while ClassyShark focuses specifically on Android APK analysis. Matrix offers a wider range of features for performance monitoring, crash reporting, and resource usage optimization across multiple platforms. ClassyShark, on the other hand, provides a more specialized tool for Android developers and security researchers to analyze and reverse engineer Android applications.
Matrix has a larger and more active community, with regular updates and contributions from Tencent. ClassyShark, while still useful, has seen fewer recent updates and contributions from the community.
A library for performance traces from production.
Pros of Profilo
- More comprehensive profiling capabilities, including CPU, memory, and I/O
- Better support for Android-specific profiling and tracing
- More active development and community support
Cons of Profilo
- Limited to Android platform, while Matrix supports both Android and iOS
- Steeper learning curve due to more complex architecture
- Requires more setup and configuration compared to Matrix
Code Comparison
Matrix (Java):
Matrix.Builder builder = new Matrix.Builder(context);
builder.pluginListener(new TestPluginListener());
Matrix.init(builder.build());
Profilo (Java):
ProfiloInitializer.initialize(context);
TraceOrchestrator.getInstance().startTracing(
TraceProvider.PROVIDER_PROFILO,
new TraceConfig.Builder().build()
);
Both libraries offer initialization methods, but Profilo's setup is more involved, reflecting its broader feature set. Matrix provides a simpler API for quick integration, while Profilo offers more granular control over tracing configurations.
A tool to help eliminate NullPointerExceptions (NPEs) in your Java code with low build-time overhead
Pros of NullAway
- Focused specifically on null pointer exceptions in Java, providing more specialized analysis
- Integrates seamlessly with the Java build process, particularly with Gradle and Error Prone
- Offers low false positive rate and minimal runtime overhead
Cons of NullAway
- Limited to Java language, while Matrix supports multiple platforms (iOS, Android, Windows)
- Narrower scope, focusing only on null pointer issues rather than broader performance and stability concerns
- Requires manual annotation of code, which can be time-consuming for large projects
Code Comparison
NullAway example:
@Nullable
public String getName() {
return name;
}
Matrix example (Android):
Matrix.with(this)
.add(new ANRPlugin())
.add(new TracePlugin())
.init();
Key Differences
NullAway is a specialized tool for preventing null pointer exceptions in Java, while Matrix is a comprehensive performance monitoring framework for multiple platforms. NullAway integrates directly into the build process, whereas Matrix requires initialization in the application code. The choice between them depends on the specific needs of the project and the platforms being targeted.
Catch common Java mistakes as compile-time errors
Pros of error-prone
- Focuses on compile-time error detection for Java, potentially catching issues earlier in the development process
- Integrates well with popular build tools like Maven and Gradle
- Extensive documentation and a large set of built-in bug patterns
Cons of error-prone
- Limited to Java language, while matrix supports multiple platforms (iOS, Android, Windows)
- Primarily targets code quality issues, whereas matrix addresses performance and stability concerns
- May require more setup and configuration compared to matrix's plug-and-play approach
Code Comparison
error-prone example (Java):
@CheckReturnValue
public static String trim(String s) {
return s.trim();
}
matrix example (C++):
#include <matrix/matrix.h>
void performanceTest() {
MatrixTracker::startTrace("PerformanceTest");
// Test code here
MatrixTracker::stopTrace();
}
While both tools aim to improve code quality, they serve different purposes. error-prone focuses on static analysis and compile-time error detection for Java, while matrix is a multi-platform APM (Application Performance Management) tool that addresses performance, stability, and resource usage issues across various platforms.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
(ä¸æçæ¬è¯·åçè¿é)
Matrix for iOS/macOS ä¸æç
Matrix for android ä¸æç
Matrix for iOS/macOS
Matrix for android
Matrix is an APM (Application Performance Manage) used in Wechat to monitor, locate and analyse performance problems. It is a plugin style, non-invasive solution and is currently available on iOS, macOS and Android.
Matrix for iOS/macOS
The monitoring scope of the current tool includes: crash, lag, and memory, which includes the following three plugins:
-
WCCrashBlockMonitorPluginï¼ Based on KSCrash framework, it features cutting-edge lag stack capture capabilities with crash capture.
-
WCMemoryStatPluginï¼ A memory monitoring tool that captures memory allocation and the callstack of an application's memory event.
-
WCFPSMonitorPluginï¼ A fps monitoring tool that captures main thread's callstack while user scrolling.
Features
WCCrashBlockMonitorPlugin
- Easy integration, no code intrusion.
- Determine whether the app is stuck by checking the running status of the Runloop, and support both the iOS and macOS platform.
- Add time-consuming stack fetching, attaching the most time-consuming main thread stack to the thread snapshot log.
WCMemoryStatPlugin
- Live recording every object's creating and the corresponding callstack of its creation, and report it when the application out-of-memory is detected.
Getting Started
Install
- Install with static framework
- Get source code of Matrix;
- Open terminal, execute
make
in thematrix/matrix-iOS
directory to compile and generate static library. After compiling, the iOS platform library is in thematrix/matrix-iOS/build_ios
directory, and the macOS platform library is in thematrix/matrix-iOS/build_macos
directory. - Link with static framework in the project:
- iOS : Use
Matrix.framework
under thematrix/matrix-iOS/build_ios
path, linkMatrix.framework
to the project as a static library; - macOS : Use
Matrix.framework
under thematrix/matrix-iOS/build_macos
path, linkMatrix.framework
to the project as a static library.
- Add
#import <Matrix/Matrix.h>
, then you can use the performance probe tool of WeChat.
Start the plugins
In the following places:
- Program
main
function; application:didFinishLaunchingWithOptions:
ofAppDelegate
;- Or other places running as earlier as possible after application launching.
Add a code similar to the following to start the plugin:
#import <Matrix/Matrix.h>
Matrix *matrix = [Matrix sharedInstance];
MatrixBuilder *curBuilder = [[MatrixBuilder alloc] init];
curBuilder.pluginListener = self; // get the related event of plugin via the callback of the pluginListener
WCCrashBlockMonitorPlugin *crashBlockPlugin = [[WCCrashBlockMonitorPlugin alloc] init];
[curBuilder addPlugin:crashBlockPlugin]; // add lag and crash monitor.
WCMemoryStatPlugin *memoryStatPlugin = [[WCMemoryStatPlugin alloc] init];
[curBuilder addPlugin:memoryStatPlugin]; // add memory monitor.
WCFPSMonitorPlugin *fpsMonitorPlugin = [[WCFPSMonitorPlugin alloc] init];
[curBuilder addPlugin:fpsMonitorPlugin]; // add fps monitor.
[matrix addMatrixBuilder:curBuilder];
[crashBlockPlugin start]; // start the lag and crash monitor.
[memoryStatPlugin start]; // start memory monitor
[fpsMonitorPlugin start]; // start fps monitor
Receive callbacks to obtain monitoring data
Set pluginListener
of the MatrixBuilder
object, implement the MatrixPluginListenerDelegate
// set delegate
MatrixBuilder *curBuilder = [[MatrixBuilder alloc] init];
curBuilder.pluginListener = <object conforms to MatrixPluginListenerDelegate>;
// MatrixPluginListenerDelegate
- (void)onInit:(id<MatrixPluginProtocol>)plugin;
- (void)onStart:(id<MatrixPluginProtocol>)plugin;
- (void)onStop:(id<MatrixPluginProtocol>)plugin;
- (void)onDestroy:(id<MatrixPluginProtocol>)plugin;
- (void)onReportIssue:(MatrixIssue *)issue;
Each plugin added to MatrixBuilder
will call back the corresponding event via pluginListener
.
Important: Get the monitoring data of the Matrix via onReportIssue:
, the data format info reference to Matrix for iOS/macOS Data Format Description
Tutorials
At this point, Matrix has been integrated into the app and is beginning to collect crash, lag, and memory data. If you still have questions, check out the example: samples/sample-iOS/MatrixDemo
.
Matrix for android
Plugins
-
APK Checker:
Analyse the APK package, give suggestions of reducing the APK's size; Compare two APK and find out the most significant increment on size
-
Resource Canary:
Detect the activity leak and bitmap duplication basing on WeakReference and Square Haha
-
Trace Canary:
FPS Monitor, Startup Performance, ANR, UI-Block / Slow Method Detection
-
SQLite Lint:
Evaluate the quality of SQLite statement automatically by using SQLite official tools
-
IO Canary:
Detect the file IO issues, including performance of file IO and closeable leak
-
Battery Canary:
App thread activities monitor (Background watch & foreground loop watch), Sonsor usage monitor (WakeLock/Alarm/Gps/Wifi/Bluetooth), Background network activities (Wifi/Mobile) monitor.
-
MemGuard
Detect heap memory overlap, use-after-free and double free issues.
Features
APK Checker
- Easy-to-use. Matrix provides a JAR tool, which is more convenient to apply to your integration systems.
- More features. In addition to APK Analyzer, Matrix find out the R redundancies, the dynamic libraries statically linked STL, unused resources, and supports custom checking rules.
- Visual Outputs. supports HTML and JSON outputs.
Resource Canary
- Separated detection and analysis. Make possible to use in automated test and in release versions (monitor only).
- Pruned Hprof. Remove the useless data in hprof and easier to upload.
- Detection of duplicate bitmap.
Trace Canary
- High performance. Dynamically modify bytecode at compile time, record function cost and call stack with little performance loss.
- Accurate call stack of ui-block. Provide informations such as call stack, function cost, execution times to solve the problem of ui-block quickly.
- Non-hack. High compatibility to Android versions.
- More features. Automatically covers multiple fluency indicators such as ui-block, startup time, activity switching, slow function detection.
- High-accuracy ANR detector. Detect ANRs accurately and give ANR trace file with high compatibility and high stability.
SQLite Lint
- Easy-to-use. Non-invasive.
- High applicability. Regardless of the amount of data, you can discover SQLite performance problems during development and testing.
- High standards. Detection algorithms based on best practices, make SQLite statements to the highest quality.
- May support multi-platform. Implementing in C++ makes it possible to support multi-platform.
IO Canary
- Easy-to-use. Non-invasive.
- More feature. Including performance of file IO and closeable leak.
- Compatible with Android P.
Battery Canary
- Easy-to-use. Use out of box (unit tests as example).
- More feature. Flexible extending with base and utils APIs.
Memory Hook
- A native memory leak detection tool for Android.
- Non-invasive. It is based on PLT-hook(iqiyi/xHook), so we do NOT need to recompile the native libraries.
- High performance. we use WeChat-Backtrace for fast unwinding which supports both aarch64 and armeabi-v7a architectures.
Pthread Hook
- A Java and native thread leak detection and native thread stack space trimming tool for Android.
- Non-invasive. It is based on PLT-hook(iqiyi/xHook), so we do NOT need to recompile the native libraries.
- It saves virtual memory overhead by trimming default stack size of native thread in half, which can reduce crashes caused by virtual memory insufficient under 32bit environment.
WVPreAllocHook
- A tool for saving virtual memory overhead caused by WebView preloading when WebView is not actually used. It's useful for reducing crashes caused by virtual memory insufficient under 32bit environment.
- Non-invasive. It is based on PLT-hook(iqiyi/xHook), so we do NOT need to recompile the native libraries.
- WebView still works after using this tool.
MemGuard
-
A tool base on GWP-Asan to detect heap memory issues.
-
Non-invasive. It is based on PLT-hook(iqiyi/xHook), so we do NOT need to recompile the native libraries.
-
It's able to apply on specific libraries that needs to be detected by RegEx.
-
It detects heap memory accessing overlap, use-after-free and double free issues.
Backtrace Component
- A fast native backtrace component designed by Matrix based on quicken unwind tables that are generated and simplified from DWARF and ARM exception handling informations. It is about 15x ~ 30x faster than libunwindstack.
Getting Started
The JCenter repository will stop service on February 1, 2022. So we uploaded Matrix(since 0.8.0) to the MavenCentral repository.
- Configure
MATRIX_VERSION
in gradle.properties.
MATRIX_VERSION=2.1.0
- Add
matrix-gradle-plugin
in your build.gradle:
dependencies {
classpath ("com.tencent.matrix:matrix-gradle-plugin:${MATRIX_VERSION}") { changing = true }
}
- Add dependencies to your app/build.gradle.
dependencies {
implementation group: "com.tencent.matrix", name: "matrix-android-lib", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-android-commons", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-trace-canary", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-resource-canary-android", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-resource-canary-common", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-io-canary", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-sqlite-lint-android-sdk", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-battery-canary", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-hooks", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-backtrace", version: MATRIX_VERSION, changing: true
}
apply plugin: 'com.tencent.matrix-plugin'
matrix {
trace {
enable = true //if you don't want to use trace canary, set false
baseMethodMapFile = "${project.buildDir}/matrix_output/Debug.methodmap"
blackListFile = "${project.projectDir}/matrixTrace/blackMethodList.txt"
}
}
- Implement
PluginListener
to receive data processed by Matrix.
public class TestPluginListener extends DefaultPluginListener {
public static final String TAG = "Matrix.TestPluginListener";
public TestPluginListener(Context context) {
super(context);
}
@Override
public void onReportIssue(Issue issue) {
super.onReportIssue(issue);
MatrixLog.e(TAG, issue.toString());
//add your code to process data
}
}
Matrix gradle plugin could work with Android Gradle Plugin 3.5.0/4.0.0/4.1.0 currently.
- Implement
DynamicConfig
to change parameters of Matrix.
public class DynamicConfigImplDemo implements IDynamicConfig {
public DynamicConfigImplDemo() {}
public boolean isFPSEnable() { return true;}
public boolean isTraceEnable() { return true; }
public boolean isMatrixEnable() { return true; }
public boolean isDumpHprof() { return false;}
@Override
public String get(String key, String defStr) {
//hook to change default values
}
@Override
public int get(String key, int defInt) {
//hook to change default values
}
@Override
public long get(String key, long defLong) {
//hook to change default values
}
@Override
public boolean get(String key, boolean defBool) {
//hook to change default values
}
@Override
public float get(String key, float defFloat) {
//hook to change default values
}
}
- Init Matrix in the
onCreate
of your application.
Matrix.Builder builder = new Matrix.Builder(application); // build matrix
builder.patchListener(new TestPluginListener(this)); // add general pluginListener
DynamicConfigImplDemo dynamicConfig = new DynamicConfigImplDemo(); // dynamic config
// init plugin
IOCanaryPlugin ioCanaryPlugin = new IOCanaryPlugin(new IOConfig.Builder()
.dynamicConfig(dynamicConfig)
.build());
//add to matrix
builder.plugin(ioCanaryPlugin);
//init matrix
Matrix.init(builder.build());
// start plugin
ioCanaryPlugin.start();
For more Matrix configurations, look at the sample.
Note:
- Since Matrix for Android has migrated to AndroidX since v0.9.0. You may need to add 'android.useAndroidX=true' flag to gradle.properties
- You can get more about Matrix output at the wiki The output of Matrix;
Battery Canary Usage
Init BatteryCanary as the following codes:
BatteryMonitorConfig config = new BatteryMonitorConfig.Builder()
.enable(JiffiesMonitorFeature.class)
.enableStatPidProc(true)
.greyJiffiesTime(30 * 1000L)
.setCallback(new BatteryMonitorCallback.BatteryPrinter())
.build();
BatteryMonitorPlugin plugin = new BatteryMonitorPlugin(config);
For detail usage, please reference showcase tests at com.tencent.matrix.batterycanary.ApisTest
or sample.tencent.matrix.battery.BatteryCanaryInitHelper
.
Backtrace Component Usage
How to init backtrace componentï¼
WeChatBacktrace.instance().configure(getApplicationContext()).commit();
Then other components in Matrix could use Quikcen Backtrace to unwind stacktrace. See more configuration comments in 'WeChatBacktrace.Configuration'.
APK Checker Usage
APK Checker can run independently in Jar (matrix-apk-canary-2.1.0.jarï¼ mode, usage:
java -jar matrix-apk-canary-2.1.0.jar
Usages:
--config CONFIG-FILE-PATH
or
[--input INPUT-DIR-PATH] [--apk APK-FILE-PATH] [--unzip APK-UNZIP-PATH] [--mappingTxt MAPPING-FILE-PATH] [--resMappingTxt RESGUARD-MAPPING-FILE-PATH] [--output OUTPUT-PATH] [--format OUTPUT-FORMAT] [--formatJar OUTPUT-FORMAT-JAR] [--formatConfig OUTPUT-FORMAT-CONFIG (json-array format)] [Options]
Options:
-manifest
Read package info from the AndroidManifest.xml.
-fileSize [--min DOWN-LIMIT-SIZE (KB)] [--order ORDER-BY ('asc'|'desc')] [--suffix FILTER-SUFFIX-LIST (split by ',')]
Show files whose size exceed limit size in order.
-countMethod [--group GROUP-BY ('class'|'package')]
Count methods in dex file, output results group by class name or package name.
-checkResProguard
Check if the resguard was applied.
-findNonAlphaPng [--min DOWN-LIMIT-SIZE (KB)]
Find out the non-alpha png-format files whose size exceed limit size in desc order.
-checkMultiLibrary
Check if there are more than one library dir in the 'lib'.
-uncompressedFile [--suffix FILTER-SUFFIX-LIST (split by ',')]
Show uncompressed file types.
-countR
Count the R class.
-duplicatedFile
Find out the duplicated resource files in desc order.
-checkMultiSTL --toolnm TOOL-NM-PATH
Check if there are more than one shared library statically linked the STL.
-unusedResources --rTxt R-TXT-FILE-PATH [--ignoreResources IGNORE-RESOURCES-LIST (split by ',')]
Find out the unused resources.
-unusedAssets [--ignoreAssets IGNORE-ASSETS-LIST (split by ',')]
Find out the unused assets file.
-unstrippedSo --toolnm TOOL-NM-PATH
Find out the unstripped shared library file.
Learn more about Matrix-APKChecker
Support
Any problem?
- Learn more from Sample
- Source Code
- Wiki & FAQ
- Contact us for help
Contributing
If you are interested in contributing, check out the CONTRIBUTING.md, also join our Tencent OpenSource Plan.
License
Matrix is under the BSD license. See the LICENSE file for details
Matrix
Matrix æ¯ä¸æ¬¾å¾®ä¿¡ç å并æ¥å¸¸ä½¿ç¨çåºç¨æ§è½æ¥å ¥æ¡æ¶ï¼æ¯æiOS, macOSåAndroidã Matrix éè¿æ¥å ¥åç§æ§è½çæ§æ¹æ¡ï¼å¯¹æ§è½çæ§é¡¹çå¼å¸¸æ°æ®è¿è¡ééååæï¼è¾åºç¸åºçé®é¢åæãå®ä½ä¸ä¼å建议ï¼ä»è帮å©å¼åè å¼ååºæ´é«è´¨éçåºç¨ã
Matrix for iOS/macOS
Matrix-iOS å½åå·¥å ·çæ§èå´å æ¬ï¼å´©æºãå¡é¡¿åå åï¼å å«ä»¥ä¸ä¸æ¬¾æ件ï¼
-
WCCrashBlockMonitorPluginï¼ åºäº KSCrash æ¡æ¶å¼åï¼å ·æä¸çé¢å çå¡é¡¿å æ æè·è½åï¼åæ¶å ¼å¤å´©æºæè·è½å
-
WCMemoryStatPluginï¼ ä¸æ¬¾æ§è½æè´çå åçæ§å·¥å ·ï¼è½å¤å ¨é¢æè·åºç¨ OOM æ¶çå ååé 以åè°ç¨å æ æ åµ
-
WCFPSMonitorPluginï¼ ä¸æ¬¾ FPS çæ§å·¥å ·ï¼å½ç¨æ·æ»å¨çé¢æ¶ï¼è®°å½ä¸»çº¿ç¨è°ç¨æ
ç¹æ§
WCCrashBlockMonitorPlugin
- æ¥å ¥ç®åï¼ä»£ç æ ä¾µå ¥
- éè¿æ£æ¥ Runloop è¿è¡ç¶æå¤æåºç¨æ¯å¦å¡é¡¿ï¼åæ¶æ¯æ iOS/macOS å¹³å°
- å¢å èæ¶å æ æåï¼å¡é¡¿çº¿ç¨å¿«ç §æ¥å¿ä¸éå æè¿æ¶é´æèæ¶ç主线ç¨å æ
WCMemoryStatPlugin
- å¨åºç¨è¿è¡æé´è·å对象å活以åç¸åºçå æ ä¿¡æ¯ï¼å¨æ£æµå°åºç¨ OOM æ¶è¿è¡ä¸æ¥
使ç¨æ¹æ³
å®è£
- éè¿éæåºå®è£
- è·å Matrix æºç ï¼
- æå¼å½ä»¤è¡ï¼å¨
matrix/matrix-iOS
代ç ç®å½ä¸æ§è¡make
è¿è¡ç¼è¯çæéæåºï¼ç¼è¯å®æåï¼iOS å¹³å°çåºå¨matrix/matrix-iOS/build_ios
ç®å½ä¸ï¼macOS å¹³å°çåºå¨matrix/matrix-iOS/build_macos
ç®å½ä¸ï¼ - å·¥ç¨å¼å ¥éæåºï¼
- iOS å¹³å°ï¼ä½¿ç¨
matrix/matrix-iOS/build_ios
è·¯å¾ä¸çMatrix.framework
ï¼å°Matrix.framework
以éæåºçæ¹å¼å¼å ¥å·¥ç¨ï¼ - macOS å¹³å°ï¼ä½¿ç¨
matrix/matrix-iOS/build_macos
è·¯å¾ä¸çMatrix.framework
ï¼å°Matrix.framework
以éæåºçæ¹å¼å¼å ¥å·¥ç¨ã
- æ·»å 头æ件
#import <Matrix/Matrix.h>
ï¼å°±å¯ä»¥æ¥å ¥å¾®ä¿¡çæ§è½æ¢éå·¥å ·äºï¼
å¯å¨çæ§
å¨ä»¥ä¸å°æ¹ï¼
- ç¨åº
main
å½æ°å ¥å£ï¼ AppDelegate
ä¸çapplication:didFinishLaunchingWithOptions:
ï¼- æè å ¶ä»åºç¨å¯å¨æ¯è¾æ©çæ¶é´ç¹ã
æ·»å 类似å¦ä¸ä»£ç ï¼å¯å¨æ件ï¼
#import <Matrix/Matrix.h>
Matrix *matrix = [Matrix sharedInstance];
MatrixBuilder *curBuilder = [[MatrixBuilder alloc] init];
curBuilder.pluginListener = self; // pluginListener åè° plugin çç¸å
³äºä»¶
WCCrashBlockMonitorPlugin *crashBlockPlugin = [[WCCrashBlockMonitorPlugin alloc] init];
[curBuilder addPlugin:crashBlockPlugin]; // æ·»å å¡é¡¿åå´©æºçæ§
WCMemoryStatPlugin *memoryStatPlugin = [[WCMemoryStatPlugin alloc] init];
[curBuilder addPlugin:memoryStatPlugin]; // æ·»å å
åçæ§åè½
WCFPSMonitorPlugin *fpsMonitorPlugin = [[WCFPSMonitorPlugin alloc] init];
[curBuilder addPlugin:fpsMonitorPlugin]; // æ·»å fps çæ§åè½
[matrix addMatrixBuilder:curBuilder];
[crashBlockPlugin start]; // å¼å¯å¡é¡¿åå´©æºçæ§
[memoryStatPlugin start]; // å¼å¯å
åçæ§
[fpsMonitorPlugin start]; // å¼å¯ fps çæ§
æ¥æ¶åè°è·å¾çæ§æ°æ®
设置 MatrixBuilder 对象ä¸ç pluginListenerï¼å®ç° MatrixPluginListenerDelegateã
// 设置 delegate
MatrixBuilder *curBuilder = [[MatrixBuilder alloc] init];
curBuilder.pluginListener = <ä¸ä¸ªéµå¾ª MatrixPluginListenerDelegate ç对象>;
// MatrixPluginListenerDelegate
- (void)onInit:(id<MatrixPluginProtocol>)plugin;
- (void)onStart:(id<MatrixPluginProtocol>)plugin;
- (void)onStop:(id<MatrixPluginProtocol>)plugin;
- (void)onDestroy:(id<MatrixPluginProtocol>)plugin;
- (void)onReportIssue:(MatrixIssue *)issue;
å个添å å° MatrixBuilder ç plugin ä¼å°å¯¹åºçäºä»¶éè¿ pluginListener åè°ã
éè¦ï¼éè¿ onReportIssue:
è·å¾ Matrix å¤çåçæ°æ®ï¼çæ§æ°æ®æ ¼å¼è¯¦è§ï¼Matrix for iOS/macOS æ°æ®æ ¼å¼è¯´æ
Demo
è³æ¤ï¼Matrix å·²ç»éæå°åºç¨ä¸å¹¶ä¸å¼å§æ¶éå´©æºãå¡é¡¿åçå
åæ°æ®ï¼å¦ä»æçé®ï¼è¯·æ¥ç示ä¾ï¼samples/sample-iOS/MatrixDemo
Matrix for Android
Matrix-android å½åçæ§èå´å æ¬ï¼åºç¨å®è£ å 大å°ï¼å¸§çååï¼å¯å¨èæ¶ï¼å¡é¡¿ï¼æ ¢æ¹æ³ï¼SQLite æä½ä¼åï¼æ件读åï¼å åæ³æ¼ççã
-
APK Checker: é对 APK å®è£ å çåææ£æµå·¥å ·ï¼æ ¹æ®ä¸ç³»å设å®å¥½çè§åï¼æ£æµ APK æ¯å¦åå¨ç¹å®çé®é¢ï¼å¹¶è¾åºè¾ä¸ºè¯¦ç»çæ£æµç»ææ¥åï¼ç¨äºåæææ¥é®é¢ä»¥åçæ¬è¿½è¸ª
-
Resource Canary: åºäº WeakReference çç¹æ§å Square Haha åºå¼åç Activity æ³æ¼å Bitmap éå¤å建æ£æµå·¥å ·
-
Trace Canary: çæ§ANRãçé¢æµç æ§ãå¯å¨èæ¶ã页é¢åæ¢èæ¶ãæ ¢å½æ°åå¡é¡¿çé®é¢
-
SQLite Lint: æå®æ¹æä½³å®è·µèªå¨åæ£æµ SQLite è¯å¥ç使ç¨è´¨é
-
IO Canary: æ£æµæ件 IO é®é¢ï¼å æ¬ï¼æ件 IO çæ§å Closeable Leak çæ§
-
Battery Canary: çæ§ App æ´»è·çº¿ç¨ï¼å¾ æºç¶æ & åå° Loop çæ§ï¼ãASM è°ç¨ (WakeLock/Alarm/Gps/Wifi/Bluetooth çä¼ æå¨)ã åå°æµé (Wifi/移å¨ç½ç»)ç Battery Historian ç»è®¡ App èçµçæ°æ®
-
MemGuard
æ£æµå å å访é®è¶çã使ç¨éæ¾åçå åãéå¤éæ¾çé®é¢
ç¹æ§
ä¸å¸¸è§ç APM å·¥å ·ç¸æ¯ï¼Matrix æ¥æ以ä¸ç¹ç¹ï¼
APK Checker
- å ·ææ´å¥½çå¯ç¨æ§ï¼JAR å æ¹å¼æä¾ï¼æ´æ¹ä¾¿åºç¨å°æç»éæç³»ç»ä¸ï¼ä»è追踪å对æ¯æ¯ä¸ª APK çæ¬ä¹é´çåå
- æ´å¤çæ£æ¥åæåè½ï¼é¤å ·å¤ APKAnalyzer çåè½å¤ï¼è¿æ¯æç»è®¡ APK ä¸å å«ç R ç±»ãæ£æ¥æ¯å¦æå¤ä¸ªå¨æåºéæé¾æ¥äº STL ãæç´¢ APK ä¸å å«çæ ç¨èµæºï¼ä»¥åæ¯æèªå®ä¹æ£æ¥è§åç
- è¾åºçæ£æ¥ç»ææ´å 详å®ï¼æ¯æå¯è§åç HTML æ ¼å¼ï¼ä¾¿äºåæå¤çç JSON ï¼èªå®ä¹è¾åºçç
Resource Canary
- å离äºæ£æµååæé¨åï¼ä¾¿äºå¨ä¸ææèªå¨åæµè¯çåæä¸æç»è¾åºåæåçæ£æµç»æ
- 对æ£æµé¨åçæç Hprof æ件è¿è¡äºè£åªï¼ç§»é¤äºå¤§é¨åæ ç¨æ°æ®ï¼éä½äºä¼ è¾ Hprof æ件çå¼é
- å¢å äºéå¤ Bitmap 对象æ£æµï¼æ¹ä¾¿éè¿åå°åä½ Bitmap æ°éï¼éä½å åæ¶è
Trace Canary
- ç¼è¯æå¨æä¿®æ¹åèç , é«æ§è½è®°å½æ§è¡èæ¶ä¸è°ç¨å æ
- åç¡®çå®ä½å°åçå¡é¡¿çå½æ°ï¼æä¾æ§è¡å æ ãæ§è¡èæ¶ãæ§è¡æ¬¡æ°çä¿¡æ¯ï¼å¸®å©å¿«é解å³å¡é¡¿é®é¢
- èªå¨æ¶µçå¡é¡¿ãå¯å¨èæ¶ã页é¢åæ¢ãæ ¢å½æ°æ£æµçå¤ä¸ªæµç æ§ææ
- åç¡®çæ§ANRï¼å¹¶ä¸è½å¤é«å ¼å®¹æ§å稳å®æ§å°ä¿åç³»ç»äº§ççANR Traceæ件
SQLite Lint
- æ¥å ¥ç®åï¼ä»£ç æ ä¾µå ¥
- æ°æ®éæ å ³ï¼å¼åãæµè¯é¶æ®µå³å¯åç°SQLiteæ§è½éæ£
- æ£æµç®æ³åºäºæä½³å®è·µï¼é«æ åææ§SQLiteè´¨é*
- åºå±æ¯ C++ å®ç°ï¼æ¯æå¤å¹³å°æ©å±
IO Canary
- æ¥å ¥ç®åï¼ä»£ç æ ä¾µå ¥
- æ§è½ãæ³æ¼å ¨é¢çæ§ï¼å¯¹ IO è´¨éå¿ä¸ææ°
- å ¼å®¹å° Android P
Battery Canary
- æ¥å ¥ç®åï¼å¼ç®±å³ç¨
- é¢ç Base ç±»å Utility å·¥å ·ä»¥ä¾¿æ©å±çæ§ç¹æ§
Memory Hook
- ä¸ä¸ªæ£æµ Android native å åæ³æ¼çå·¥å ·
- æ ä¾µå ¥ï¼åºäº PLT-hook(iqiyi/xHook)ï¼æ ééç¼ native åº
- é«æ§è½ï¼åºäº Wechat-Backtrace è¿è¡å¿«é unwind å æ ï¼æ¯æ aarch64 å armeabi-v7a æ¶æ
Pthread Hook
- ä¸ä¸ªæ£æµ Android Java å native 线ç¨æ³æ¼å缩å native 线ç¨æ 空é´çå·¥å ·
- æ ä¾µå ¥ï¼åºäº PLT-hook(iqiyi/xHook)ï¼æ ééç¼ native åº
- éè¿å¯¹ native 线ç¨çé»è®¤æ 大å°è¿è¡ååéä½çº¿ç¨å¸¦æ¥çèæå åå¼éï¼å¨ 32 ä½ç¯å¢ä¸å¯ç¼è§£èæå åä¸è¶³å¯¼è´çå´©æºé®é¢
WVPreAllocHook
- ä¸ä¸ªç¨äºå®å ¨éæ¾ WebView é¢åé å å以å¨ä¸å è½½ WebView æ¶èçèæå åçå·¥å ·ï¼å¨ 32 ä½ç¯å¢ä¸å¯ç¼è§£èæå åä¸è¶³å¯¼è´çå´©æºé®é¢
- æ ä¾µå ¥ï¼åºäº PLT-hook(iqiyi/xHook)ï¼æ ééç¼ native åº
- 使ç¨è¯¥å·¥å ·å WebView ä»å¯æ£å¸¸å·¥ä½
MemGuard
- ä¸ä¸ªåºäº GWP-Asan ä¿®æ¹çå å åé®é¢æ£æµå·¥å ·
- æ ä¾µå ¥ï¼åºäº PLT-hook(iqiyi/xHook)ï¼æ ééç¼ native åº
- å¯æ ¹æ®æ£å表达å¼æå®è¢«æ£æµçç®æ åº
- å¯æ£æµå å å访é®è¶çã使ç¨éæ¾åçå åååééæ¾çé®é¢
Backtrace Component
- åºäº DWARF 以å ARM å¼å¸¸å¤çæ°æ®è¿è¡ç®å并çæå ¨æ°ç quicken unwind tables æ°æ®ï¼ç¨äºå®ç°å¯å¿«éå溯 native è°ç¨æ ç backtrace ç»ä»¶ãå溯éåº¦çº¦æ¯ libunwindstack ç 15x ~ 30x å·¦å³ã
使ç¨æ¹æ³
ç±äº JCenter æå¡å°äº 2022 å¹´ 2 æ 1 æ¥ä¸çº¿ï¼æä»¬å·²å° Matrix æ°çæ¬ï¼>= 0.8.0) maven repo åå¸è³ MavenCentralã
- å¨ä½ 项ç®æ ¹ç®å½ä¸ç gradle.properties ä¸é ç½®è¦ä¾èµç Matrix çæ¬å·ï¼å¦ï¼
MATRIX_VERSION=2.1.0
- å¨ä½ 项ç®æ ¹ç®å½ä¸ç build.gradle æ件添å Matrix ä¾èµï¼å¦ï¼
dependencies {
classpath ("com.tencent.matrix:matrix-gradle-plugin:${MATRIX_VERSION}") { changing = true }
}
- æ¥çï¼å¨ app/build.gradle æ件ä¸æ·»å Matrix å模åçä¾èµï¼å¦ï¼
dependencies {
implementation group: "com.tencent.matrix", name: "matrix-android-lib", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-android-commons", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-trace-canary", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-resource-canary-android", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-resource-canary-common", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-io-canary", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-sqlite-lint-android-sdk", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-battery-canary", version: MATRIX_VERSION, changing: true
implementation group: "com.tencent.matrix", name: "matrix-hooks", version: MATRIX_VERSION, changing: true
}
apply plugin: 'com.tencent.matrix-plugin'
matrix {
trace {
enable = true //if you don't want to use trace canary, set false
baseMethodMapFile = "${project.buildDir}/matrix_output/Debug.methodmap"
blackListFile = "${project.projectDir}/matrixTrace/blackMethodList.txt"
}
}
ç®å Matrix gradle plugin æ¯æ Android Gradle Plugin 3.5.0/4.0.0/4.1.0ã
- å®ç° PluginListenerï¼æ¥æ¶ Matrix å¤çåçæ°æ®, å¦ï¼
public class TestPluginListener extends DefaultPluginListener {
public static final String TAG = "Matrix.TestPluginListener";
public TestPluginListener(Context context) {
super(context);
}
@Override
public void onReportIssue(Issue issue) {
super.onReportIssue(issue);
MatrixLog.e(TAG, issue.toString());
//add your code to process data
}
}
- å®ç°å¨æé ç½®æ¥å£ï¼ å¯ä¿®æ¹ Matrix å é¨åæ°. å¨ sample-android ä¸ æ们æ个ç®åçå¨ææ¥å£å®ä¾DynamicConfigImplDemo.java, å ¶ä¸åæ°å¯¹åºç key ä½äºæ件 MatrixEnumä¸ï¼ ææé¨å示ä¾å¦ä¸ï¼
public class DynamicConfigImplDemo implements IDynamicConfig {
public DynamicConfigImplDemo() {}
public boolean isFPSEnable() { return true;}
public boolean isTraceEnable() { return true; }
public boolean isMatrixEnable() { return true; }
public boolean isDumpHprof() { return false;}
@Override
public String get(String key, String defStr) {
//hook to change default values
}
@Override
public int get(String key, int defInt) {
//hook to change default values
}
@Override
public long get(String key, long defLong) {
//hook to change default values
}
@Override
public boolean get(String key, boolean defBool) {
//hook to change default values
}
@Override
public float get(String key, float defFloat) {
//hook to change default values
}
}
- éæ©ç¨åºå¯å¨çä½ç½®å¯¹ Matrix è¿è¡åå§åï¼å¦å¨ Application ç继æ¿ç±»ä¸ï¼ Init æ ¸å¿é»è¾å¦ä¸ï¼
Matrix.Builder builder = new Matrix.Builder(application); // build matrix
builder.pluginListener(new TestPluginListener(this)); // add general pluginListener
DynamicConfigImplDemo dynamicConfig = new DynamicConfigImplDemo(); // dynamic config
// init plugin
IOCanaryPlugin ioCanaryPlugin = new IOCanaryPlugin(new IOConfig.Builder()
.dynamicConfig(dynamicConfig)
.build());
//add to matrix
builder.plugin(ioCanaryPlugin);
//init matrix
Matrix.init(builder.build());
// start plugin
ioCanaryPlugin.start();
è³æ¤ï¼Matrix就已æåéæå°ä½ ç项ç®ä¸ï¼å¹¶ä¸å¼å§æ¶éååææ§è½ç¸å ³å¼å¸¸æ°æ®ï¼å¦ä»æçé®ï¼è¯·æ¥ç 示ä¾.
PSï¼
- ä» v0.9.0 å¼å§ï¼Matrix for Android è¿ç§»å°äº AndroidX. ä½ å¯è½éè¦æ·»å 'android.useAndroidX=true' æ å¿å° gradle.properties æ件éã
- Matrix åæåçè¾åºå段çå«ä¹è¯·æ¥ç Matrix è¾åºå 容çå«ä¹è§£æ
Battery Canary Usage
ç¸å ³åå§å代ç å¦ä¸ï¼
BatteryMonitorConfig config = new BatteryMonitorConfig.Builder()
.enable(JiffiesMonitorFeature.class)
.enableStatPidProc(true)
.greyJiffiesTime(30 * 1000L)
.setCallback(new BatteryMonitorCallback.BatteryPrinter())
.build();
BatteryMonitorPlugin plugin = new BatteryMonitorPlugin(config);
å
·ä½ä½¿ç¨æ¹å¼ï¼è¯·åèåå
æµè¯éç¸å
³ç¨ä¾ç代ç ï¼ com.tencent.matrix.batterycanary.ApisTest
æ sample.tencent.matrix.battery.BatteryCanaryInitHelper
.
Backtrace Component Usage
å¦ä½åå§å backtrace ç»ä»¶ï¼
WeChatBacktrace.instance().configure(getApplicationContext()).commit();
åå§ååå ¶ä» Matrix ç»ä»¶å°±å¯ä»¥ä½¿ç¨ Quicken Backtrace è¿è¡å溯ãæ´å¤åæ°çé 置请æ¥ç WeChatBacktrace.Configuration çæ¥å£æ³¨éã
APK Checker
APK Check 以ç¬ç«ç jar å æä¾ (matrix-apk-canary-2.1.0.jarï¼ï¼ä½ å¯ä»¥è¿è¡ï¼
java -jar matrix-apk-canary-2.1.0.jar
æ¥ç Usages æ¥ä½¿ç¨å®ã
Usages:
--config CONFIG-FILE-PATH
or
[--input INPUT-DIR-PATH] [--apk APK-FILE-PATH] [--unzip APK-UNZIP-PATH] [--mappingTxt MAPPING-FILE-PATH] [--resMappingTxt RESGUARD-MAPPING-FILE-PATH] [--output OUTPUT-PATH] [--format OUTPUT-FORMAT] [--formatJar OUTPUT-FORMAT-JAR] [--formatConfig OUTPUT-FORMAT-CONFIG (json-array format)] [Options]
Options:
-manifest
Read package info from the AndroidManifest.xml.
-fileSize [--min DOWN-LIMIT-SIZE (KB)] [--order ORDER-BY ('asc'|'desc')] [--suffix FILTER-SUFFIX-LIST (split by ',')]
Show files whose size exceed limit size in order.
-countMethod [--group GROUP-BY ('class'|'package')]
Count methods in dex file, output results group by class name or package name.
-checkResProguard
Check if the resguard was applied.
-findNonAlphaPng [--min DOWN-LIMIT-SIZE (KB)]
Find out the non-alpha png-format files whose size exceed limit size in desc order.
-checkMultiLibrary
Check if there are more than one library dir in the 'lib'.
-uncompressedFile [--suffix FILTER-SUFFIX-LIST (split by ',')]
Show uncompressed file types.
-countR
Count the R class.
-duplicatedFile
Find out the duplicated resource files in desc order.
-checkMultiSTL --toolnm TOOL-NM-PATH
Check if there are more than one shared library statically linked the STL.
-unusedResources --rTxt R-TXT-FILE-PATH [--ignoreResources IGNORE-RESOURCES-LIST (split by ',')]
Find out the unused resources.
-unusedAssets [--ignoreAssets IGNORE-ASSETS-LIST (split by ',')]
Find out the unused assets file.
-unstrippedSo --toolnm TOOL-NM-PATH
Find out the unstripped shared library file.
ç±äºç¯å¹ å½±åï¼æ¤æ¬¡ä¸åèµè¿°ï¼æä»¬å¨ Matrix-APKChecker ä¸è¿è¡äºè¯¦ç»è¯´æã
Support
è¿æå ¶ä»é®é¢ï¼
åä¸è´¡ç®
å ³äº Matrix åæ¯ç®¡çãissue 以å pr è§èï¼è¯·é 读 Matrix Contributing Guideã
è ¾è®¯å¼æºæ¿å±è®¡å é¼å±å¼åè çåä¸åè´¡ç®ï¼æå¾ ä½ çå å ¥ã
License
Matrix is under the BSD license. See the LICENSE file for details
ä¿¡æ¯å ¬ç¤º
- SDKå称ï¼Matrix
- çæ¬å·ï¼2.1.0
- å¼åè ï¼æ·±å³å¸è ¾è®¯è®¡ç®æºç³»ç»æéå ¬å¸
- 主è¦åè½ï¼Matrixæ¯å¾®ä¿¡ç å并æ¥å¸¸ä½¿ç¨çåºç¨æ§è½çæ§å·¥å ·ï¼æ¯æiOSãmacOSåAndroidãMatrixéè¿æ¥å ¥éªéãå¡é¡¿ãèçµãå åçæ¹é¢ççæ§æ¹æ¡ï¼å¯¹æ§è½çæ§é¡¹çå¼å¸¸æ°æ®è¿è¡ééååæï¼è¾åºç¸åºçé®é¢åæãå®ä½ä¸ä¼å建议ï¼ä»è帮å©å¼åè å¼ååºæ´é«è´¨éçåºç¨ã
- Matrix SDK使ç¨è¯´æ
- Matrix SDK个人信æ¯ä¿æ¤è§å
Top Related Projects
A memory leak detection library for Android.
A static analyzer for Java, C, C++, and Objective-C
Android and Java bytecode viewer
A library for performance traces from production.
A tool to help eliminate NullPointerExceptions (NPEs) in your Java code with low build-time overhead
Catch common Java mistakes as compile-time errors
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot