-
-
Notifications
You must be signed in to change notification settings - Fork 2k
ohos_setup
MMKV is an efficient, small, easy-to-use mobile key-value storage framework used in the WeChat application. It's now available on HarmonyOS NEXT.
-
Efficient. MMKV uses mmap to keep memory synced with files, and protobuf to encode/decode values, making the most of the native platform to achieve the best performance.
- Multi-Process concurrency: MMKV supports concurrent read-read and read-write access between processes.
-
Easy-to-use. You can use MMKV as you go. All changes are saved immediately, no
sync, noflushcalls are needed. -
Small.
- A handful of files: MMKV contains process locks, encode/decode helpers and mmap logics and nothing more. It's really tidy.
- About 600K in binary size: MMKV adds about 600K per architecture on App size, and much less when zipped (HAR/HAP).
- Apps using MMKV can target: HarmonyOS Next (3.0.0.13) or later.
- ARM64 & x86_64 architecture.
- DevEco Studio NEXT Developer Beta1 (5.0.3.100) or later.
This is the fastest and most recommended way to add MMKV to your project.
ohpm install @tencent/mmkvOr, you can add it to your project manually.
-
Add the following lines to
oh-package.json5on your app module."dependencies": { "@tencent/mmkv": "2.3.0", }
-
Then run
ohpm install
You can integrate MMKV by source.
-
Checkout MMKV source code:
git clone https://github.com/Tencent/MMKV.git
Note:
- you may consider adding MMKV as git submodule.
- By default, MMKV links
libc++statically. If you want smaller binary size and you know what you're doing, you can edit the filebuild-profile.json5of the MMKV module, change the line to"arguments": "-DOHOS_STL=c++_shared", and"cppFlags": "-DMMKV_STL_SHARED=1. - If you want to access MMKV's C++ interface directly, you can edit the file
build-profile.json5of the MMKV module, changing the line to"cppFlags": "…… -fvisibility=default ……". Note that this will increase the binary size a little bit.
-
Add the following lines to
oh-package.json5on your app module."dependencies": { "@tencent/mmkv": "file:path/to/mmkv/OpenHarmony/MMKV", }
-
Then run
ohpm install
You can integrate MMKV by pre-built HAR.
-
Checkout MMKV source code:
git clone https://github.com/Tencent/MMKV.git
-
Open the MMKV project in
path/to/mmkv/OpenHarmony, open the Product window and select Build Mode to "release"; SelectMMKVmodule, in the menu selectBuild->Make Module 'MMKV', export the build result as "MMKV.har" to your project folder.- you may consider adding MMKV as git submodule.
- By default, MMKV links
libc++statically. If you want smaller binary size and you know what you're doing, you can edit the filebuild-profile.json5of the MMKV module, change the line to"arguments": "-DOHOS_STL=c++_shared", and"cppFlags": "-DMMKV_STL_SHARED=1. - If you want to access MMKV's C++ interface directly, you can edit the file
build-profile.json5of the MMKV module, changing the line to"cppFlags": "…… -fvisibility=default ……". Note that this will increase the binary size a little bit.
-
Add the following lines to
oh-package.json5on your app module."dependencies": { "@tencent/mmkv": "file:path/to/MMKV.har", }
-
Then run
ohpm install
You can use MMKV as you go. All changes are saved immediately, no sync, no apply calls needed.
Setup MMKV on App startup, say your EntryAbility.onCreate() function, add these lines:
import { MMKV } from '@tencent/mmkv';
export default class EntryAbility extends UIAbility {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
let appCtx = this.context.getApplicationContext();
let mmkvRootDir = MMKV.initialize(appCtx);
console.info('mmkv rootDir: ', mmkvRootDir);
……
}-
MMKV has a global instance, that can be used directly:
import { MMKV } from '@tencent/mmkv'; let mmkv = MMKV.defaultMMKV(); mmkv.encodeBool('bool', true); console.info('bool = ', mmkv.decodeBool('bool')); mmkv.encodeInt32('int32', Math.pow(2, 31) - 1); console.info('max int32 = ', mmkv.decodeInt32('int32')); mmkv.encodeInt64('int', BigInt(2**63) - BigInt(1)); console.info('max int64 = ', mmkv.decodeInt64('int')); let str: string = 'Hello OpenHarmony from MMKV'; mmkv.encodeString('string', str); console.info('string = ', mmkv.decodeString('string')); let arrayBuffer: ArrayBuffer = StringToArrayBuffer('Hello OpenHarmony from MMKV with bytes'); mmkv.encodeBytes('bytes', arrayBuffer); let bytes = mmkv.decodeBytes('bytes'); console.info('bytes = ', ArrayBufferToString(bytes)); let arr = new Uint8Array([0, 255, 1, 255]); mmkv.encodeTypedArray('uint8-array', arr); let newUI8Arr = kv.decodeUint8Array('uint8-array'); console.info('uint8-array = ', newUI8Arr);
As you can see, MMKV is quite easy to use.
-
Deleting & Querying:
mmkv.removeValueForKey('bool'); console.info('contains "bool"', mmkv.containsKey('bool')); mmkv.removeValuesForKeys(['int32', 'int']); console.info('all keys: ', mmkv.allKeys().join());
-
If different modules/logic need isolated storage, you can also create your own MMKV instance separately:
var mmkv = MMKV.mmkvWithID('test'); mmkv.encodeBool('bool', true); console.info('bool = ', mmkv.decodeBool('bool'));
-
If multi-process accessing is needed,you can set
MMKV.MULTI_PROCESS_MODEon MMKV initialization:var mmkv = MMKV.mmkvWithID('test-multi-process', MMKV.MULTI_PROCESS_MODE); mmkv.encodeBool('bool', true); console.info('bool = ', mmkv.decodeBool('bool'));
-
Primitive Types:
boolean, number, bigint, string
-
Classes & Collections:
boolean[], number[], string[], ArrayBuffer, TypedArray
-
Custom Classes:
We don't support custom classes directly because there's noParcelreplacement in OHOS. You can encode/decode to JSON first. Or use whatever encoding lib you like such as protobuf.let user = { username: 'dummy_user', age: 23 } // Serialize the object into a JSON string mmkv.encodeString('user', JSON.stringify(user)) // Deserialize the JSON string into an object let jsonUser = mmkv.decodeString('user') // { 'username': 'dummy_user', 'age': 23 } let userObject = JSON.parse(jsonUser)
-
By default, MMKV prints log to hilog, which is not convenient for diagnosing online issues. You can setup MMKV log redirecting on App startup on the native interface of MMKV. Checkout how to do it on C++. Due to the current limitation of NAPI runtime, we can't efficiently redirect log to the JavaScript side.
-
You can turn off MMKV's logging once and for all on initialization (which we strongly disrecommend).
import { MMKV, MMKVLogLevel } from '@tencent/mmkv'; MMKV.initialize(appCtx, MMKVLogLevel.None);
-
By default MMKV stores all key-values in plain text on file, relying on Android's/iOS's sandbox to make sure the file is encrypted. Should you worry about information leaking, you can choose to encrypt MMKV.
let encryptKey = 'MyEncryptKey'; let mmkv = MMKV.mmkvWithID('test-encryption', MMKV.SINGLE_PROCESS_MODE, encryptKey);
-
You can change the encryption key later as you like. You can also change an existing MMKV instance from encrypted to unencrypted, or vice versa.
// an unencrypted MMKV instance let mmkv = MMKV.mmkvWithID('test-encryption'); // change from unencrypted to encrypted with AES-128 key length mmkv.reKey('Key_seq_1'); // change encryption key with AES-256 key length mmkv.reKey('Key_Seq_Very_Looooooooong', true); // change from encrypted to unencrypted kmmkv.reKey();
-
By default, MMKV stores file inside
$(FilesDir)/mmkv/. You can customize MMKV's root directory on App startup:let appCtx = this.context.getApplicationContext(); let rootDir = appCtx.filesDir + '/mmkv_2'; let cacheDir = appCtx.cacheDir; MMKV.initializeWithPath(rootDir, cacheDir);
-
You can even customize any MMKV instance's location:
let appCtx = this.context.getApplicationContext(); let rootDir = appCtx.filesDir + '/mmkv_3'; var mmkv = MMKV.mmkvWithID('testCustomDir', MMKV.SINGLE_PROCESS_MODE, null, rootDir);
Note: It's recommended to store MMKV files inside your App's sandbox path. DO NOT store them on external storage(aka SD card).
-
Typically, when a
stringorArrayBuffervalue is getting from MMKV, there's a memory copying from native to JSVM. And if that value is passed to another native library(NAPI) immediately, another memory-copying from JSVM to native happens. The whole process wastes too much if that value's size is large. Here comes the Native Buffer to the rescue.
Native Buffer is a memory buffer created in native, wrapped asNativeBufferin JavaScript, which can be passed to another native library transparently. This process saves memory-copying to & from JSVM. Example code:let sizeNeeded = mmkv.getValueSize('bytes', true); let nativeBuffer = MMKV.createNativeBuffer(sizeNeeded); if (nativeBuffer != null) { let size = mmkv.writeValueToNativeBuffer('bytes', nativeBuffer); console.info('NativeBuffer: size Needed = ', sizeNeeded, ', written size = ', size); // pass nativeBuffer to another native library // ... // destroy when you're done MMKV.destroyNativeBuffer(nativeBuffer); }
-
You can use MMKV's backup & restore API to backup your data to somewhere else, and restore them later.
let rootDir = ...; let backupRootDir = rootDir + '/mmkv_backup'; // backup one instance let ret = MMKV.backupOneToDirectory(mmapID, backupRootDir); // backup all instances let count = MMKV.backupAllToDirectory(backupRootDir); // restore one instance ret = MMKV.restoreOneMMKVFromDirectory(mmapID, backupRootDir); // restore all instances count = MMKV.restoreAllFromDirectory(backupRootDir);
You can upgrade MMKV to auto key expiration. Note that this is a breaking change. Once upgraded to auto key expiration, the file is not valid for any older version of MMKV (<= v1.2.16) to operate correctly.
-
Global Expiration
The most simple way to do it is to turn on auto key expiration for all keys in the whole file.// expire in a day mmkv.enableAutoKeyExpire(MMKV.ExpireInDay); // MMKV.ExpireInDay = 24 * 60 * 60
Or, if you prefer, you can enable auto key expiration without setting a global expiration duration. In this case, each key is not expired by default.
// enable auto key expiration without global duration mmkv.enableAutoKeyExpire(MMKV.ExpireNever); // MMKV.ExpireNever = 0
-
Individual Expiration
You can set a special expiration duration for a key, regardless with the file has a global duration or not. Note that you have to enable auto key expiration first.// enable auto key expiration with an hour duration mmkv.enableAutoKeyExpire(MMKV.ExpireInHour); // MMKV.ExpireInHour = 60 * 60 // set a key with the file's global expiration duration, aka MMKV.ExpireInHour mmkv.encodeString('key_1', 'some value'); // set a special key that expires in two hours mmkv.encodeString('key_2', 'some value', 2 * 60 * 60); // set a special key that never expires mmkv.encodeString('key_3', 'some value', MMKV.ExpireNever);
Or, if you prefer, you can enable auto key expiration without setting a global expiration duration. In this case, each key is not expired by default.
// enable auto key expiration without global duration mmkv.enableAutoKeyExpire(MMKV.ExpireNever); // MMKV.ExpireNever = 0 // set a key that never expires mmkv.encodeString('key_1', 'some value'); // set a special key that expires in an hour mmkv.encodeString('key_2', 'some value', MMKV.ExpireInHour);
-
The expire duration is counted in seconds
MMKV has some pre-defined duration for your convenience. You can use any other duration you prefer. For example, expiration in a week is7 * 24 * 60 * 60.static const int ExpireNever = 0; static const int ExpireInMinute = 60; static const int ExpireInHour = 60 * 60; static const int ExpireInDay = 24 * 60 * 60; static const int ExpireInMonth = 30 * 24 * 60 * 60; static const int ExpireInYear = 365 * 30 * 24 * 60 * 60;
Starting from v2.1.0, MMKV supports the NameSpace feature. It’s primarily designed to solve these problems:
-
Using in other modules/3rd lib/SDK without initialization
Traditionary MMKV requires initialized before use, and it will cause problem in multiple libs for one can’t be sure if MMKV has been initialized, nor can be sure of the root directory of MMKV. With NameSpace, a lib can use MMKV without initialization, and of cause without configuring global root directory. -
Fix the incorrect file naming in custom root directory
Historically MMKV for Android/OHOS mistakenly use mmapKey as mmapID, which will be problematic with the NameSpace feature. Starting from v2.1.0, MMKV will try to migrate them back to normal when possible. -
Make customizing root directory easy
Using NameSpace you can customize the root directory of a group of MMKV instances easily.
let appCtx = this.context.getApplicationContext();
let rootDir = appCtx.filesDir + '/mmkv_namespace';
let ns = MMKV.nameSpace(rootDir);
let kv = ns.mmkvWithID('test_namespace');Key Notes:
- This is a breaking change. It’s highly recommended that you upgrade to v2.0.2/v1.3.11+ first with forward support of normal MMKV in a custom directory.
- Upgrade path: v2.0.2/v1.3.11+ → v2.1.0+ (make sure a smooth upgrade)
Starting from v2.1.0, MMKV’s C++ interface can be accessed in your C++ code. It's done by embedding public headers in the OHPM archives.
Steps to adapt:
-
Verify MMKV has public headers
Afterohpm install, cd to the module you embedded MMKV, for example entry, and check if this folder exists:
path/to/entry/oh_modules/@tencent/mmkv/include/MMKV -
Find and link MMKV in your CMake project
# Add these lines
set(MODULE_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
# project/entry/oh_modules/@tencent/mmkv
set(MMKV_MODULE_PATH ${MODULE_ROOT_PATH}/oh_modules/@tencent/mmkv)
# project/entry/oh_modules/@tencent/mmkv/include
set(MMKV_INCLUDE_PATH ${MMKV_MODULE_PATH}/include)
# project/entry/oh_modules/@tencent/mmkv/libs/arm64-v8a
set(MMKV_LIB_PATH ${MMKV_MODULE_PATH}/libs/${OHOS_ARCH})
# setup mmkv include path
target_include_directories(entry PRIVATE ${MMKV_INCLUDE_PATH})
# setup mmkv lib path
add_library(mmkv SHARED IMPORTED)
if (EXISTS ${MMKV_LIB_PATH}/libmmkv.so)
set_target_properties(mmkv PROPERTIES IMPORTED_LOCATION ${MMKV_LIB_PATH}/libmmkv.so)
else()
message(FATAL_ERROR "Can't find libmmkv.so in @tencent/mmkv module:${MMKV_MODULE_PATH}, check if \"ohpm install @tencent/mmkv\" fail!")
endif()
target_link_libraries(entry PRIVATE mmkv)-
Include MMKV header
#include <MMKV/MMKV.h> auto ns = MMKV::nameSpace(nameSpaceDir); auto kv = ns.mmkvWithID("test_NAPI");
Check out the CHANGELOG.md for details of change history.
MMKV is published under the BSD 3-Clause license. For details check out the LICENSE.TXT.
Check out the CHANGELOG.md for details of change history.
If you are interested in contributing, check out the CONTRIBUTING.md, also join our Tencent OpenSource Plan.
To give clarity of what is expected of our members, MMKV has adopted the code of conduct defined by the Contributor Covenant, which is widely used. And we think it articulates our values well. For more, check out the Code of Conduct.
Check out the FAQ first. Should there be any questions, don't hesitate to create issues.
User privacy is taken very seriously: MMKV does not obtain, collect or upload any personal information. Please refer to the MMKV SDK Personal Information Protection Rules for details.
- In English
- 中文
- In English
- 中文
- In English
- 中文
-
In English
-
中文
-
Golang
- In English
- 中文