├── .gitignore ├── LICENSE ├── README.md ├── android ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── robinpowered │ └── react │ └── vitals │ ├── RNVitalsModule.java │ └── RNVitalsPackage.java ├── entry.android.js ├── entry.ios.js ├── index.js ├── ios ├── RNVitals.h ├── RNVitals.m ├── RNVitals.xcodeproj │ └── project.pbxproj ├── SSMemoryInfo.h └── SSMemoryInfo.m ├── package.json ├── react-native-vitals.podspec └── vitals.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | ############ 61 | # Android 62 | ############ 63 | # Built application files 64 | *.apk 65 | *.ap_ 66 | 67 | # Files for the Dalvik VM 68 | *.dex 69 | 70 | # Java class files 71 | *.class 72 | 73 | # Generated files 74 | android/bin/ 75 | android/gen/ 76 | android/out/ 77 | 78 | # Gradle files 79 | android/.gradle/ 80 | android/build/ 81 | 82 | # Local configuration file (sdk path, etc) 83 | local.properties 84 | 85 | # Proguard folder generated by Eclipse 86 | android/proguard/ 87 | 88 | # Log Files 89 | *.log 90 | 91 | # Android Studio Navigation editor temp files 92 | android/.navigation/ 93 | 94 | # Android Studio captures folder 95 | android/captures/ 96 | 97 | # Intellij 98 | *.iml 99 | 100 | # Keystore files 101 | *.jks 102 | 103 | # Gradle 104 | /build/ 105 | /RNTester/android/app/build/ 106 | /RNTester/android/app/gradle/ 107 | /RNTester/android/app/gradlew 108 | /RNTester/android/app/gradlew.bat 109 | /ReactAndroid/build/ 110 | 111 | # Xcode 112 | !**/*.xcodeproj 113 | !**/*.pbxproj 114 | !**/*.xcworkspacedata 115 | !**/*.xcsettings 116 | !**/*.xcscheme 117 | *.pbxuser 118 | !default.pbxuser 119 | *.mode1v3 120 | !default.mode1v3 121 | *.mode2v3 122 | !default.mode2v3 123 | *.perspectivev3 124 | !default.perspectivev3 125 | xcuserdata 126 | *.xccheckout 127 | *.moved-aside 128 | DerivedData 129 | *.hmap 130 | *.ipa 131 | *.xcuserstate 132 | project.xcworkspace 133 | 134 | ################ 135 | # JetBrains 136 | ################ 137 | .idea 138 | 139 | ## File-based project format: 140 | *.iws 141 | 142 | ## Plugin-specific files: 143 | 144 | # IntelliJ 145 | /out/ 146 | 147 | # mpeltonen/sbt-idea plugin 148 | .idea_modules/ 149 | 150 | # JIRA plugin 151 | atlassian-ide-plugin.xml 152 | 153 | # Crashlytics plugin (for Android Studio and IntelliJ) 154 | com_crashlytics_export_strings.xml 155 | crashlytics.properties 156 | crashlytics-build.properties 157 | fabric.properties 158 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Ying Hang Eng 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-vitals 2 | 3 | React Native package that provides memory/storage usage info of a device. 4 | 5 | ## Usage 6 | ```javascript 7 | import Vitals from 'react-native-vitals'; 8 | 9 | Vitals.getMemory().then(memory => { 10 | var { 11 | appUsed, 12 | systemTotal, 13 | systemFree, 14 | systemUsed 15 | } = memory; 16 | }); 17 | 18 | Vitals.getStorage().then(storage => { 19 | var { 20 | total, 21 | free, 22 | used 23 | } = storage; 24 | }); 25 | 26 | Vitals.addLowMemoryListener(memory => { 27 | console.log('Low memory warning triggered'); 28 | var { 29 | appUsed, 30 | systemTotal, 31 | systemFree, 32 | systemUsed 33 | } = memory; 34 | }) 35 | ``` 36 | 37 | ## Getting started 38 | 39 | `$ npm install react-native-vitals --save` 40 | 41 | ### Mostly automatic installation 42 | 43 | `$ react-native link react-native-vitals` 44 | 45 | ### Manual installation 46 | 47 | 48 | #### iOS 49 | 50 | 1. In XCode, in the project navigator, right click `Libraries` ➜ `Add Files to [your project's name]` 51 | 2. Go to `node_modules` ➜ `react-native-vitals` and add `RNVitals.xcodeproj` 52 | 3. In XCode, in the project navigator, select your project. Add `libRNVitals.a` to your project's `Build Phases` ➜ `Link Binary With Libraries` 53 | 4. Run your project (`Cmd+R`) 54 | 55 | #### iOS (using [CocoaPods](https://cocoapods.org/)) 56 | 57 | Alternatively, you can use CocoaPods to manage your native dependencies, just add this inside your `Podfile`: 58 | ``` 59 | pod 'react-native-vitals', :path => '../node_modules/react-native-vitals' 60 | ``` 61 | 62 | After adding this, you need to run `pod install` inside the `ios`-folder of your RN application. 63 | 64 | #### Android 65 | 66 | 1. Open up `android/app/src/main/java/[...]/MainActivity.java` 67 | - Add `import com.robinpowered.react.vitals.RNVitalsPackage;` to the imports at the top of the file 68 | - Add `new RNVitalsPackage()` to the list returned by the `getPackages()` method 69 | 2. Append the following lines to `android/settings.gradle`: 70 | ``` 71 | include ':react-native-vitals' 72 | project(':react-native-vitals').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-vitals/android') 73 | ``` 74 | 3. Insert the following lines inside the dependencies block in `android/app/build.gradle`: 75 | ``` 76 | compile project(':react-native-vitals') 77 | ``` 78 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | jcenter() 4 | } 5 | 6 | dependencies { 7 | classpath 'com.android.tools.build:gradle:1.3.1' 8 | } 9 | } 10 | 11 | apply plugin: 'com.android.library' 12 | 13 | def safeExtGet(prop, fallback) { 14 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback 15 | } 16 | 17 | android { 18 | compileSdkVersion safeExtGet('compileSdkVersion', '23') 19 | buildToolsVersion safeExtGet('buildToolsVersion', '23.0.1') 20 | 21 | defaultConfig { 22 | minSdkVersion safeExtGet('minSdkVersion', '16') 23 | targetSdkVersion safeExtGet('targetSdkVersion', '22') 24 | versionCode 1 25 | versionName "1.0" 26 | } 27 | lintOptions { 28 | abortOnError false 29 | } 30 | } 31 | 32 | repositories { 33 | mavenCentral() 34 | } 35 | 36 | dependencies { 37 | implementation 'com.facebook.react:react-native:+' 38 | } 39 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/src/main/java/com/robinpowered/react/vitals/RNVitalsModule.java: -------------------------------------------------------------------------------- 1 | package com.robinpowered.react.vitals; 2 | 3 | import android.os.Environment; 4 | import android.os.StatFs; 5 | import android.os.Build; 6 | import android.os.Debug; 7 | import android.content.ComponentCallbacks2; 8 | import android.content.res.Configuration; 9 | import android.app.ActivityManager; 10 | import android.content.Context; 11 | 12 | import com.facebook.react.bridge.LifecycleEventListener; 13 | import com.facebook.react.bridge.ReactApplicationContext; 14 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 15 | import com.facebook.react.bridge.ReactMethod; 16 | import com.facebook.react.bridge.Promise; 17 | import com.facebook.react.bridge.WritableMap; 18 | import com.facebook.react.bridge.Arguments; 19 | import com.facebook.react.modules.core.DeviceEventManagerModule; 20 | import java.util.Map; 21 | import java.util.HashMap; 22 | import javax.annotation.Nullable; 23 | 24 | import java.io.File; 25 | 26 | public class RNVitalsModule extends ReactContextBaseJavaModule implements ComponentCallbacks2, LifecycleEventListener { 27 | 28 | public static final String MODULE_NAME = "RNVitals"; 29 | public static final String LOW_MEMORY = "LOW_MEMORY"; 30 | public static final String MEMORY_LEVEL_KEY = "MemoryLevel"; 31 | 32 | public static final int MEMORY_MODERATE = TRIM_MEMORY_RUNNING_MODERATE; 33 | public static final int MEMORY_LOW = TRIM_MEMORY_RUNNING_LOW; 34 | public static final int MEMORY_CRITICAL = TRIM_MEMORY_RUNNING_CRITICAL; 35 | 36 | 37 | public RNVitalsModule(ReactApplicationContext reactContext) { 38 | super(reactContext); 39 | } 40 | 41 | private double toMB(long num) { 42 | return (double) (num / 1024 / 1024); 43 | } 44 | 45 | @Override 46 | public String getName() { 47 | return MODULE_NAME; 48 | } 49 | 50 | @Override 51 | public @Nullable Map getConstants() { 52 | HashMap memoryLevelConstants = new HashMap(); 53 | memoryLevelConstants.put("CRITICAL", MEMORY_CRITICAL); 54 | memoryLevelConstants.put("LOW", MEMORY_LOW); 55 | memoryLevelConstants.put("MODERATE", MEMORY_MODERATE); 56 | 57 | HashMap constants = new HashMap(); 58 | constants.put(LOW_MEMORY, LOW_MEMORY); 59 | constants.put(MEMORY_LEVEL_KEY, memoryLevelConstants); 60 | 61 | return constants; 62 | } 63 | 64 | private WritableMap getMemoryInfo() { 65 | ActivityManager.MemoryInfo mi = new ActivityManager.MemoryInfo(); 66 | ActivityManager activityManager = (ActivityManager) getReactApplicationContext() 67 | .getSystemService(Context.ACTIVITY_SERVICE); 68 | activityManager.getMemoryInfo(mi); 69 | 70 | Debug.MemoryInfo memInfo = new Debug.MemoryInfo(); 71 | Debug.getMemoryInfo(memInfo); 72 | long appUsed = memInfo.getTotalPss() * 1024L; 73 | 74 | WritableMap info = Arguments.createMap(); 75 | info.putDouble("systemTotal", toMB(mi.totalMem)); 76 | info.putDouble("appUsed", toMB(appUsed)); 77 | info.putDouble("systemFree", toMB(mi.availMem)); 78 | info.putDouble("systemUsed", toMB(mi.totalMem - mi.availMem)); 79 | return info; 80 | } 81 | 82 | @Override 83 | public void onTrimMemory(int level) { 84 | ReactApplicationContext context = getReactApplicationContext(); 85 | if (context.hasActiveCatalystInstance()) { 86 | WritableMap memoryInfo = getMemoryInfo(); 87 | memoryInfo.putInt("memoryLevel", level); 88 | context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(LOW_MEMORY, memoryInfo); 89 | } 90 | } 91 | 92 | @Override 93 | public void onLowMemory() { 94 | // no-op 95 | } 96 | 97 | @Override 98 | public void initialize() { 99 | getReactApplicationContext().addLifecycleEventListener(this); 100 | getReactApplicationContext().registerComponentCallbacks(this); 101 | } 102 | 103 | @Override 104 | public void onHostResume() { 105 | getReactApplicationContext().registerComponentCallbacks(this); 106 | } 107 | 108 | @Override 109 | public void onHostPause() { 110 | getReactApplicationContext().unregisterComponentCallbacks(this); 111 | } 112 | 113 | @Override 114 | public void onHostDestroy() { 115 | getReactApplicationContext().unregisterComponentCallbacks(this); 116 | getReactApplicationContext().removeLifecycleEventListener(this); 117 | } 118 | 119 | @Override 120 | public void onConfigurationChanged(Configuration newConfig) { 121 | // no-op 122 | } 123 | 124 | @ReactMethod 125 | public void getStorage(Promise promise) { 126 | File path = Environment.getDataDirectory(); 127 | StatFs stat = new StatFs(path.getPath()); 128 | 129 | long totalSpace; 130 | long freeSpace; 131 | 132 | if (Build.VERSION.SDK_INT >= 18) { 133 | totalSpace = stat.getTotalBytes(); 134 | freeSpace = stat.getFreeBytes(); 135 | } else { 136 | long blockSize = stat.getBlockSize(); 137 | totalSpace = blockSize * stat.getBlockCount(); 138 | freeSpace = blockSize * stat.getAvailableBlocks(); 139 | } 140 | 141 | WritableMap info = Arguments.createMap(); 142 | info.putDouble("total", toMB(totalSpace)); 143 | info.putDouble("free", toMB(freeSpace)); 144 | long usedSpace = totalSpace - freeSpace; 145 | info.putDouble("used", toMB(usedSpace)); 146 | 147 | promise.resolve(info); 148 | } 149 | 150 | @ReactMethod 151 | public void getMemory(Promise promise) { 152 | promise.resolve(getMemoryInfo()); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /android/src/main/java/com/robinpowered/react/vitals/RNVitalsPackage.java: -------------------------------------------------------------------------------- 1 | package com.robinpowered.react.vitals; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collections; 5 | import java.util.List; 6 | 7 | import com.facebook.react.ReactPackage; 8 | import com.facebook.react.bridge.NativeModule; 9 | import com.facebook.react.bridge.ReactApplicationContext; 10 | import com.facebook.react.uimanager.ViewManager; 11 | import com.facebook.react.bridge.JavaScriptModule; 12 | public class RNVitalsPackage implements ReactPackage { 13 | @Override 14 | public List createNativeModules(ReactApplicationContext reactContext) { 15 | return Arrays.asList(new RNVitalsModule(reactContext)); 16 | } 17 | 18 | // Deprecated from RN 0.47 19 | public List> createJSModules() { 20 | return Collections.emptyList(); 21 | } 22 | 23 | @Override 24 | public List createViewManagers(ReactApplicationContext reactContext) { 25 | return Collections.emptyList(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /entry.android.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import Vitals from './vitals'; 4 | import {DeviceEventEmitter} from 'react-native'; 5 | 6 | export default { 7 | ...Vitals, 8 | // Android overrides 9 | addLowMemoryListener(callback) { 10 | const wrappedCallback = memoryInfo => { 11 | if (memoryInfo.memoryLevel === Vitals.MemoryLevel.CRITICAL) { 12 | callback(memoryInfo); 13 | } 14 | }; 15 | 16 | return DeviceEventEmitter.addListener( 17 | Vitals.LOW_MEMORY, 18 | wrappedCallback 19 | ); 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /entry.ios.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | export {default} from './vitals'; 4 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | export {default} from './entry'; 4 | -------------------------------------------------------------------------------- /ios/RNVitals.h: -------------------------------------------------------------------------------- 1 | #if __has_include() 2 | #import 3 | #elif __has_include("RCTBridgeModule.h") 4 | #import "RCTBridgeModule.h" 5 | #else 6 | #import "React/RCTBridgeModule.h" 7 | #endif 8 | 9 | @interface RNVitals : NSObject 10 | @end 11 | -------------------------------------------------------------------------------- /ios/RNVitals.m: -------------------------------------------------------------------------------- 1 | 2 | #import "RNVitals.h" 3 | #import "SSMemoryInfo.h" 4 | #import 5 | #import 6 | 7 | // Used to send events to JS 8 | #if __has_include() 9 | #import 10 | #import 11 | #elif __has_include("RCTBridge.h") 12 | #import "RCTBridge.h" 13 | #import "RCTEventDispatcher.h" 14 | #else 15 | #import "React/RCTBridge.h" 16 | #import "React/RCTEventDispatcher.h" 17 | #endif 18 | 19 | @implementation RNVitals 20 | 21 | @synthesize bridge = _bridge; 22 | 23 | static NSString * const LOW_MEMORY = @"LOW_MEMORY"; 24 | 25 | - (instancetype)init 26 | { 27 | if ((self = [super init])) { 28 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; 29 | } 30 | 31 | return self; 32 | 33 | } 34 | 35 | - (void)dealloc 36 | { 37 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 38 | } 39 | 40 | + (BOOL)requiresMainQueueSetup 41 | { 42 | return YES; 43 | } 44 | 45 | + (NSDictionary *)getMemoryInfo 46 | { 47 | struct mach_task_basic_info info; 48 | mach_msg_type_number_t size = sizeof(info); 49 | kern_return_t kerr = task_info(mach_task_self(), 50 | MACH_TASK_BASIC_INFO, 51 | (task_info_t)&info, 52 | &size); 53 | 54 | if (kerr != KERN_SUCCESS) { 55 | return nil; 56 | } 57 | 58 | double appUsed = (double) info.resident_size / 1024 / 1024; 59 | 60 | return @{ 61 | @"systemTotal": @([SSMemoryInfo totalMemory]), 62 | @"appUsed": @(appUsed), 63 | @"systemUsed": @([SSMemoryInfo usedMemory:NO]), 64 | @"systemFree": @([SSMemoryInfo freeMemory:NO]), 65 | @"systemActive": @([SSMemoryInfo activeMemory:NO]), 66 | @"systemInactive": @([SSMemoryInfo inactiveMemory:NO]), 67 | @"systemWired": @([SSMemoryInfo wiredMemory:NO]), 68 | @"systemPurgable": @([SSMemoryInfo purgableMemory:NO]) 69 | }; 70 | } 71 | 72 | - (void)applicationDidReceiveMemoryWarning:(NSNotification *)notification 73 | { 74 | NSDictionary *memoryInfo = [RNVitals getMemoryInfo]; 75 | [_bridge.eventDispatcher sendDeviceEventWithName:LOW_MEMORY 76 | body:memoryInfo]; 77 | } 78 | 79 | RCT_EXPORT_MODULE() 80 | 81 | - (NSDictionary *)constantsToExport 82 | { 83 | return @{ @"LOW_MEMORY": LOW_MEMORY }; 84 | } 85 | 86 | RCT_EXPORT_METHOD(getStorage:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) 87 | { 88 | unsigned long long totalSpace = 0; 89 | unsigned long long totalFreeSpace = 0; 90 | 91 | __autoreleasing NSError *error = nil; 92 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 93 | NSDictionary *dictionary = [[NSFileManager defaultManager] attributesOfFileSystemForPath:[paths lastObject] error:&error]; 94 | 95 | if (dictionary) { 96 | NSNumber *fileSystemSizeInBytes = [dictionary objectForKey: NSFileSystemSize]; 97 | NSNumber *freeFileSystemSizeInBytes = [dictionary objectForKey:NSFileSystemFreeSize]; 98 | totalSpace = [fileSystemSizeInBytes unsignedLongLongValue]; 99 | totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue]; 100 | double used = (double) totalSpace - totalFreeSpace; 101 | resolve(@{ 102 | @"total": @((double) totalSpace / 1024 / 1024), 103 | @"free": @((double) totalFreeSpace / 1024 / 1024), 104 | @"used": @(used / 1024 / 1024) 105 | }); 106 | } else { 107 | reject(@"not-support", @"An error happened", nil); 108 | } 109 | } 110 | 111 | RCT_EXPORT_METHOD(getMemory:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) 112 | { 113 | NSDictionary *memoryInfo = [RNVitals getMemoryInfo]; 114 | if (memoryInfo == nil) { 115 | reject(@"not-support", @"An error happened", nil); 116 | } else { 117 | resolve(memoryInfo); 118 | } 119 | 120 | } 121 | 122 | @end 123 | -------------------------------------------------------------------------------- /ios/RNVitals.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 909820951FCDB62700A7617D /* SSMemoryInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 909820931FCDB62700A7617D /* SSMemoryInfo.m */; }; 11 | B3E7B58A1CC2AC0600A0062D /* RNVitals.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNVitals.m */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXCopyFilesBuildPhase section */ 15 | 58B511D91A9E6C8500147676 /* CopyFiles */ = { 16 | isa = PBXCopyFilesBuildPhase; 17 | buildActionMask = 2147483647; 18 | dstPath = "include/$(PRODUCT_NAME)"; 19 | dstSubfolderSpec = 16; 20 | files = ( 21 | ); 22 | runOnlyForDeploymentPostprocessing = 0; 23 | }; 24 | /* End PBXCopyFilesBuildPhase section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 134814201AA4EA6300B7C361 /* libRNVitals.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNVitals.a; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | 909820931FCDB62700A7617D /* SSMemoryInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSMemoryInfo.m; sourceTree = ""; }; 29 | 909820941FCDB62700A7617D /* SSMemoryInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SSMemoryInfo.h; sourceTree = ""; }; 30 | B3E7B5881CC2AC0600A0062D /* RNVitals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNVitals.h; sourceTree = ""; }; 31 | B3E7B5891CC2AC0600A0062D /* RNVitals.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNVitals.m; sourceTree = ""; }; 32 | /* End PBXFileReference section */ 33 | 34 | /* Begin PBXFrameworksBuildPhase section */ 35 | 58B511D81A9E6C8500147676 /* Frameworks */ = { 36 | isa = PBXFrameworksBuildPhase; 37 | buildActionMask = 2147483647; 38 | files = ( 39 | ); 40 | runOnlyForDeploymentPostprocessing = 0; 41 | }; 42 | /* End PBXFrameworksBuildPhase section */ 43 | 44 | /* Begin PBXGroup section */ 45 | 134814211AA4EA7D00B7C361 /* Products */ = { 46 | isa = PBXGroup; 47 | children = ( 48 | 134814201AA4EA6300B7C361 /* libRNVitals.a */, 49 | ); 50 | name = Products; 51 | sourceTree = ""; 52 | }; 53 | 58B511D21A9E6C8500147676 = { 54 | isa = PBXGroup; 55 | children = ( 56 | B3E7B5881CC2AC0600A0062D /* RNVitals.h */, 57 | 909820941FCDB62700A7617D /* SSMemoryInfo.h */, 58 | 909820931FCDB62700A7617D /* SSMemoryInfo.m */, 59 | B3E7B5891CC2AC0600A0062D /* RNVitals.m */, 60 | 134814211AA4EA7D00B7C361 /* Products */, 61 | ); 62 | sourceTree = ""; 63 | }; 64 | /* End PBXGroup section */ 65 | 66 | /* Begin PBXNativeTarget section */ 67 | 58B511DA1A9E6C8500147676 /* RNVitals */ = { 68 | isa = PBXNativeTarget; 69 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNVitals" */; 70 | buildPhases = ( 71 | 58B511D71A9E6C8500147676 /* Sources */, 72 | 58B511D81A9E6C8500147676 /* Frameworks */, 73 | 58B511D91A9E6C8500147676 /* CopyFiles */, 74 | ); 75 | buildRules = ( 76 | ); 77 | dependencies = ( 78 | ); 79 | name = RNVitals; 80 | productName = RCTDataManager; 81 | productReference = 134814201AA4EA6300B7C361 /* libRNVitals.a */; 82 | productType = "com.apple.product-type.library.static"; 83 | }; 84 | /* End PBXNativeTarget section */ 85 | 86 | /* Begin PBXProject section */ 87 | 58B511D31A9E6C8500147676 /* Project object */ = { 88 | isa = PBXProject; 89 | attributes = { 90 | LastUpgradeCheck = 0830; 91 | ORGANIZATIONNAME = Facebook; 92 | TargetAttributes = { 93 | 58B511DA1A9E6C8500147676 = { 94 | CreatedOnToolsVersion = 6.1.1; 95 | }; 96 | }; 97 | }; 98 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNVitals" */; 99 | compatibilityVersion = "Xcode 3.2"; 100 | developmentRegion = English; 101 | hasScannedForEncodings = 0; 102 | knownRegions = ( 103 | en, 104 | ); 105 | mainGroup = 58B511D21A9E6C8500147676; 106 | productRefGroup = 58B511D21A9E6C8500147676; 107 | projectDirPath = ""; 108 | projectRoot = ""; 109 | targets = ( 110 | 58B511DA1A9E6C8500147676 /* RNVitals */, 111 | ); 112 | }; 113 | /* End PBXProject section */ 114 | 115 | /* Begin PBXSourcesBuildPhase section */ 116 | 58B511D71A9E6C8500147676 /* Sources */ = { 117 | isa = PBXSourcesBuildPhase; 118 | buildActionMask = 2147483647; 119 | files = ( 120 | 909820951FCDB62700A7617D /* SSMemoryInfo.m in Sources */, 121 | B3E7B58A1CC2AC0600A0062D /* RNVitals.m in Sources */, 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXSourcesBuildPhase section */ 126 | 127 | /* Begin XCBuildConfiguration section */ 128 | 58B511ED1A9E6C8500147676 /* Debug */ = { 129 | isa = XCBuildConfiguration; 130 | buildSettings = { 131 | ALWAYS_SEARCH_USER_PATHS = NO; 132 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 133 | CLANG_CXX_LIBRARY = "libc++"; 134 | CLANG_ENABLE_MODULES = YES; 135 | CLANG_ENABLE_OBJC_ARC = YES; 136 | CLANG_WARN_BOOL_CONVERSION = YES; 137 | CLANG_WARN_CONSTANT_CONVERSION = YES; 138 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 139 | CLANG_WARN_EMPTY_BODY = YES; 140 | CLANG_WARN_ENUM_CONVERSION = YES; 141 | CLANG_WARN_INFINITE_RECURSION = YES; 142 | CLANG_WARN_INT_CONVERSION = YES; 143 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 144 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 145 | CLANG_WARN_UNREACHABLE_CODE = YES; 146 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 147 | COPY_PHASE_STRIP = NO; 148 | ENABLE_STRICT_OBJC_MSGSEND = YES; 149 | ENABLE_TESTABILITY = YES; 150 | GCC_C_LANGUAGE_STANDARD = gnu99; 151 | GCC_DYNAMIC_NO_PIC = NO; 152 | GCC_NO_COMMON_BLOCKS = YES; 153 | GCC_OPTIMIZATION_LEVEL = 0; 154 | GCC_PREPROCESSOR_DEFINITIONS = ( 155 | "DEBUG=1", 156 | "$(inherited)", 157 | ); 158 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 159 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 160 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 161 | GCC_WARN_UNDECLARED_SELECTOR = YES; 162 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 163 | GCC_WARN_UNUSED_FUNCTION = YES; 164 | GCC_WARN_UNUSED_VARIABLE = YES; 165 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 166 | MTL_ENABLE_DEBUG_INFO = YES; 167 | ONLY_ACTIVE_ARCH = YES; 168 | SDKROOT = iphoneos; 169 | }; 170 | name = Debug; 171 | }; 172 | 58B511EE1A9E6C8500147676 /* Release */ = { 173 | isa = XCBuildConfiguration; 174 | buildSettings = { 175 | ALWAYS_SEARCH_USER_PATHS = NO; 176 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 177 | CLANG_CXX_LIBRARY = "libc++"; 178 | CLANG_ENABLE_MODULES = YES; 179 | CLANG_ENABLE_OBJC_ARC = YES; 180 | CLANG_WARN_BOOL_CONVERSION = YES; 181 | CLANG_WARN_CONSTANT_CONVERSION = YES; 182 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 183 | CLANG_WARN_EMPTY_BODY = YES; 184 | CLANG_WARN_ENUM_CONVERSION = YES; 185 | CLANG_WARN_INFINITE_RECURSION = YES; 186 | CLANG_WARN_INT_CONVERSION = YES; 187 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 188 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 189 | CLANG_WARN_UNREACHABLE_CODE = YES; 190 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 191 | COPY_PHASE_STRIP = YES; 192 | ENABLE_NS_ASSERTIONS = NO; 193 | ENABLE_STRICT_OBJC_MSGSEND = YES; 194 | GCC_C_LANGUAGE_STANDARD = gnu99; 195 | GCC_NO_COMMON_BLOCKS = YES; 196 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 197 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 198 | GCC_WARN_UNDECLARED_SELECTOR = YES; 199 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 200 | GCC_WARN_UNUSED_FUNCTION = YES; 201 | GCC_WARN_UNUSED_VARIABLE = YES; 202 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 203 | MTL_ENABLE_DEBUG_INFO = NO; 204 | SDKROOT = iphoneos; 205 | VALIDATE_PRODUCT = YES; 206 | }; 207 | name = Release; 208 | }; 209 | 58B511F01A9E6C8500147676 /* Debug */ = { 210 | isa = XCBuildConfiguration; 211 | buildSettings = { 212 | HEADER_SEARCH_PATHS = ( 213 | "$(inherited)", 214 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 215 | "$(SRCROOT)/../../../React/**", 216 | "$(SRCROOT)/../../react-native/React/**", 217 | ); 218 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 219 | OTHER_LDFLAGS = "-ObjC"; 220 | PRODUCT_NAME = RNVitals; 221 | SKIP_INSTALL = YES; 222 | }; 223 | name = Debug; 224 | }; 225 | 58B511F11A9E6C8500147676 /* Release */ = { 226 | isa = XCBuildConfiguration; 227 | buildSettings = { 228 | HEADER_SEARCH_PATHS = ( 229 | "$(inherited)", 230 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 231 | "$(SRCROOT)/../../../React/**", 232 | "$(SRCROOT)/../../react-native/React/**", 233 | ); 234 | LIBRARY_SEARCH_PATHS = "$(inherited)"; 235 | OTHER_LDFLAGS = "-ObjC"; 236 | PRODUCT_NAME = RNVitals; 237 | SKIP_INSTALL = YES; 238 | }; 239 | name = Release; 240 | }; 241 | /* End XCBuildConfiguration section */ 242 | 243 | /* Begin XCConfigurationList section */ 244 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNVitals" */ = { 245 | isa = XCConfigurationList; 246 | buildConfigurations = ( 247 | 58B511ED1A9E6C8500147676 /* Debug */, 248 | 58B511EE1A9E6C8500147676 /* Release */, 249 | ); 250 | defaultConfigurationIsVisible = 0; 251 | defaultConfigurationName = Release; 252 | }; 253 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNVitals" */ = { 254 | isa = XCConfigurationList; 255 | buildConfigurations = ( 256 | 58B511F01A9E6C8500147676 /* Debug */, 257 | 58B511F11A9E6C8500147676 /* Release */, 258 | ); 259 | defaultConfigurationIsVisible = 0; 260 | defaultConfigurationName = Release; 261 | }; 262 | /* End XCConfigurationList section */ 263 | }; 264 | rootObject = 58B511D31A9E6C8500147676 /* Project object */; 265 | } 266 | -------------------------------------------------------------------------------- /ios/SSMemoryInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // SSMemoryInfo.h 3 | // SystemServicesDemo 4 | // 5 | // Created by Shmoopi LLC on 9/19/12. 6 | // Copyright (c) 2012 Shmoopi LLC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SSMemoryInfo : NSObject 12 | 13 | // Memory Information 14 | 15 | // Total Memory 16 | + (double)totalMemory; 17 | 18 | // Free Memory 19 | + (double)freeMemory:(BOOL)inPercent; 20 | 21 | // Used Memory 22 | + (double)usedMemory:(BOOL)inPercent; 23 | 24 | // Active Memory 25 | + (double)activeMemory:(BOOL)inPercent; 26 | 27 | // Inactive Memory 28 | + (double)inactiveMemory:(BOOL)inPercent; 29 | 30 | // Wired Memory 31 | + (double)wiredMemory:(BOOL)inPercent; 32 | 33 | // Purgable Memory 34 | + (double)purgableMemory:(BOOL)inPercent; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /ios/SSMemoryInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // SSMemoryInfo.m 3 | // SystemServicesDemo 4 | // 5 | // Created by Shmoopi LLC on 9/19/12. 6 | // Copyright (c) 2012 Shmoopi LLC. All rights reserved. 7 | // 8 | 9 | #import "SSMemoryInfo.h" 10 | 11 | // stat 12 | #import 13 | 14 | // mach 15 | #import 16 | 17 | @implementation SSMemoryInfo 18 | 19 | // Total Memory 20 | + (double)totalMemory { 21 | // Find the total amount of memory 22 | @try { 23 | // Set up the variables 24 | double totalMemory = 0.00; 25 | double allMemory = [[NSProcessInfo processInfo] physicalMemory]; 26 | 27 | // Total Memory (formatted) 28 | totalMemory = (allMemory / 1024.0) / 1024.0; 29 | 30 | // Round to the nearest multiple of 256mb - Almost all RAM is a multiple of 256mb (I do believe) 31 | int toNearest = 256; 32 | int remainder = (int)totalMemory % toNearest; 33 | 34 | if (remainder >= toNearest / 2) { 35 | // Round the final number up 36 | totalMemory = ((int)totalMemory - remainder) + 256; 37 | } else { 38 | // Round the final number down 39 | totalMemory = (int)totalMemory - remainder; 40 | } 41 | 42 | // Check to make sure it's valid 43 | if (totalMemory <= 0) { 44 | // Error, invalid memory value 45 | return -1; 46 | } 47 | 48 | // Completed Successfully 49 | return totalMemory; 50 | } 51 | @catch (NSException *exception) { 52 | // Error 53 | return -1; 54 | } 55 | } 56 | 57 | // Free Memory 58 | + (double)freeMemory:(BOOL)inPercent { 59 | // Find the total amount of free memory 60 | @try { 61 | // Set up the variables 62 | double totalMemory = 0.00; 63 | vm_statistics_data_t vmStats; 64 | mach_msg_type_number_t infoCount = HOST_VM_INFO_COUNT; 65 | kern_return_t kernReturn = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmStats, &infoCount); 66 | 67 | if(kernReturn != KERN_SUCCESS) { 68 | return -1; 69 | } 70 | 71 | // Check if the user wants it in percent 72 | if (inPercent) { 73 | // Percent 74 | // Convert to doubles 75 | double fm = [self totalMemory]; 76 | double am = ((vm_page_size * vmStats.free_count) / 1024.0) / 1024.0; 77 | // Get the percent 78 | totalMemory = (am * 100) / fm; 79 | } else { 80 | // Not in percent 81 | // Total Memory (formatted) 82 | totalMemory = ((vm_page_size * vmStats.free_count) / 1024.0) / 1024.0; 83 | } 84 | 85 | // Check to make sure it's valid 86 | if (totalMemory <= 0) { 87 | // Error, invalid memory value 88 | return -1; 89 | } 90 | 91 | // Completed Successfully 92 | return totalMemory; 93 | } 94 | @catch (NSException *exception) { 95 | // Error 96 | return -1; 97 | } 98 | } 99 | 100 | // Used Memory 101 | + (double)usedMemory:(BOOL)inPercent { 102 | // Find the total amount of used memory 103 | @try { 104 | // Set up the variables 105 | double totalUsedMemory = 0.00; 106 | mach_port_t host_port; 107 | mach_msg_type_number_t host_size; 108 | vm_size_t pagesize; 109 | 110 | // Get the variable values 111 | host_port = mach_host_self(); 112 | host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); 113 | host_page_size(host_port, &pagesize); 114 | 115 | vm_statistics_data_t vm_stat; 116 | 117 | // Check for any system errors 118 | if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) { 119 | // Error, failed to get Virtual memory info 120 | return -1; 121 | } 122 | 123 | // Memory statistics in bytes 124 | natural_t usedMemory = (natural_t)((vm_stat.active_count + 125 | vm_stat.inactive_count + 126 | vm_stat.wire_count) * pagesize); 127 | natural_t allMemory = [self totalMemory]; 128 | 129 | // Check if the user wants it in percent 130 | if (inPercent) { 131 | // Percent 132 | // Convert to doubles 133 | double um = (usedMemory /1024) / 1024; 134 | double am = allMemory; 135 | // Get the percent 136 | totalUsedMemory = (um * 100) / am; 137 | } else { 138 | // Not in percent 139 | // Total Used Memory (formatted) 140 | totalUsedMemory = (usedMemory / 1024.0) / 1024.0; 141 | } 142 | 143 | // Check to make sure it's valid 144 | if (totalUsedMemory <= 0) { 145 | // Error, invalid memory value 146 | return -1; 147 | } 148 | 149 | // Completed Successfully 150 | return totalUsedMemory; 151 | } 152 | @catch (NSException *exception) { 153 | // Error 154 | return -1; 155 | } 156 | } 157 | 158 | // Active Memory 159 | + (double)activeMemory:(BOOL)inPercent { 160 | // Find the Active memory 161 | @try { 162 | // Set up the variables 163 | double totalMemory = 0.00; 164 | mach_port_t host_port; 165 | mach_msg_type_number_t host_size; 166 | vm_size_t pagesize; 167 | 168 | // Get the variable values 169 | host_port = mach_host_self(); 170 | host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); 171 | host_page_size(host_port, &pagesize); 172 | 173 | vm_statistics_data_t vm_stat; 174 | 175 | // Check for any system errors 176 | if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) { 177 | // Error, failed to get Virtual memory info 178 | return -1; 179 | } 180 | 181 | // Check if the user wants it in percent 182 | if (inPercent) { 183 | // Percent 184 | // Convert to doubles 185 | double FM = [self totalMemory]; 186 | double AM = ((vm_stat.active_count * pagesize) / 1024.0) / 1024.0; 187 | // Get the percent 188 | totalMemory = (AM * 100) / FM; 189 | } else { 190 | // Not in percent 191 | // Total Memory (formatted) 192 | totalMemory = ((vm_stat.active_count * pagesize) / 1024.0) / 1024.0; 193 | } 194 | 195 | // Check to make sure it's valid 196 | if (totalMemory <= 0) { 197 | // Error, invalid memory value 198 | return -1; 199 | } 200 | 201 | // Completed Successfully 202 | return totalMemory; 203 | } 204 | @catch (NSException *exception) { 205 | // Error 206 | return -1; 207 | } 208 | } 209 | 210 | // Inactive Memory 211 | + (double)inactiveMemory:(BOOL)inPercent { 212 | // Find the Inactive memory 213 | @try { 214 | // Set up the variables 215 | double totalMemory = 0.00; 216 | mach_port_t host_port; 217 | mach_msg_type_number_t host_size; 218 | vm_size_t pagesize; 219 | 220 | // Get the variable values 221 | host_port = mach_host_self(); 222 | host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); 223 | host_page_size(host_port, &pagesize); 224 | 225 | vm_statistics_data_t vm_stat; 226 | 227 | // Check for any system errors 228 | if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) { 229 | // Error, failed to get Virtual memory info 230 | return -1; 231 | } 232 | 233 | // Check if the user wants it in percent 234 | if (inPercent) { 235 | // Percent 236 | // Convert to doubles 237 | double FM = [self totalMemory]; 238 | double AM = ((vm_stat.inactive_count * pagesize) / 1024.0) / 1024.0; 239 | // Get the percent 240 | totalMemory = (AM * 100) / FM; 241 | } else { 242 | // Not in percent 243 | // Total Memory (formatted) 244 | totalMemory = ((vm_stat.inactive_count * pagesize) / 1024.0) / 1024.0; 245 | } 246 | 247 | // Check to make sure it's valid 248 | if (totalMemory <= 0) { 249 | // Error, invalid memory value 250 | return -1; 251 | } 252 | 253 | // Completed Successfully 254 | return totalMemory; 255 | } 256 | @catch (NSException *exception) { 257 | // Error 258 | return -1; 259 | } 260 | } 261 | 262 | // Wired Memory 263 | + (double)wiredMemory:(BOOL)inPercent { 264 | // Find the Wired memory 265 | @try { 266 | // Set up the variables 267 | double totalMemory = 0.00; 268 | mach_port_t host_port; 269 | mach_msg_type_number_t host_size; 270 | vm_size_t pagesize; 271 | 272 | // Get the variable values 273 | host_port = mach_host_self(); 274 | host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); 275 | host_page_size(host_port, &pagesize); 276 | 277 | vm_statistics_data_t vm_stat; 278 | 279 | // Check for any system errors 280 | if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) { 281 | // Error, failed to get Virtual memory info 282 | return -1; 283 | } 284 | 285 | // Check if the user wants it in percent 286 | if (inPercent) { 287 | // Percent 288 | // Convert to doubles 289 | double FM = [self totalMemory]; 290 | double AM = ((vm_stat.wire_count * pagesize) / 1024.0) / 1024.0; 291 | // Get the percent 292 | totalMemory = (AM * 100) / FM; 293 | } else { 294 | // Not in percent 295 | // Total Memory (formatted) 296 | totalMemory = ((vm_stat.wire_count * pagesize) / 1024.0) / 1024.0; 297 | } 298 | 299 | // Check to make sure it's valid 300 | if (totalMemory <= 0) { 301 | // Error, invalid memory value 302 | return -1; 303 | } 304 | 305 | // Completed Successfully 306 | return totalMemory; 307 | } 308 | @catch (NSException *exception) { 309 | // Error 310 | return -1; 311 | } 312 | } 313 | 314 | // Purgable Memory 315 | + (double)purgableMemory:(BOOL)inPercent { 316 | // Find the Purgable memory 317 | @try { 318 | // Set up the variables 319 | double totalMemory = 0.00; 320 | mach_port_t host_port; 321 | mach_msg_type_number_t host_size; 322 | vm_size_t pagesize; 323 | 324 | // Get the variable values 325 | host_port = mach_host_self(); 326 | host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); 327 | host_page_size(host_port, &pagesize); 328 | 329 | vm_statistics_data_t vm_stat; 330 | 331 | // Check for any system errors 332 | if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS) { 333 | // Error, failed to get Virtual memory info 334 | return -1; 335 | } 336 | 337 | // Check if the user wants it in percent 338 | if (inPercent) { 339 | // Percent 340 | // Convert to doubles 341 | double fm = [self totalMemory]; 342 | double am = ((vm_stat.purgeable_count * pagesize) / 1024.0) / 1024.0; 343 | // Get the percent 344 | totalMemory = (am * 100) / fm; 345 | } else { 346 | // Not in percent 347 | // Total Memory (formatted) 348 | totalMemory = ((vm_stat.purgeable_count * pagesize) / 1024.0) / 1024.0; 349 | } 350 | 351 | // Check to make sure it's valid 352 | if (totalMemory <= 0) { 353 | // Error, invalid memory value 354 | return -1; 355 | } 356 | 357 | // Completed Successfully 358 | return totalMemory; 359 | } 360 | @catch (NSException *exception) { 361 | // Error 362 | return -1; 363 | } 364 | } 365 | 366 | @end 367 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-vitals", 3 | "version": "2.0.0", 4 | "description": "Memory and resource information Native Module for React Native", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "react-native", 11 | "memory", 12 | "storage" 13 | ], 14 | "author": { 15 | "name" : "Robin Powered", 16 | "email" : "engineering@robinpowered.com", 17 | "url" : "https://robinpowered.com" 18 | }, 19 | "license": "MIT", 20 | "homepage": "https://github.com/robinpowered/react-native-vitals", 21 | "repository": { 22 | "type" : "git", 23 | "url" : "https://github.com/robinpowered/react-native-vitals.git" 24 | }, 25 | "devDependencies": { 26 | "react-native": ">=0.27" 27 | }, 28 | "peerDependencies": { 29 | "react-native": ">=0.27" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /react-native-vitals.podspec: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) 4 | 5 | Pod::Spec.new do |s| 6 | s.name = package['name'] 7 | s.version = package['version'] 8 | s.summary = package['description'] 9 | s.license = package['license'] 10 | s.homepage = package['homepage'] 11 | s.author = { package['author']['name'] => package['author']['email'] } 12 | s.source = { :git => package['repository']['url'], :tag => "v#{s.version}" } 13 | s.source_files = 'ios/*.{h,m}' 14 | s.platform = :ios, '8.0' 15 | 16 | s.dependency 'React' 17 | end 18 | -------------------------------------------------------------------------------- /vitals.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import { 4 | DeviceEventEmitter, 5 | NativeModules 6 | } from 'react-native'; 7 | 8 | const {RNVitals} = NativeModules; 9 | 10 | export default { 11 | ...RNVitals, 12 | addLowMemoryListener (callback) { 13 | return DeviceEventEmitter.addListener( 14 | RNVitals.LOW_MEMORY, 15 | callback 16 | ); 17 | } 18 | }; 19 | --------------------------------------------------------------------------------